DESIGN SYSTEMS

设计系统不是组件库:
从 Token 到协作的
完整视角

组件只是系统的可见部分。真正决定它能否生长的,是语言、约束和治理方式。

我见过不少团队有过这样的经历:花几个月整理出一套组件库,按钮、输入框、弹窗一应俱全,Storybook 也很漂亮。但半年后,页面里仍然散落着手写按钮、临时颜色和相似却不一致的卡片。组件库确实存在,设计系统却没有真正发生。

原因通常不在组件质量,而在我们把“发布了一套 UI 组件”误当成了“建立了一套共同工作方式”。组件库是设计系统的产物之一,不是设计系统本身。

设计系统真正包含什么

如果把设计系统只理解成代码仓库,那么设计、内容、无障碍和治理都会落在系统之外。一个能被长期使用的系统,至少包含六部分:

  • 原则:团队共同认可的体验判断,例如清晰优先、渐进披露、错误可恢复;
  • 语言:颜色、间距、字体、层级和状态如何被命名与描述;
  • Token:设计决策在代码中的最小可复用表达;
  • 组件与模式:在真实场景中解决具体问题的交互单元;
  • 文档:何时使用、何时不用、键盘行为、错误文案与失败恢复;
  • 治理:谁提出变更、如何评审、如何发布、如何废弃。

缺掉任何一环,系统都会在真实协作中变形。尤其是治理:没有人维护的一致性,最后只会退化成一堆看起来相似的选择。

Token 是决策的语言,不是变量收藏夹

Token 的价值不是“把颜色抽成变量”,而是让团队用意图交流,而不是用具体值交流。直接写 #d9ff57 只能表达颜色,使用 color-action-primary 才能表达“这是主要操作”。

我习惯把 Token 分成三层:

原始层 / Primitive

  • lime-400: #d9ff57
  • ink-900: #111309
  • 描述值本身,不承载业务含义

语义层 / Semantic

  • action-primary-bg
  • text-on-action
  • 描述用途,可随主题切换

组件层则只在有明确必要时存在,例如 button-primary-bg 引用 action-primary-bg。很多系统失败在层级太细:每一个组件都有自己的颜色变量,最后改一套主题需要穿过几十个别名。

tokens.css
:root {
  /* primitive:只描述值 */
  --lime-400: #d9ff57;
  --ink-950: #0b0c09;
  --paper-100: #ecebdd;

  /* semantic:描述意图 */
  --color-action-primary: var(--lime-400);
  --color-action-ink: var(--ink-950);
  --color-surface-canvas: var(--paper-100);
}

[data-theme='dark'] {
  --color-surface-canvas: var(--ink-950);
}

一个好的 Token 名称应当回答“为什么用它”,而不仅是“它长什么样”。如果名称里出现了具体数值或视觉描述,通常说明它还停留在原始层,不应该被页面直接使用。

系统的力量来自约束,而不是覆盖一切

组件库倾向于不断增加能力:更多变体、更多尺寸、更多插槽。时间久了,一个按钮拥有 40 种组合,所有页面都能找到“刚好合适”的版本,系统也失去了统一性。真正成熟的设计系统,敢明确说“不”:

  • 哪些场景应该使用系统组件,哪些允许业务自定义;
  • 哪些变体有明确语义,哪些只是视觉偏好;
  • 哪些交互需要重新评审,而不是通过新增 prop 绕过。

约束不代表抹平差异。系统应该让差异变得可见、有理由、有记录:这个页面为什么需要不同的密度?是因为移动端操作频率更高,还是因为设计者个人偏好?只有前者值得进入系统。

先做模式,再做组件

如果一个需求只出现过一次,先用现有组件组合解决;当相似形态第三次出现,再考虑抽象。过早抽象的共同成本,往往比一次局部重复更高。

文档是系统的一部分,不是附赠品

一个只有 Props 表格的文档,无法帮助使用者做判断。设计系统文档至少应该回答:

  1. 什么时候用:这个组件解决什么用户问题,与邻近组件的边界在哪里;
  2. 什么时候不用:哪些看似匹配、但会引起语义混淆的场景;
  3. 如何访问:键盘顺序、焦点管理、屏幕阅读器名称与状态;
  4. 失败时怎么办:错误提示、重试、空状态和禁用条件;
  5. 内容怎么写:按钮文案的语气、长度限制和本地化注意事项。

可访问性不能作为“合规附录”。如果一个弹窗没有正确的初始焦点,或者表单错误只在边框上变色,那么它在系统层面就是不合格的。把这些问题写进组件的验收标准,比事后逐页修复更便宜。

治理机制决定系统能否生长

设计系统最难的,不是第一版,而是第一百次修改。一个可持续的治理机制需要回答下面几个问题:

贡献与决策

  • 业务团队如何提出新需求?
  • 谁对语义和最终实现负责?
  • 紧急修复能否绕过常规评审?

版本与退出

  • 破坏性变更如何告知使用者?
  • 旧版本维护多久?
  • 废弃组件如何迁移与删除?

版本号本身没有意义,迁移路径才有。如果一次升级让业务团队需要手工检查五个页面,而系统没有 codemod、可视化 diff 或清晰迁移文档,团队自然会选择冻结版本,系统随即分裂。

衡量健康度也不应只看组件调用量。更有价值的信号包括:新页面使用系统组件的比例、绕过 Token 的硬编码数量、组件升级的完成率、无障碍缺陷的回归情况,以及业务团队提交贡献的频次。调用量只能证明存在,不能证明有效。

从下往上推广,往往行不通

设计系统需要高层支持,但落地必须发生在具体业务里。最有效的方式通常不是发一封“请使用新组件库”的邮件,而是找到真实痛点,在现有项目中把系统带入:

  1. 选择一个高频且体验不一致的流程,例如表单错误状态;
  2. 与业务团队一起修复真实用户问题,而不是先做完整组件目录;
  3. 把这次解决方案沉淀成模式、组件、文档和迁移指南;
  4. 记录收益,同时承认成本,再扩展到下一个领域。

当业务团队发现使用系统能更快交付、更少返工,采纳自然会扩散。没有人会仅仅因为系统“更规范”就长期承担额外成本。

系统是一种共同做决定的方式

组件库让页面拥有相同的零件,设计系统让团队拥有相同的判断。它把你对颜色、间距、状态和无障碍的思考,变成下一次可以直接复用的默认选择。

所以,下次准备从组件清单开始时,不妨先问:我们有没有共同的词汇?愿意接受哪些约束?当有人需要偏离时,如何记录并重新形成共识?这些问题的答案,往往比多写十个组件更能决定设计系统的命运。

沈健健

前端工程师,关注界面工程、性能与设计系统。相信好的技术判断,最终都会反映在用户不必思考的细节里。