Color
颜色
组件只消费按用途命名的语义色。它们在亮暗主题下映射到不同原始色,因此切主题只换值、不换类名。
界面 / 表面
--color-bg亮 gray-50 · 暗 gray-950
--color-surface亮 white · 暗 gray-900
--color-surface-hover亮 gray-100 · 暗 gray-800
--color-track亮 gray-200 · 暗 gray-950
分段控件(Tabs solid / Segmented)的轨道底。定义是一条关系而非某个灰阶:恒比「卡片表面」沉一档,且亮暗两态都保证浮起的药丸更靠近观察者(亮色更亮、暗色也更亮)。别拿「表面悬停」顶替——亮色下它与白只差 3.3% 亮度,暗色下它比药丸还亮,凹凸是反的。
--color-subtle亮 gray-100 · 暗 gray-800
静态区域底:分组容器、看板列、泳道、说明条。与「表面悬停」当前同值但语义不同——常驻底色写 hover: 是语义错位。
--color-muted亮 gray-100 · 暗 gray-800
与「弱背景」同值同义,存在只为与 shadcn/ui 生态对齐(那边 --muted 就是弱背景)。0.28.0 之前这个名字是次要文字色,与生态同名反义,已改名为下方的「次要文字」。
--color-border亮 gray-200 · 暗 gray-800
--color-hairline亮 transparent · 暗 gray-800(同 border)
只用于 border-*:给带阴影的表面(卡片/浮层/按钮)勾轮廓。浅色主题下它就是 transparent——用作 text- / bg- / fill- 会静默隐形(无报错、无回落),填充与文字请改用 border 或 muted-foreground。
文字
--color-foreground亮 gray-900 · 暗 gray-50
--color-muted-foreground亮 gray-600 · 暗 gray-400
说明文案、时间戳、占位、禁用态标签。0.28.0 之前叫 --color-muted。
品牌 / 强调
--color-primary亮 brand-700 · 暗 brand-400
配它的文字色是 -foreground,但那只配这块实心底:亮色下它就是白。自己画浅底(-subtle 或 /12)时按命名直觉写 text-x-foreground 就是白字白底、文字整个看不见,而暗色下反而是对的,谁在暗色主题里开发谁查不出来。浅底的文字色用语义色本身:solid = bg-x + text-x-foreground,soft = bg-x-subtle + text-x,outline = border-x + text-x。
--color-primary-hover亮 brand-500 · 暗 brand-500
语义色的悬停档一律取「亮暗两端之间的那一档」:亮色下变亮、暗色下变暗,两个主题都朝对比更弱的方向走一步。
--color-primary-subtle亮 brand-50 · 暗 surface + 16% brand-400
提示条底、选中行、Tag/Badge 浅底、侧栏当前项高亮。暗色下方向翻转——不是抬亮度,而是把语义色掺进表面色,底仍比表面深沉、只是染上该语义的色相。别自己拿主色 mix() 到白色派生,暗色主题下必错。
--color-primary-border亮 brand-200 · 暗 surface + 34% brand-400
--color-ring亮 brand-500 · 暗 brand-400
状态
--color-danger亮 danger-700 · 暗 danger-400
配它的文字色是 -foreground,但那只配这块实心底:亮色下它就是白。自己画浅底(-subtle 或 /12)时按命名直觉写 text-x-foreground 就是白字白底、文字整个看不见,而暗色下反而是对的,谁在暗色主题里开发谁查不出来。浅底的文字色用语义色本身:solid = bg-x + text-x-foreground,soft = bg-x-subtle + text-x,outline = border-x + text-x。
--color-danger-hover亮 danger-500 · 暗 danger-500
--color-danger-subtle亮 danger-50 · 暗 surface + 16% danger-400
提示条底、选中行、Tag/Badge 浅底、侧栏当前项高亮。暗色下方向翻转——不是抬亮度,而是把语义色掺进表面色,底仍比表面深沉、只是染上该语义的色相。别自己拿主色 mix() 到白色派生,暗色主题下必错。
--color-danger-border亮 danger-200 · 暗 surface + 34% danger-400
--color-success亮 success-700 · 暗 success-500
配它的文字色是 -foreground,但那只配这块实心底:亮色下它就是白。自己画浅底(-subtle 或 /12)时按命名直觉写 text-x-foreground 就是白字白底、文字整个看不见,而暗色下反而是对的,谁在暗色主题里开发谁查不出来。浅底的文字色用语义色本身:solid = bg-x + text-x-foreground,soft = bg-x-subtle + text-x,outline = border-x + text-x。
--color-success-hover亮 success-600 · 暗 success-600
--color-success-subtle亮 success-50 · 暗 surface + 16% success-500
提示条底、选中行、Tag/Badge 浅底、侧栏当前项高亮。暗色下方向翻转——不是抬亮度,而是把语义色掺进表面色,底仍比表面深沉、只是染上该语义的色相。别自己拿主色 mix() 到白色派生,暗色主题下必错。
--color-success-border亮 success-200 · 暗 surface + 34% success-500
--color-warning亮 warning-700 · 暗 warning-500
配它的文字色是 -foreground,但那只配这块实心底:亮色下它就是白。自己画浅底(-subtle 或 /12)时按命名直觉写 text-x-foreground 就是白字白底、文字整个看不见,而暗色下反而是对的,谁在暗色主题里开发谁查不出来。浅底的文字色用语义色本身:solid = bg-x + text-x-foreground,soft = bg-x-subtle + text-x,outline = border-x + text-x。
--color-warning-hover亮 warning-600 · 暗 warning-600
--color-warning-subtle亮 warning-50 · 暗 surface + 16% warning-500
提示条底、选中行、Tag/Badge 浅底、侧栏当前项高亮。暗色下方向翻转——不是抬亮度,而是把语义色掺进表面色,底仍比表面深沉、只是染上该语义的色相。别自己拿主色 mix() 到白色派生,暗色主题下必错。
--color-warning-border亮 warning-200 · 暗 surface + 34% warning-500
--color-info亮 info-700 · 暗 info-400
提示 / 说明 / 中性通知,刻意与主色分开:主色说「这里可以点」,信息色说「这段是说明」。两者同为蓝族但差 30° 色相,借主色当提示色会让页面上最稀缺的注意力资源被说明文案占掉。配它的文字色是 -foreground,但那只配这块实心底:亮色下它就是白。自己画浅底(-subtle 或 /12)时按命名直觉写 text-x-foreground 就是白字白底、文字整个看不见,而暗色下反而是对的,谁在暗色主题里开发谁查不出来。浅底的文字色用语义色本身:solid = bg-x + text-x-foreground,soft = bg-x-subtle + text-x,outline = border-x + text-x。
--color-info-hover亮 info-500 · 暗 info-500
--color-info-subtle亮 info-50 · 暗 surface + 16% info-400
提示条底、选中行、Tag/Badge 浅底、侧栏当前项高亮。暗色下方向翻转——不是抬亮度,而是把语义色掺进表面色,底仍比表面深沉、只是染上该语义的色相。别自己拿主色 mix() 到白色派生,暗色主题下必错。
--color-info-border亮 info-200 · 暗 surface + 34% info-400
图表分类色
数据序列专用,SVG 直接通过 var() 消费;亮暗模式各自调整亮度以保持对比。
语义色阶
50–300 是浅档(提示条底、选中行、Tag 浅底),400–700 是强调档。浅档在 OKLCH 里手工定,不由 mix() 派生——sRGB 插值会带色相偏移,而且各家挑的百分比不同,浅档恰恰是中后台面积最大的那部分颜色。
原始灰阶
底层调色盘位于 primitives.css,明暗共用且不随主题变化;语义色由它派生。