← ALL NOTES
METHOD·2026.09·8 MIN READ
从 Figma 设计系统到代码组件的技术分层
figma-apidesign-systems
问题

第一次接触前端 UI 技术栈时,最容易混在一起的是一组看起来都和"界面"有关的名字:Ant Design、Arco Design、Tailwind CSS、shadcn/ui、Radix UI、GSAP、Framer Motion、Magic UI。

它们经常会出现在同一场讨论里,但解决的问题并不一样。如果不先把职责分清楚,很容易把本来可以组合使用的东西当成竞品,也很难判断哪一层真正适合承接公司的设计系统。

我之前在为设计系统组件试点选择技术栈时,就遇到了这个问题。真正需要解决的不是"哪个库最好",而是先回答三个更基础的问题:

  • 哪些工具负责视觉样式?
  • 哪些工具提供已经封装好的组件?
  • 哪些工具只处理交互行为或动效?

这次分类主要由 Claude Code 帮我梳理,我再用自己熟悉的 Figma 组件工作方式去验证这些概念是否成立,并据此做后续技术选型。

先按职责分层

把这些工具按职责拆开以后,关系会清楚很多。

层级主要职责典型工具
样式基础提供原子化样式能力,由开发者组合出具体视觉Tailwind CSS
完整 UI 组件直接提供按钮、输入框、弹窗、表格等已经组装好的界面组件Ant Design、Arco Design、shadcn/ui
无样式行为组件处理键盘、焦点、可访问性和交互状态,不规定最终视觉Radix UI、Base UI
动效控制元素如何进入、退出、移动和编排GSAP、Framer Motion
视觉特效组件提供更偏展示和营销页面的成品视觉效果Magic UI

这里最容易混淆的是 Tailwind 和 UI 组件库。

如果类比到 Figma:

  • Tailwind 更像颜色、圆角、间距、字号这些基础属性;
  • UI 组件库更像已经组装好的 Button / Primary / Large;
  • Radix / Base UI 更像组件内部关于焦点、键盘、选中状态的行为规范;
  • 动效库则负责这个组件出现、消失和移动时怎么动。

它们不是同一层的替代关系,而是可以叠加在一起组成完整界面。

Tailwind 和组件库不是竞品

这一步是我最早最容易问错的问题。

Tailwind CSS 不提供一个完整的 Button。它提供的是一组原子化 class,让开发者自己决定颜色、间距、圆角、字号和状态,再把这些属性组合成按钮。

UI 组件库则已经把这些东西封装成一个可以直接调用的单位。

放回 Figma 里其实很好理解:设计师从 Auto Layout、Fill、Radius、Spacing 这些基础属性开始搭出一个 Button,然后把它保存成组件。代码世界里也有类似的分层。

shadcn/ui 就是一个很直观的例子。它提供 <Button> 这样的组件,但组件内部的视觉样式本身仍然由 Tailwind class 组成。

所以更准确的关系是:Tailwind 提供样式材料,组件库把这些材料组织成可复用组件。

这个理解一旦建立,"Ant Design 还是 Tailwind"这种问题本身就不再成立,因为两者解决的不是同一层问题。

shadcn/ui 为什么适合做设计系统底座

这次选型里,shadcn/ui 最关键的特点并不是它的默认视觉,而是它的代码归属方式。

Ant Design、Arco 这类传统组件库通常作为依赖安装到项目里。开发者主要通过主题变量和组件 API 去调整它们。

shadcn/ui 的方式不同:通过 CLI 把组件源码直接放进项目仓库。生成以后,这些文件和自己写的代码没有本质区别,可以阅读、修改、删减,也可以逐步替换成公司的设计规范。

对一个需要把 Figma 设计系统转成公司自己的代码组件库 的项目来说,这一点很重要。

我需要的不是"找一套视觉接近公司的现成组件",而是一套已经处理好基础交互和工程结构、但允许我们完全控制最终视觉的组件骨架。

因此,shadcn 更适合作为起点,而不是最终设计语言本身。

Radix / Base UI 解决的是行为,不是视觉

继续往下看 shadcn 组件,会发现很多复杂组件并不是从零处理交互状态,而是建立在 Radix UI 这类无样式组件基础上。

这一层负责的是:

  • 键盘操作;
  • 焦点管理;
  • 打开 / 关闭状态;
  • 可访问性;
  • 一些复杂组件的交互行为。

但它不负责决定按钮是什么颜色、弹窗是什么圆角。

这和设计系统里的"行为规范"和"视觉规范"是两件事很像。公司可以重新定义视觉 token 和样式,而不必重新发明一套 Dialog 怎么管理焦点、Dropdown 怎么用键盘操作的底层逻辑。

因此,换 Radix 或 Base UI 这类骨架,主要影响内部实现方式,不应该直接决定产品最后长什么样。

Ant Design / Arco 更适合什么场景

Ant Design 和 Arco Design 的优势非常明确:它们已经提供了大量成熟的企业级组件,尤其适合表格、表单、筛选、后台管理等信息密集型产品。

如果目标是快速搭一个中后台,直接采用这种完整组件库通常效率很高。

但如果目标是建立一套视觉上高度独立的公司设计系统,约束也会更明显。组件结构、默认样式和主题机制已经有较强的系统特征,最终要把产品改得完全不像原组件库,需要付出更多覆盖成本。

所以这次没有选择 Ant Design,并不是因为它"不够好",而是它优化的目标和这次项目目标不同。

Arco 对我仍然很有参考价值,因为它本身就同时维护 Figma 设计资源和代码组件,是观察"设计系统如何跨设计和开发同步"的一个成熟案例。

动效库是另一条独立链路

GSAP 和 Framer Motion 也经常和组件技术栈放在一起讨论,但它们不负责组件的基础样式或结构。

它们解决的是元素怎么动。

Framer Motion 更适合常见的 UI 状态变化和页面过渡;GSAP 更擅长复杂时间线和精细动画编排。

因此,一个项目完全可以同时使用 shadcn/ui 和 Framer Motion,也可以在复杂动画场景里再引入 GSAP。这里不存在"选了组件库以后就不需要动效库"的关系。

从 Figma 到代码组件

把这些层级理清以后,我才更准确地理解了 Figma 设计系统和代码组件库之间的关系。

Figma 负责定义:

  • token;
  • 组件结构;
  • 视觉状态;
  • 尺寸与组合规则。

代码组件还需要处理:

  • 实际交互状态;
  • 键盘与焦点;
  • 可访问性;
  • API;
  • 与业务代码的连接。

所以目标并不是把 Figma "自动翻译成代码",而是让设计和代码共享同一套设计规则,同时让代码层借用成熟的交互基础设施。

这也是最终采用 React + Tailwind CSS + shadcn/ui 的原因:

  • React 承担组件结构和状态;
  • Tailwind 承担样式组合;
  • shadcn 提供可直接进入仓库、可修改的组件骨架;
  • 公司的 token 和规范决定最终视觉。
Token 如何接到组件里

实际落地时遇到的一个问题,是 shadcn 默认使用自己的语义变量,例如:

--primary
--muted
--accent

而从 Figma 设计系统提取出来的 token 使用的是公司的命名,例如:

--color-text-brand-primary

最终没有去逐个修改 shadcn 组件,而是在两套命名之间加一层很薄的映射。

例如让 shadcn 的 --primary 指向公司 token 中对应的变量。

这样做以后:

  • 组件源码可以尽量保持原有结构;
  • 公司 token 仍然是视觉规范的唯一来源;
  • Figma token 更新时,主要调整映射层,而不是逐个组件修改样式。

这层桥接比"把 shadcn 的 token 名直接当成公司的设计 token"更清楚,因为它保留了设计系统自己的语义体系。

实现备注

最终试点技术栈:React + Tailwind CSS + shadcn/ui。

shadcn 组件源码直接进入项目仓库,而不是只作为不可见的第三方依赖使用。

公司自己的 design token 保持独立命名,通过 CSS variable mapping 对接 shadcn 的语义变量。

复杂组件的行为基础可以继续使用 Radix UI / Base UI 一类无样式 primitive,而最终视觉由公司 token 和组件样式决定。

经验总结
  1. 技术选型先分层,再比较工具。 如果两个工具解决的不是同一层问题,就不应该直接拿来做二选一。
  2. 设计系统需要区分样式、组件和行为。 视觉 token、组件封装、可访问性交互不是同一个层级。
  3. 选择代码组件底座时,先看需要多少视觉控制权。 快速使用成熟默认样式和建立高度定制的品牌组件库,是两种不同目标。
  4. Figma 和代码不需要一一复制实现方式。 更重要的是共享 token、状态和组件规则,再让代码使用合适的工程基础设施。
  5. 第三方组件的语义变量不等于公司的 design token。 中间增加映射层,可以降低组件实现和设计规范之间的耦合。
关于 AI 辅助学习

这次 Claude Code 最有帮助的地方,是把陌生的前端技术生态重新映射到我已经熟悉的 Figma 组件体系里。

但我没有把这个类比直接当成最终结论。比如理解"shadcn 的组件是 Tailwind 拼出来的"之后,我还是打开实际生成的 Button 源码看了一遍,确认它确实是可以阅读和修改的普通组件代码。

对我来说,这种方式比较有效:先用 AI 把陌生概念翻译到已有知识框架里,再用真实代码或产品验证一次。 前一步降低理解成本,后一步确保这个理解足以支撑真正的技术判断。

CONTINUE READING
从 Figma 组件属性到代码 Props2026.09Figma 设计系统的工程化落地2026.09