跳到主要内容

颜色

Unif Design 的颜色是 role-based(角色化)token:role 名固定(primary / surface / foreground…),亮 / 暗主题切换时,改的是 role 指向哪个 hex,组件代码不动。值的唯一真相源是 src/theme/colors.ts

取色只走 hook,不要顶层 import

颜色跟随系统亮暗切换,必须在组件内用 useColors() / useTheme().colors 运行期拿。顶层 import { colors } 导出已删除(见迁移 → 令牌迁移)。下方所有色块的 hex 仅供查阅;代码里写 role 名,不写 hex。

取色优先级链

从语义匹配度由高到低,不跳级:

  1. 角色 token —— useColors() 返回的 c.primary / c.surface / c.foreground 等。语义对得上就用它,自动亮 / 暗。
  2. 静态 palettes —— 渐变序列(avatarGradientwarmOrangePalette),塞不进单值 role 的"色组 / 渐变",见间距·圆角·阴影与下文。
  3. 新增 token —— 现有 role 都对不上时,在 colors.tslightColorsdarkColors 同时加同名 key(TS 编译期强制两套键集合对齐,少一个就报错)。

永远不要内联 #EB6E00 / rgba(...) 新硬编码颜色会被 CI 拦下。唯一例外:视觉锁定(QR 白卡、固定商标色),且必须加注释说明锁定理由。

品牌 / Brand

品牌橙 #EB6E00 是 Unif 的核心识别色。亮 / 暗共用同一 hex —— 在 #0A0A0A 暗底上对比度仍过 WCAG AA,brand identity 不随主题变。

primary
#EB6E00
主品牌橙(亮/暗共用)
primaryPressed
#D06200
按下态(亮/暗共用)
primaryContainer
#FFF5EB
亮:高亮选中背景
primaryContainerSubtle
#FFF8F0
亮:Card 选中背景
onPrimary
#FFFFFF
品牌底上的内容色
rolelightdark用途
primary#EB6E00#EB6E00主按钮、用户气泡、活动标签、关键强调
primaryPressed#D06200#D06200按下态
primaryContainer#FFF5EB#3D1F00高亮选中背景
primaryContainerSubtle#FFF8F0#2A1500Card 选中背景
onPrimary#FFFFFF#FFFFFF品牌底上的内容色
onPrimaryMutedrgba(255,255,255,0.85)rgba(255,255,255,0.85)品牌底上的次级文字

品牌渐变(数组,不暴露为 role):avatarGradient = ['#F49443', '#EB6E00'](135°,Me hero 头像;亮 / 暗共用)。平铺橙 #EB6E00 在 90% 场景已足够,不要引入新渐变

语义色 / Semantic

success
#52C41A
成功 / 完成
error
#F4511E
错误 / 销毁(暗:#FF6B40)
info
#3775F6
⚠ 仅用于用户头像(暗:#5A91FF)
rolelightdark用途
success#52C41A#52C41A成功态
successContainer#F0FFF0#0E2810success badge 底
onSuccess#FFFFFF#FFFFFFsuccess 上的内容
error#F4511E#FF6B40错误 / destructive
errorContainer#FFF5F5#2A1010error badge 底
onError#FFFFFF#FFFFFFerror 上的内容
info#3775F6#5A91FF仅用户头像(Tag info variant 历史沿用)
infoContainer#F0F5FF#0F1A33info badge 底
onInfo#FFFFFF#FFFFFFinfo 上的内容
蓝色规则

info(#3775F6)专属于用户头像。除 Tag 的 info variant 历史沿用外,不要在按钮、提示、链接等任何其它地方铺蓝色 —— 这会破坏 user / AI 的视觉区分。详见设计原则 → 橙色克制

表面 / Surface(5 层)

5 层明度阶梯。暗色不靠 shadow 表达深度,靠这 5 层 surface 的明度差(见阴影)。

background
#F5F5F5
整页底(暗:#0A0A0A,OLED 友好)
surface
#FFFFFF
Card / Sheet / 气泡(暗:#1C1C1E)
surfaceContainer
#F5F5F5
卡内输入框 / 次级(暗:#2C2C2E)
surfaceContainerHigh
#F0F0F0
次按钮 / 按下态(暗:#3A3A3C)
surfaceContainerHighest
#E0E0E0
disabled / pill(暗:#48484A)
rolelightdark用途
background#F5F5F5#0A0A0A整页底色(OLED 友好)
surface#FFFFFF#1C1C1ECard / Sheet / 气泡
surfaceContainer#F5F5F5#2C2C2E卡内输入框 / 次级面
surfaceContainerHigh#F0F0F0#3A3A3C次按钮 / 按下态
surfaceContainerHighest#E0E0E0#48484Adisabled 按钮 / pill

前景 / Foreground

foreground
#333333
主文字(暗:#FFFFFF)
foregroundMuted
#666666
次级文字
foregroundSubtle
#999999
三级 / placeholder
rolelightdark用途
foreground#333333#FFFFFF主文字
foregroundMuted#666666rgba(235,235,245,0.6)次级文字
foregroundSubtle#999999rgba(235,235,245,0.3)三级文字 / placeholder
onSurface= foreground= foreground别名(语义同 foreground)
onSurfaceMuted= foregroundMuted= foregroundMuted别名

描边 / Outline

rolelightdark用途
outline#EDEDED#3A3A3C默认 hairline
outlineVariant#E8E8E8#48484A次级 hairline
outlineFaint#F5F5F5rgba(84,84,88,0.65)最弱 hairline

反色 / Inverse · 遮罩 / Scrim

rolelightdark用途
inverseSurface#1C1C1E#FFFFFFtoast / tooltip 反色底
inverseOnSurface#FFFFFF#000000inverseSurface 上的内容
scrimrgba(0,0,0,0.5)rgba(0,0,0,0.7)Sheet 遮罩(暗色加深)
sheetBackdroprgba(245,245,247,0.72)rgba(245,245,247,0.72)合规 sheet 之下的浅 tint(焦点引导,亮 / 暗共用)
玻璃 / 渐变等专用色

colors.ts 另有一批玻璃感(glassTintLight / glassBorder / glassActiveFg…)、Hero 渐变(heroGradient0/1/2)、淡阶图标(iconFaint40/30/25)等专用 role,多数亮 / 暗 alpha 故意不同(逐条注释了原因,不要"归一化")。这些供具体组件内部使用,完整清单与注释见 src/theme/colors.ts

中性色规则

无近黑、无米白、无染色灰。 中性色保持纯净 —— 不要在灰阶里掺品牌橙或其它色相。

在代码中使用

import { StyleSheet } from 'react-native';
import { useColors, useThemedStyles } from '@unif/react-native-design';
import type { ColorTokens } from '@unif/react-native-design';

// makeStyles 必须定义在模块顶层(不要内联进组件,否则打穿 useThemedStyles 缓存)
const makeStyles = (c: ColorTokens) =>
StyleSheet.create({
primary: { backgroundColor: c.primary }, // 亮/暗同:#EB6E00
text: { color: c.foreground }, // 亮:#333333 / 暗:#FFFFFF
border: { borderColor: c.outline }, // 亮:#EDEDED / 暗:#3A3A3C
error: { color: c.error }, // 亮:#F4511E / 暗:#FF6B40
});

function MyView() {
const styles = useThemedStyles(makeStyles);
const c = useColors(); // inline 取色(状态映射 / prop fallback)时用
// ...
}

暗色哲学

  • iOS HIG dark 风格 —— 纯黑 / 近黑 background(#0A0A0A)+ 深灰多层 surface(#1C / #2C / #3A / #48),OLED 友好。
  • 品牌橙保留原值 —— 亮 / 暗均 #EB6E00,brand identity 不变。
  • layered surface 替代 shadow —— 暗色下 shadow token 的 shadowOpacity / elevation 多数置 0,深度靠 surface 5 层明度差(见阴影)。
  • 气泡"内角方"签名完整保留(见设计原则 → 气泡内角方)。

完整 role → hex 对照、迁移 grep 表、为何不引入 reference layer,见完整规范 → Color system