尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

设计 Token 不该越堆越乱:三层分法和检查方式

设计 Token 不该越堆越乱:三层分法和检查方式 设计 Token 不该越堆越乱三层分法和检查方式让 AI 生成 UI 时最容易丢掉的往往不是布局而是设计系统的命名和层级。它会直接写一个接近的色值或间距短时间看不出差别主题切换和组件复用就开始变难。Token 不必堆成一套庞大的术语体系。重点是分清基础值、语义和组件用途再让构建与 lint 帮忙守住引用关系。本文以三层 Token、Style Dictionary 和 TypeScript 校验为例说明。基础值、语义和组件用途分开一个实用的 Token 体系通常分三层基础值Global、语义Semantic和组件用途Component。叫法可以随团队约定关键是引用关系清楚主题切换时不必在组件里逐个找色值。flowchart TD subgraph Figma Tokens / JSON 集中式配置源 A[JSON / YAML Token 原始设计文件] -- B{第一层: Option Tokens 基础选项层} B -- C[定义物理色板与纯数值: sys.color.palette.blue-500 #3B82F6] C -- D{第二层: Alias Tokens 业务语义抽象层} D -- E[映射业务意图: sys.color.interactive.primary {sys.color.palette.blue-500}] E -- F{第三层: Component Tokens 组件专有绑定层} F -- G[绑定组件属性: comp.button.primary.bg {sys.color.interactive.primary}] end subgraph Style-Dictionary 自动化编译与多端分发管线 G -- H[Style-Dictionary 多端编译引擎] H -- I[Web 端: CSS Variables / SCSS / Tailwind] H -- J[iOS 端: Swift / Color Assets] H -- K[Android 端: XML / Jetpack Compose] H -- L[Flutter 端: Dart Color / ThemeData] end C -. ❌ 严禁越过语义层直接引用基础色板 .- G三层各自负责的内容可以这样约定基础层存色板、字号、间距等原始值例如blue-500、space-16。语义层描述用途例如interactive-primary、background-danger、surface-card为主题映射留出位置。组件层表达组件属性例如button-primary-bg。只有组件确实需要独立状态或映射时才新增。诊断命令与自动化 Lint 约束构建和 lint 可以提醒代码是否绕过 Token。颜色与尺寸的硬编码不一定全是错误例如边框或第三方组件的兼容处理例外应写清原因而不是靠一刀切规则压过去。在仿真基准测试模型中自动化诊断与拦截指令链如下# 1. 运行 Style-Dictionary 构建脚本校验源 JSON 文件的结构合法性 npx style-dictionary build --config ./style-dictionary.config.js # 2. 执行 Stylelint 校验阻断 CSS/SCSS 中的硬编码颜色与非标单位 npx stylelint src/**/*.scss --config .stylelintrc.tokens.js # 3. 运行自定义 Node.js 静态扫描脚本分析未被 Alias 语义层收录的孤立 Token node scripts/audit-tokens-orphan.js --src./src --tokens./build/web/tokens.json --outtoken-audit-report.json # 4. 从报告中提取违规硬编码样式的行号与关联选择器 jq .violations[] | {file: .file, line: .line, raw_value: .rawValue} token-audit-report.json这组命令能在合并前列出疑似绕过语义层的样式评审再根据上下文决定保留、改 Token 或登记例外。Style-Dictionary 编译转换与 TypeScript 强类型收束源码下面的 Style-Dictionary 构建配置与 TypeScript 类型收束模块展示了如何将结构化 JSON Token 自动化编译为符合 Web 标准的 CSS 自定义变量并提供编译期类型提示。Style-Dictionary 编译配置文件 (style-dictionary.config.js)const StyleDictionary require(style-dictionary); // 注册自定义命名转换器生成 kebab-case 规范的 CSS 自定义变量名 StyleDictionary.registerTransform({ name: name/cti/kebab-semantic, type: name, transformer: (token) { return ds-${token.path.join(-)}; } }); module.exports { source: [tokens/**/*.json], platforms: { css: { transformGroup: css, transforms: [attribute/cti, name/cti/kebab-semantic, color/hex], buildPath: build/web/, files: [ { destination: tokens.css, format: css/variables, options: { showFileHeader: false, }, }, ], }, typescript: { transforms: [attribute/cti, name/cti/kebab-semantic], buildPath: build/web/, files: [ { destination: tokens.d.ts, format: typescript/es6-declarations, }, ], }, }, };强类型 Token 契约校验与解析模块 (token-contract-validator.ts)import tokens from ../build/web/tokens.json; export type SemanticColorMode light | dark; export interface ButtonTokenContract { backgroundNormal: string; backgroundHover: string; textPrimary: string; borderRadius: string; } /** * 解析并生成契合设计 Token 的强类型样式属性映射 * param isDark 是否开启暗黑模式 */ export function resolveButtonTokens(isDark: boolean): ButtonTokenContract { const modeKey: SemanticColorMode isDark ? dark : light; // 校验源 JSON 结构中是否存在关键语义 Token防止运行期样式破损 const interactiveTheme tokens.sys?.color?.interactive?.[modeKey]; const radiusTheme tokens.sys?.dimension?.radius; if (!interactiveTheme || !interactiveTheme.primary) { throw new Error([Token Schema Error] 关键语义 Token 缺失: sys.color.interactive.${modeKey}.primary); } return { backgroundNormal: var(--ds-sys-color-interactive-${modeKey}-primary), backgroundHover: var(--ds-sys-color-interactive-${modeKey}-primary-hover), textPrimary: var(--ds-sys-color-text-${modeKey}-on-primary), borderRadius: var(--ds-sys-dimension-radius-${radiusTheme.medium || 8px}), }; }边界条件推演与典型反模式防范维护 Token 时下面三种情况最容易让体系失去边界1. 反模式一按视觉属性命名Visual-based Naming将 Token 命名为color-red-500并直接绑定到警告按钮、系统通知或错误输入框上。一旦后续品牌主题升级需要将警告主题色调整为深橙色或黄色代码库中将产生color-red-500: #FF5722这种语义与实际值倒置的架构失真。可行做法组件引用时优先使用描述用途的语义 Token例如color-feedback-danger基础色板仍可保留在底层供语义层映射。2. 反模式二Token 数量无节制爆炸Token Explosion为了满足各个具体业务场景的微小视觉差异允许每一个子组件都申请独立的 Component Token会让 Token 库越来越难找、难改构建产物也可能随之膨胀。可行做法创建组件 Token 前先确认现有语义 Token 是否已能表达需求。确有独立状态、主题映射或跨端差异时再增加组件级 Token数量上限应由实际维护成本决定。3. 反模式三缺乏平滑的版本废弃机制Deprecation Strategy更新 Token 库时直接删除旧名称会让仍在使用它的下游项目在升级后报错或样式丢失。可行做法加上deprecated标注和编译期提醒给下游一段明确的迁移窗口。窗口长短应按发布节奏和依赖范围决定{ sys: { color: { old-btn-bg: { $value: {sys.color.interactive.primary}, $extensions: { deprecated: true, replacement: sys.color.interactive.primary-bg } } } } }Token 变更怎么进入日常评审日常规则可以简单些业务组件引用语义 Token而不是直接拿基础色板颜色和尺寸的例外要有明确理由新增全局 Token 先讨论用途再写入构建产物。这样即使先用 AI 起草组件也不会把设计系统悄悄拆散。
返回列表