颜色
raft-ui 的颜色分三层。组件从不直接写某个颜色值:它只说自己要什么用途的颜色,比如“主按钮的填充色”或“错误文字”,具体是哪个颜色由主题决定。
| 层 | 命名 | 存什么 |
|---|---|---|
| 色板 | --r-palette-{hue}-{1..12} | Raft 品牌色相的 12 级色阶 |
| 别名 | --rw-alias-{property}-{state}-{role} | 颜色的用途;指向色板里的某一级 |
| 组件 | --rl-{component}-* | 组件自己的插槽;只读别名 |
色板
每个色相有 12 级,每一级在所有色相里的用途都相同,第 9 级就是品牌色本身。亮色色阶由 Brutal 和 Elegant light 共用;Elegant dark 换成暗色色阶,每一级的用途不变,所以所有别名都会自动跟着模式走。切换页面顶部的主题就能看到。
contrast 是第 9 级实心填充上的文字颜色:同色系的深色,不用纯黑。
每一级用来做什么
参照 Radix Colors。
| 级 | 用途 | 别名 |
|---|---|---|
| 1–2 | 页面底色、次级区域底色 | bg-page、bg-panel(中性色) |
| 3 / 4 / 5 | 组件底色:常态、悬停、按下 | surface、surface-hover、surface-pressed |
| 6 / 7 / 8 | 边框:弱、常态、悬停 | border-subtle、border、border-hover |
| 9 / 10 | 实心填充:常态、悬停 | fill、fill-hover |
| 11 | 白底或 1–5 级底上的彩色文字 | text |
| 12 | 同色系的高对比文字 | text-strong |
| contrast | 实心填充上的文字 | text-on-fill |
两条规则保证文字可读:
- 彩色底上的字用同一色系的深色。 黄色底配深橄榄棕,青色底配深青色。彩色底上用纯黑或灰色文字会显得脏。
- 浅色底上的彩色字用第 11 级。 它是在 1–5 级底上仍能达到 WCAG AA(4.5:1)的最鲜艳的一级。
别名
命名遵循 how-to-style:先写属性,再写状态,角色放最后。组件映射不同类型时只需要改最后一段。
.r-button {
&&--error-type {
--rl-button-family-fill: var(--rw-alias-fill-error);
--rl-button-family-fill-hover: var(--rw-alias-fill-hover-error);
--rl-button-family-text: var(--rw-alias-text-error);
}
}各个角色和它们使用的色相:
| surface3 | surface-hover4 | surface-pressed5 | border-subtle6 | border7 | border-hover8 | fill9 | fill-hover10 | text11 | text-strong12 | text-on-fillcontrast | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| neutralgray | |||||||||||
| primaryyellow | |||||||||||
| accentpink | |||||||||||
| infocyan | |||||||||||
| successlime | |||||||||||
| warningorange | |||||||||||
| errorred |
中性的文字和底色有自己的名字:--rw-alias-bg-page、--rw-alias-bg-panel、--rw-alias-bg-raised(浮在凹陷底色之上的东西,比如分段控制器选中的那一段:浅色模式是白色,深色模式比底色更亮)、--rw-alias-label-primary / -secondary / -tertiary / -disabled、--rw-alias-border-strong(Brutal 的墨色)和 --rw-alias-border-focus。--rw-static-white 和 --rw-static-black 永远不变。
反馈色
状态(info、success、warning、error)在所有组件上都要是同一种说法,所以组件不自己挑颜色,而是读 --rw-feedback-{property}-{role},由每个主题统一决定一次。
状态色单独成一组,不借用上面各角色的品牌色相。错误是 15° 的覆盆子红,警告是 72° 的琥珀色,成功是 153° 的真绿,三者容易分清,也不挤在品牌的暖色带里。只有错误是饱和的;警告和成功收着一些。输入框用中间调;文字用同一色相更深的一级,保证满足 AA 对比度(4.5:1)。深色模式有一组单独调亮的值,一个颜色两处都用。
| Token | Elegant(浅色和深色) | Brutal |
|---|---|---|
--rw-feedback-text-{role} | 状态色,浅色模式下加深到满足 AA;用于提示文字和图标 | 同左 |
--rw-feedback-border-{role} | 状态色 | 状态色,替换墨色描边 |
--rw-feedback-shadow-{role} | 无 | 状态色的硬阴影 |
处于某个状态的输入框整体换成同一个颜色:Elegant 的细线变成状态色,Brutal 的描边和硬阴影一起变成状态色。切换页面顶部的主题对比看。
Input 和 Select 的 status 都读这层 token,之后的表单类组件和提示信息也一样。
对比度
按当前主题实时计算。组件用到的每一对颜色都应该达到 4.5:1。
| pair | neutral | primary | accent | info | success | warning | error |
|---|---|---|---|---|---|---|---|
| 11 on panel | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— |
| 11 on 3 | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— |
| 11 on 5 | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— |
| contrast on 9 | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— |
| contrast on 10 | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— | Aa— |
修改颜色
覆盖色板里的一级,所有指向它的别名都会跟着变,可以作用于整个页面,也可以只在某个 ConfigProvider 里:
<ConfigProvider themeOverrides={{ "--r-palette-yellow-9": "oklch(0.86 0.17 85)" }}>…</ConfigProvider>覆盖某个别名,只改变这一个用途用的颜色,不动色板:
<ConfigProvider themeOverrides={{ "--rw-alias-fill-primary": "var(--r-palette-orange-9)" }}>…</ConfigProvider>