我见过不少团队有过这样的经历:花几个月整理出一套组件库,按钮、输入框、弹窗一应俱全,Storybook 也很漂亮。但半年后,页面里仍然散落着手写按钮、临时颜色和相似却不一致的卡片。组件库确实存在,设计系统却没有真正发生。
原因通常不在组件质量,而在我们把“发布了一套 UI 组件”误当成了“建立了一套共同工作方式”。组件库是设计系统的产物之一,不是设计系统本身。
设计系统真正包含什么
如果把设计系统只理解成代码仓库,那么设计、内容、无障碍和治理都会落在系统之外。一个能被长期使用的系统,至少包含六部分:
- 原则:团队共同认可的体验判断,例如清晰优先、渐进披露、错误可恢复;
- 语言:颜色、间距、字体、层级和状态如何被命名与描述;
- Token:设计决策在代码中的最小可复用表达;
- 组件与模式:在真实场景中解决具体问题的交互单元;
- 文档:何时使用、何时不用、键盘行为、错误文案与失败恢复;
- 治理:谁提出变更、如何评审、如何发布、如何废弃。
缺掉任何一环,系统都会在真实协作中变形。尤其是治理:没有人维护的一致性,最后只会退化成一堆看起来相似的选择。
Token 是决策的语言,不是变量收藏夹
Token 的价值不是“把颜色抽成变量”,而是让团队用意图交流,而不是用具体值交流。直接写 #d9ff57 只能表达颜色,使用 color-action-primary 才能表达“这是主要操作”。
我习惯把 Token 分成三层:
原始层 / Primitive
lime-400: #d9ff57ink-900: #111309- 描述值本身,不承载业务含义
语义层 / Semantic
action-primary-bgtext-on-action- 描述用途,可随主题切换
组件层则只在有明确必要时存在,例如 button-primary-bg 引用 action-primary-bg。很多系统失败在层级太细:每一个组件都有自己的颜色变量,最后改一套主题需要穿过几十个别名。
: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 表格的文档,无法帮助使用者做判断。设计系统文档至少应该回答:
- 什么时候用:这个组件解决什么用户问题,与邻近组件的边界在哪里;
- 什么时候不用:哪些看似匹配、但会引起语义混淆的场景;
- 如何访问:键盘顺序、焦点管理、屏幕阅读器名称与状态;
- 失败时怎么办:错误提示、重试、空状态和禁用条件;
- 内容怎么写:按钮文案的语气、长度限制和本地化注意事项。
可访问性不能作为“合规附录”。如果一个弹窗没有正确的初始焦点,或者表单错误只在边框上变色,那么它在系统层面就是不合格的。把这些问题写进组件的验收标准,比事后逐页修复更便宜。
治理机制决定系统能否生长
设计系统最难的,不是第一版,而是第一百次修改。一个可持续的治理机制需要回答下面几个问题:
贡献与决策
- 业务团队如何提出新需求?
- 谁对语义和最终实现负责?
- 紧急修复能否绕过常规评审?
版本与退出
- 破坏性变更如何告知使用者?
- 旧版本维护多久?
- 废弃组件如何迁移与删除?
版本号本身没有意义,迁移路径才有。如果一次升级让业务团队需要手工检查五个页面,而系统没有 codemod、可视化 diff 或清晰迁移文档,团队自然会选择冻结版本,系统随即分裂。
衡量健康度也不应只看组件调用量。更有价值的信号包括:新页面使用系统组件的比例、绕过 Token 的硬编码数量、组件升级的完成率、无障碍缺陷的回归情况,以及业务团队提交贡献的频次。调用量只能证明存在,不能证明有效。
从下往上推广,往往行不通
设计系统需要高层支持,但落地必须发生在具体业务里。最有效的方式通常不是发一封“请使用新组件库”的邮件,而是找到真实痛点,在现有项目中把系统带入:
- 选择一个高频且体验不一致的流程,例如表单错误状态;
- 与业务团队一起修复真实用户问题,而不是先做完整组件目录;
- 把这次解决方案沉淀成模式、组件、文档和迁移指南;
- 记录收益,同时承认成本,再扩展到下一个领域。
当业务团队发现使用系统能更快交付、更少返工,采纳自然会扩散。没有人会仅仅因为系统“更规范”就长期承担额外成本。
系统是一种共同做决定的方式
组件库让页面拥有相同的零件,设计系统让团队拥有相同的判断。它把你对颜色、间距、状态和无障碍的思考,变成下一次可以直接复用的默认选择。
所以,下次准备从组件清单开始时,不妨先问:我们有没有共同的词汇?愿意接受哪些约束?当有人需要偏离时,如何记录并重新形成共识?这些问题的答案,往往比多写十个组件更能决定设计系统的命运。