主题Theming
主题不是一份配置对象,而是 <html> 上的三个属性:data-theme、data-accent、data-motion。所有组件的样式都从它们派生;OinkProvider 负责读写,useOink() 负责在组件里拿到当前值和切换方法。
深色与浅色
setTheme 的第二个参数是视口坐标。传了它,新主题会从这一点以圆形揭开(用的是 View Transitions;浏览器不支持、或者开了减弱动效时直接切换)。
theme 是用户选的(可以是 'system'),resolvedTheme 是实际生效的 'light' 或 'dark'。判断“现在是不是深色”用后者。
强调色
五种预设:pink、orange、amber、blue、violet,也可以是任意颜色。柔和底、填充、悬停色、文字色都由 color-mix() 从这一个颜色派生,深浅两套主题各有一组配比。
自定义颜色。setAccent('#3fa7c4') 或 defaultAccent="#3fa7c4":<html> 上是 data-accent="custom",颜色和几个派生变量写在它的行内样式上。强调色上的文字按颜色的感知亮度自动选墨色或白色;当文字用的深一档(浅色主题,对白底至少 4.5:1)和亮一档(深色主题)也自动算出来。工具函数 accentVars(hex)、onAccentColor(hex) 可以单独用。挑颜色可以用 ColorPicker。
局部换色
派生色是在声明 data-accent 的那个元素上求值的,所以可以只给页面的一块换强调色。
动效偏好与 --ok-ms
所有时长令牌都乘了全局倍率 --ok-ms。系统开了“减弱动态效果”,或者 data-motion 为 reduced 时,它变成 0:位移归零,只保留状态切换。
auto:跟随系统设置(默认)。full:即使系统要求减弱,也保留完整动效。只在用户自己明确选择时用。reduced:强制减弱。
自己写的过渡用 var(--ok-dur-*),脚本动画用 animate(),就会自动跟着这个倍率走,不需要单独判断。减弱之后各种动效实际是什么样子,见 动效 · 减弱动效。也可以把 --ok-ms 设成别的数来整体放慢或加快,比如调试时设成 4。
圆角系数
容器的圆角用连续曲率的超椭圆曲线。同样的半径下超椭圆显得更方,所以配了一个半径倍率 --ok-rk 把视觉大小拉回来。
/* 默认:支持 corner-shape 的浏览器自动用超椭圆,并把半径放大 1.45 倍来保持视觉大小 */
@supports (corner-shape: squircle) {
:root { --ok-corner: superellipse(1.75); --ok-rk: 1.45; }
}
/* 想在所有浏览器里都用普通圆角:覆盖回去 */
:root { --ok-corner: round; --ok-rk: 1; }--ok-r-1 到 --ok-r-6 是在 :root 上用 calc(Npx * var(--ok-rk)) 算好的,所以要改倍率得在 :root 上改,写在子元素上不起作用。全圆(--ok-r-full)不受影响,始终是正圆。圆角刻度和同心圆角的规矩见 形状 · 间距 · 层级。
触屏高度
控件高度只有三档:32 / 40 / 48。触屏设备(pointer: coarse)上自动抬到 36 / 44 / 52,保证点按区域不小于 44px,输入框字号同时变成 16px;列表项(--ok-h-item)也抬到 44。各档令牌见“形状 · 间距 · 层级”。
API
OinkProvider
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
defaultTheme | 'light' | 'dark' | 'system' | 'system' | 初始主题。 |
defaultAccent | AccentPreset | '#rrggbb' | 'pink' | 初始强调色:五种预设之一,或任意颜色。 |
defaultMotion | 'auto' | 'full' | 'reduced' | 'auto' | 初始动效偏好。 |
storageKey | string | — | 传了就把三项选择记到 localStorage 的这个键下。 |
locale | 'zh-CN' | 'en-US' | 'zh-CN' | 组件自带文案的语言:aria-label、关闭 / 确认之类的按钮、日历的月份名、占位文字等。 |
tail | ReactNode | ((props: { className: string }) => ReactNode) | — | 全局替换加载器和按钮加载状态里的尾巴图案,等于在最外层包一个 TailProvider。见下面“替换尾巴图案”。 |
locale 只管库组件自带的文案,默认中文;做英文界面时传 locale="en-US"。你自己写的文案仍由应用的国际化方案负责。
useOink() 的返回值
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
theme | ThemeMode | — | 用户选的主题,可能是 system。 |
resolvedTheme | 'light' | 'dark' | — | 实际生效的主题。 |
accent | Accent | — | 当前强调色。 |
motion | MotionMode | — | 当前动效偏好。 |
setTheme | (theme, origin?: { x, y }) => void | — | 切换主题;传 origin(视口坐标)时从该点圆形揭开。 |
setAccent | (accent: Accent) => void | — | 切换强调色。 |
setMotion | (motion: MotionMode) => void | — | 切换动效偏好。 |
替换尾巴图案
品牌尾巴是加载与提示里用的图形:Spinner 的 tail 变体、Button 的加载状态都画它。它是默认值,但可以整体换掉:给 OinkProvider 传 tail,或者用 TailProvider 包住应用,就是全局替换;TailProvider 包住一块就只换那一块,可以嵌套,内层优先。
替换图案约定是一个 viewBox="0 0 48 48" 的 svg。它会拿到和默认尾巴一样的类名 ok-tail,于是:
- 整体的摆动 / 旋转、尺寸、颜色(
currentColor)自动跟上; - 带
pathLength="1"的路径或图形会做描线动效;没有的只做摆动; - 没写
fill/stroke属性的图形默认按尾巴的笔触描线(圆头,线宽 5.5);自己写了的保留。
组件里需要画尾巴时用 <TailGlyph className="ok-tail" />,它会读到最近的 TailProvider;useTail() 返回当前生效的替换图案(默认时为 undefined)。
TailProvider
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
tail | ReactNode | ((props: { className: string }) => ReactNode) | — | 替换的图案。传节点时把 className 合并到它的根元素上并对读屏隐藏;传函数时自己处理。不传时沿用外层设置。 |