Design Tokens 标准
Design Tokens 是主题作者、框架组件和业务页面之间的共享语言。业务页面不应把颜色、字号、间距、圆角、边框、焦点和状态色散落在局部配置中;应优先使用编译后的 ResolvedTheme 和组件公开参数。
Token 分层
| 层级 | 来源 | 用途 |
|---|---|---|
| Theme authoring | ThemeDefinition |
描述品牌、密度或业务主题相对基础主题的差异。 |
| Resolved semantic token | ResolvedTheme |
runtime 和组件消费的完整颜色、字体、尺寸、动效、高程、编辑器、图表和语法契约。 |
| Internal component recipe | 框架内部 | 把语义 token 转换为某类组件的状态、padding、border、font 和 radius。 |
| Component state | 组件当前状态组合 | hovered、pressed、focused、selected、disabled、loading 等。 |
| Paint value | 最终显示值 | 根据完整主题、内部配方和状态组合得到的颜色、位置和尺寸。 |
业务主题通过 createTheme() 或 compileTheme() 编译。组件内部配方不是公共 token 层;页面不应导入 derive*Style() 或复制其返回对象。
Surface Token
Surface 表达区域层级,不表达具体色名:
| Token | 用途 |
|---|---|
surfaceCanvas |
应用 Canvas 的最外层底色、浮动窗口之后的工作区。 |
surfaceContent |
页面、文档和窗口客户区的主要内容底色。 |
surfaceWindowTitle / surfaceWindowTitleActive |
非活动和活动窗口标题栏。 |
surfacePanel |
卡片、工具面板、页面分区。 |
surfacePopup |
Popup、Menu、Dropdown、Tooltip 等临时浮层。 |
surfaceControl |
普通按钮、输入框和选择器。 |
surfaceControlHover / surfaceControlActive |
普通控件 hover 和 pressed 表面。 |
surfaceNav |
导航栏、tab strip、toolbar chrome、dock rail。 |
surfaceDataHeader |
表头、分组头和数据区域 chrome。 |
surfaceDataBody |
Grid、Table、Tree 等数据正文区域。 |
选择规则:
- Canvas、页面内容、数据正文不是同一层,不要再用一个通用 window 背景覆盖三者。
surfaceWindow已删除。迁移时先判断区域语义,再选surfaceCanvas、surfaceContent或surfaceDataBody。- Popup 不使用页面 surface,否则浮层和内容区会粘在一起。
- 导航、tab strip、dock rail 属于 chrome,优先使用
surfaceNav。 - 数据表头和分组头使用
surfaceDataHeader;滚动数据正文使用surfaceDataBody。
文本、边框和语义色
| Token | 用途 |
|---|---|
textPrimary / textSecondary / textPlaceholder / textDisabled |
主文本、辅助文本、占位文本和禁用文本。 |
textAccent / textOnAccent / textOnDanger / textOnSelection |
强调文本及不同强调背景上的前景。 |
borderWindow / borderPanel |
窗口和面板边界。 |
borderControl / borderControlHover |
普通控件及其 hover 边框。 |
borderSubtle |
弱分隔线和低层级边界。 |
borderData / borderDataStrong |
数据区域边框和强调分隔。 |
focusBorder |
键盘焦点框。 |
accentPrimary / accentPrimaryHover / accentPrimaryActive |
主操作和主强调交互。 |
accentSuccess / accentSuccessHover |
成功语义。 |
accentWarning / accentWarningHover |
警告语义。 |
accentDanger / accentDangerHover / accentDangerActive |
危险操作和危险语义。 |
statusSuccessBg / statusWarningBg / statusDangerBg |
成功、警告、危险状态面。 |
statusSuccessBorder / statusWarningBorder / statusDangerBorder |
成功、警告、危险状态边框。 |
selectionMuted / selectionBg / selectionStrong |
弱选中、普通选中和强选中。 |
accentSuccessActive 和 accentWarningActive 已删除。成功和警告通常表达结果或风险,不是持续的 pressed 主操作;需要按下反馈时由对应组件内部配方合成。
规则:
- 品牌色只能集中在主题定义文件,不在组件或业务页面中散落固定十六进制值。
- placeholder 必须弱于真实值,但仍满足必要可读性。
- icon 默认跟随相邻文本语义;成功、警告、危险图标才使用对应语义色。
- 浅色选中背景使用
textOnSelection或resolveSelectionText(),不要默认使用textOnAccent。 - 同一语义在浅色、深色和紧凑主题下都必须可识别。
交互 Token
交互反馈分为基础 surface 和可组合覆盖层:
| Token | 用途 |
|---|---|
surfaceControlHover |
普通控件的完整 hover 表面。 |
surfaceControlActive |
普通控件的完整 pressed 表面。 |
stateHoverOverlay |
在当前 surface 或 selection 上叠加的 hover 覆盖色。 |
statePressedOverlay |
在当前 surface 或 selection 上叠加的 pressed 覆盖色。 |
stateHoverOverlay / statePressedOverlay 适用于数据行、选中项、导航项等必须保留基础语义的组合状态。它们是含 alpha 的覆盖色,不应被当作页面背景直接铺设。
规则:
- hover 是临时弱反馈,不能比 selected 更强。
- selected + hovered 应保留 selection 主视觉,再叠加 hover。
- pressed 比 hovered 更明确,但不能改变布局尺寸。
- focus 使用独立
focusBorder,不覆盖 selected、error 或 pressed 背景。 - disabled 清理 hover/pressed 等临时状态,并使用 disabled 前景。
字段编辑和文档编辑
普通字段及表格内编辑使用:
| Token | 用途 |
|---|---|
fieldBg |
字段编辑背景。 |
fieldFocusBorder |
字段编辑焦点边框。 |
fieldSelectionBg |
字段内文本选择背景。 |
文档编辑器使用 editor 层:
editor.selectionBgeditor.selectionTexteditor.searchMatchBgeditor.searchActiveMatchBgeditor.searchActiveMatchBorder
字段编辑和大文档编辑具有不同的面积、内容和性能约束。不要把 fieldSelectionBg 和 editor.selectionBg 机械合并,也不要使用已删除的 editBg、editBorder、editSelection。
尺寸 Token
| Token | 用途 |
|---|---|
controlHeight |
普通按钮、输入框和下拉框高度。 |
dataRowHeight / dataHeaderHeight |
数据行和数据表头高度。 |
panelHeaderHeight / toolbarHeight / statusBarHeight |
面板、工具栏和状态栏高度。 |
framePadding / itemSpacing / contentPadding / windowPadding |
控件、相邻项、内容和窗口内边距。 |
frameRounding / windowRounding |
控件和窗口圆角。 |
frameBorderSize / windowBorderSize |
控件和窗口边框宽度。 |
scrollbarSize / scrollbarRounding |
滚动条命中宽度和圆角。 |
规则:
- 控件、tab、数据行高度在 hover、selected、文本变化时必须稳定。
- 图标按钮使用稳定命中尺寸;图标本身可以小于命中区域。
- 1px 设备无关线宽由绘制层适配 DPR,业务代码不参与 DPR 换算。
- 紧凑密度通过主题定义和组件内部配方派生,不在组件里散落多个 magic number。
- 组件自然尺寸由内容和 token 计算,不能依赖上一次 paint 结果。
Typography 层
根级 fontFamily 是通用界面字体,根级 fontSize 是普通控件默认字号。完整 typography 层按角色同时定义 size、lineHeight 和 weight:
| 角色 | 字段 | 用途 |
|---|---|---|
| body | bodyFontSize / bodyLineHeight / bodyFontWeight |
正文、表单说明和普通内容。 |
| title | titleFontSize / titleLineHeight / titleFontWeight |
面板、卡片和工作区标题。 |
| secondary | secondaryFontSize / secondaryLineHeight / secondaryFontWeight |
hint、辅助统计和次要说明。 |
| mono | monoFontFamily |
代码、日志、标识符和需要等宽对齐的数据。 |
规则:
- size、lineHeight 和 weight 作为一个角色整体设计,不能只改字号导致裁切。
- 不按 viewport 宽度缩放业务字号。
- 不使用负 letter spacing。
- 业务区块和控件标题不使用营销页面的 hero 字号。
- 单行文本默认 ellipsis 或裁剪;多行文本必须有明确最大行数或可滚动容器。
Elevation 层
所有遮罩和阴影集中在 elevation:
modalScrim/drawerScrimpopupShadowColor/popupShadowBlur/popupShadowOffsetX/popupShadowOffsetYwindowShadowColor/windowShadowBlur/windowShadowOffsetX/windowShadowOffsetYcardShadowColor/cardShadowBlur/cardShadowOffsetX/cardShadowOffsetYcardHighlightColor
根级 popupShadow* 已删除。Popup、Modal、Drawer、Window 和 Card 应从各自高程语义取值,不共享一组模糊的“通用阴影”。
六个必需嵌套层
ResolvedTheme 始终包含完整的:
typographymotionelevationeditorchartsyntax
ThemeDefinition 可以局部覆盖它们,createTheme() / compileTheme() 会在进入 runtime 前补全并深冻结。组件不需要可选链或 paint-time fallback。
主题扩展边界
扩展业务主题时依次确认:
ResolvedTheme或组件公开 options 是否已经表达相同语义。- 该视觉是否会跨多个业务模块复用,而不是单页装饰。
- 自定义后是否仍能表达 hovered、pressed、focused、selected、disabled 和 error 的组合。
- 浅色、深色和高密度页面下是否保持足够对比度。
如果公共能力不足,应把临时差异集中在业务应用自己的 ThemeDefinition,再提出稳定语义需求;不要 deep import 框架内部组件配方。
主题中的前景色和背景色应使用 contrastRatio() 或 resolveContrastText() 校验。普通文字目标不低于 4.5:1;较大的图形、边框和焦点提示目标不低于 3:1。