夜雨聆风学习资料网

ARTICLE · 1267233

设计系统代码化同构:设计师如何用 AI 把 Figma Token 填进真实业务组件

设计系统代码化同构:设计师如何用 AI 把 Figma Token 填进真实业务组件

作者:丹丹

在组件库建设里,设计师经常会遇到一些很熟悉的对话。比如:

“这个按钮圆角能不能再大一点?”

“这个描边颜色不太对,和页面层级不搭。”

“Hover 状态能不能更明显一点?现在用户感知不到。”

“这个业务是深色场景,主按钮如果还是普通纯色,会有点压不住。”

前端的回答也很真实:

“组件库里就是这样的”

或者更准确一点:

“能改,但一改就是全局组件,可能会影响其他业务。”

这就是很多设计系统落到业务里时最尴尬的地方:

组件库 提供了统一性,但业务需要差异;

设计师 看到了问题,但没有安全修改的入口;

前端 能改代码,但不应该为每一次视觉微调重新维护一套组件。

所以在组件库建设里,很多团队都会遇到一个看似简单、实际很难的问题:交互逻辑是稳定的,但视觉表达一直在变。

Button、Input、Select、Tooltip、Dropdown 这些组件,在不同业务里通常不会改变最底层的交互逻辑。按钮还是按钮,选择器还是选择器,浮层还是浮层。但不同产品、不同品牌、不同业务场景,对颜色、圆角、层级、密度、阴影、状态反馈和动效节奏的要求都不一样。

如果每次视觉变化都走一遍“UI 出稿 → 前端还原 → UI 验收”,交付链路会很长。

如果每个业务都单独做一套组件库,又会重复维护交互、焦点、键盘操作、无障碍、测试和缺陷修复。

所以这次做 UI 共创组件库,我真正想解决的不是“再做一套组件库”,而是建立一种新的协作方式:

前端沉淀稳定交互,设计师持续填入视觉规则。  

一套组件行为,多种业务视觉表达。

这篇文章更偏设计工程师视角,聊聊我是怎么把 Figma 里的 Token、业务里的视觉判断,以及 AI 编程助手的代码执行能力串起来的。

这不是简单换肤

一开始很容易把这件事理解成“做几套主题皮肤”,但真实业务里,主题差异不只是颜色不同。有些业务按钮是扁平的,纯色、无描边;有些业务按钮需要渐变、描边和更强的高光感;有些产品需要轻量克制的边界,有些产品需要更明确的层级;有些页面追求高密度,有些页面需要更强的呼吸感。

同样是 Hover 状态,不同业务里可能一个只需要轻微变色,另一个需要明显的边框和背景变化。所以组件库不能只解决“换颜色”,还要承接:

  • 品牌色差异;
  • 明暗模式差异;
  • 控件密度差异;
  • 圆角和阴影差异;
  • 状态反馈强弱;
  • 组件级特殊样式;
  • 真实业务里的例外规则。

这也是为什么我没有把 Token 当成一张变量表,而是把它看作一种设计判断的结构化方式。

整体架构:行为、样式、主题分离

当前仓库大致分成几类包:

包
职责
@your-org/ui-react
React 组件、Props、交互、可访问性
@your-org/ui-styles
品牌无关的组件结构样式、状态样式和动画
@your-org/ui-theme-a
Brand A 主题 Token
@your-org/ui-theme-b
Brand B 主题 Token
@your-org/ui-docs
Storybook 文档和验收场景,不发布

可以简单理解为三层:

React 包负责组件行为、Props、DOM、ARIA、data-slot、data-stateStyles 包负责结构样式、状态样式、动画,只消费 --ui-* 变量Theme 包负责具体业务主题,把 Figma Token 转成可运行的 CSS Variables

这样做以后,React 组件不需要知道当前业务长什么样。它只负责稳定地暴露结构和状态。

视觉差异则通过主题包里的 CSS Custom Properties 注入。

例如业务侧使用时,只需要加载基础样式和对应主题:

import '@your-org/ui-styles';import '@your-org/ui-theme-a';import { Button, Tooltip, UiTheme } from '@your-org/ui-react';export function App() {  return (    <UiTheme name="theme-a">      <Tooltip content="保存当前内容">        <Button variant="primary">保存</Button>      </Tooltip>    </UiTheme>  );}

如果换成另一个品牌主题,React 组件不需要改,替换主题包和 UiTheme 名称即可。

设计师真正做的事:往稳定结构里填空

我理解的共创,不是让设计师去改复杂交互逻辑,而是在前端已经搭好的稳定结构里,把视觉规则填进去。

前端提供的是稳定骨架:

  • 组件有哪些 Props;
  • 有哪些尺寸;
  • 有哪些状态;
  • DOM 层级如何稳定;
  • 哪些节点可以被样式化;
  • 状态通过什么属性暴露;
  • 键盘、焦点、ARIA 怎么处理。

设计师填进去的是视觉规则:

  • 主色、辅助色、背景色;
  • Hover、Active、Disabled、Focus 状态;
  • 控件高度、间距、圆角;
  • 阴影、边框、渐变;
  • 动效时长和缓动;
  • 不同业务主题下的差异。

这件事看起来像是在写 CSS,但本质不是“改样式”,而是在判断:

这个视觉值应该属于基础色板?

应该上升为语义 Token?

应该直接应用到组件?

还是应该沉淀成组件 Token?

这个判断,是设计师在共创组件库里最重要的价值。

开始前:让 AI 先看得懂你的设计和代码

普通设计师要参与这类项目,第一步不是直接让 AI 写代码,而是先让 AI 告诉你:这个项目里哪些文件分别在管什么。

因为很多设计师第一次打开前端仓库,看到 packages、src、stories、theme、styles、react 这些目录,很容易不知道从哪里下手。

开始前,先做两件事:

第一件事,先连接 Figma MCP。

这一步要放在开始前做,而不是等到后面改不动了再补。因为到后面“喂组件”的时候,你不应该只给 AI 一段口头描述,最好直接把 Figma 里的组件链接、节点链接、变量和状态上下文给它。

第二件事,让 AI 先读代码仓库。

不是让它马上改代码,而是让它先告诉你

  • React 组件在哪里;
  • 组件样式在哪里;
  • 主题 Token 在哪里;
  • Storybook 场景在哪里;
  • 哪些文件是 UI 可以改的;
  • 哪些文件涉及 Props、DOM、ARIA、发布配置,需要前端 Review。

这一步的目的,是先把“仓库地图”拿到手。设计师不一定要立刻看懂所有代码,但至少要知道:我要改 token 时看哪个文件;我要改组件样式时看哪个文件;我要补 Storybook 验收场景时又该看哪里。

正式开始做组件之前,我的顺序是固定的:

先喂散装基础值  → 形成 Base Token  → 再喂语义层  → 形成 Semantic Token  → 最后喂具体组件设计稿  → 让 AI 根据组件实现样式,并沉淀 Component Token  → 后续微调时,优先调整 Component Token

这个顺序不能反。

如果一开始就把 Button 组件链接给 AI,它很容易直接围绕按钮生成一堆组件变量,看起来很快,但系统会变碎。正确做法是先把散装色值、字号、圆角、间距这些基础材料放好,再把“主色、页面背景、默认边框、主文本”这些语义层放好,最后才让组件来消费这些 token。

所以这里说的“填空”,不是让 AI 自己决定系统怎么分层,而是我先把空位一层一层定义好:

  • 第一层填原材料:色值、字号、圆角、间距、高度这些散装值;
  • 第二层填用途:主色、页面背景、默认边框、正文文字这些语义值,它们引用第一层;
  • 第三层填组件:把 Button、Input、Select 这些组件设计稿喂给 AI,让组件优先消费前两层;
  • 第四层填例外:如果某个业务组件确实有特殊表达,再封装成组件 Token;
  • 第五层做微调:组件跑起来以后,优先调组件 Token,而不是回头污染语义层。

Figma MCP 的价值不是“让 AI 自动替你做设计”,而是让 AI 能更直接地读取 Figma 里的设计结构、变量、节点和组件上下文。这样你在和 AI 编程助手沟通时,不需要完全靠截图或口头描述,它可以结合 Figma 的真实设计和代码仓库一起判断。

我是怎么和 AI 沟通的?

和 AI 协作时,最重要的是不要只说“帮我改成设计稿这样”。

这种描述太模糊,AI 不知道你要改的是品牌层、语义层,还是组件层。

提示词 1:让 AI 先理解项目边界

请先阅读当前仓库结构,不要修改代码。我希望你先告诉我:1. React 组件在哪里;2. 品牌无关样式在哪里;3. 主题 Token 在哪里;4. Storybook 场景在哪里;5. 哪些文件是 UI 可以直接修改的;6. 哪些文件涉及 Props、DOM、ARIA、发布配置,需要前端 Review。请用设计师能理解的方式解释每个目录是干什么的,并告诉我如果要改 Button 的视觉,优先应该看哪些文件。

这一步是让 AI 先停下来读项目,而不是马上生成一堆不合适的代码。

对应到这个仓库里,AI 需要先识别出几条边界:packages/react 管组件行为和 API,packages/styles 管品牌无关样式,packages/theme-a / packages/theme-b 管主题变量,apps/docs/src/stories 管 Storybook 验收场景。设计师不一定要马上看懂所有代码,但要先知道“我要改视觉时应该动哪一层”。

提示词 2:先喂散装基础值

这是从 Figma 通用组件库导出的基础 token 文件,里面主要是散装色值、字号、圆角、间距、高度这些原材料:- mode/xxx.tokens.json- mode/xxx.tokens.json请先分析它们的结构。我希望你区分:1. 哪些是基础色阶;2. 哪些是文本、背景、填充、描边等基础色组;3. 哪些是字号、字重、行高;4. 哪些是间距、圆角、高度;5. 哪些值适合进入代码里的 --ui-ref-*。先输出分析,不要直接改代码。

这一步是把散装材料整理成 Base Token,可以把设计系统项目的 Figma 地址给他(需要明确告知哪些是基础token),也可以自行导出。

比如 #ffffff、#3A89FE、0、4px、12px 这些值,本身还不应该带组件含义。它们只是后面语义层和组件层可以引用的基础材料。

对应到真实文件里,mode/Light.tokens.json 和 mode/Dark.tokens.json 更像这一层。它们提供的是 color、size、font、padding、borderRadius、height 这些原材料。进入代码后,我会把它们整理成类似 --ui-ref-primary-6、--ui-ref-text-1、--ui-ref-bg-1 这样的基础变量,而不是直接命名成 button-primary-bg。

提示词 3:再喂语义层 Token

这是我在 Figma 里封装好的语义层 token,它们不是散装值,而是已经带有用途含义的变量:- theme/xxx.tokens.json- theme/xxx.tokens.json请帮我分析它们和 base token 的引用关系。我希望你区分:1. 哪些是主色、信息色、成功色、警告色、危险色;2. 哪些是文本、背景、填充、描边等界面语义;3. 哪些语义 token 是引用 base token 得到的;4. 哪些适合映射成 --ui-color-*;5. 哪些还不应该进入组件 token。先输出分析,不要直接改代码。

这一步很重要。

Figma 导出的 token 不是原样塞进代码就结束。设计师要先判断它们在系统里属于哪一层:散装基础值进入 Base Token,带用途的值进入 Semantic Token。

对应到真实文件里,theme/ProductA.tokens.json、theme/ProductB.tokens.json, 更像这一层。它们已经不只是色值,而是带有“主色、背景、文本、填充、描边”等用途。代码里对应的是 --ui-color-surface-page、--ui-color-text-primary、--ui-color-action-primary、--ui-color-border-default 这类语义变量。

提示词 4:让 AI 帮你做基础 Token 映射

请基于 Figma 导出的 Light / Dark token,帮我整理一套基础 Reference Token。命名规则:- 基础色阶用 --ui-ref-*;- 不要直接出现组件名;- 不要把业务语义提前写进基础 token;- 尽量保留色阶关系和注释。目标文件:packages/theme-theme-a/src/index.css请先给出映射方案,说明每组 token 为什么这样命名,再修改代码。

这个提示词的重点是:基础 Token 不要带组件语义。

比如 #3A89FE 可以先进入 --ui-ref-primary-6,而不是一上来就叫 --ui-button-primary-bg。

对应到代码里,xxx 主题里会先有一层基础变量:

[data-ui-theme='theme-a'] {  --ui-ref-primary-1: #00144d;  --ui-ref-primary-2: #072979;  --ui-ref-primary-3: #1747a5;  --ui-ref-primary-5: #2e6ad2;  --ui-ref-primary-6: #3a89fe;  --ui-ref-primary-7: #60a5fa;  --ui-ref-primary-8: rgb(58 137 254 / 16%);}

这层只回答“有哪些基础材料”,不回答“按钮应该怎么用”。

提示词 5:把基础 Token 转成语义 Token

现在请基于已有的 --ui-ref-*,以及 Figma theme 文件里的语义变量,继续补充语义 Token。语义 Token 要描述界面角色,而不是颜色本身。请优先覆盖:- 页面背景;- 控件背景;- 浮层背景;- 主文本;- 次级文本;- 占位文本;- 主操作色;- 主操作 hover / active / disabled;- 默认边框;- 控件边框;- focus ring;- success / info / warning / danger。命名尽量使用:--ui-color-surface-*--ui-color-text-*--ui-color-action-*--ui-color-border-*不要在这一层写 button、select、tooltip 这类组件名。

这一层是从“颜料”进入“界面角色”。

组件优先消费这一层,才能避免每个组件都长出一套自己的变量。

对应到代码里,语义层会引用基础层:

--ui-color-surface-page: var(--ui-ref-bg-1);--ui-color-text-primary: var(--ui-ref-text-1);--ui-color-action-primary: var(--ui-ref-primary-6);--ui-color-action-primary-hover: var(--ui-ref-primary-5);--ui-color-border-default: var(--ui-ref-border-2);

这样组件消费的是“主操作”“默认边框”“主文本”这些用途,而不是直接消费 #3A89FE。

提示词 6:把 Figma 组件链接喂给 AI

这是 Figma 通用组件库里 Button 的组件链接:直接粘贴 Figma component / node link,都可以请先读取这个组件的结构、状态和变量使用情况。我希望你帮我判断:1. 这个 Button 在 Figma 里有哪些 variant / state / size;2. 它用到了哪些颜色、圆角、描边、间距和文字变量;3. 这些值分别应该优先对应现有的 base token、semantic token,还是需要新增 component token;4. 当前代码里的 Button 样式是否已经有 fallback 机制;5. 如果设计稿里有业务特殊表达,比如渐变、描边、特殊 hover,请先说明它为什么不能直接放进 semantic token。先输出分析,不要直接修改代码。

这一步发生在 base token 和 semantic token 之后。

比起只给 AI 一句“按钮要做成这样”,直接给 Figma 组件链接会更稳定。AI 可以结合真实组件结构、变量和状态,再去判断代码里应该改 theme、styles,还是组件 token。

对应到 Button,基础样式里已经预留了 fallback:

.ui-button[data-variant='primary'] {  color: var(--ui-button-primary-on, var(--ui-color-on-action-primary));  border-color: var(--ui-button-primary-border, transparent);  background: var(--ui-button-primary-bg, var(--ui-color-action-primary));}

也就是说,没有特殊业务要求时,它走语义 Token;有特殊业务要求时,才填 --ui-button-* 组件 Token。

提示词 7:判断并封装组件 Token

现在我发现一个业务差异:Figma 通用组件库里的主按钮是扁平纯色,没有 border。但当前 AI Screen 业务里的主按钮需要更强的视觉层级:- 背景是 180deg 渐变;- 默认态 from primary-6 to primary-5;- hover 态 from primary-7 to primary-6;- active 态 from primary-5 to primary-3;- disabled 态 from primary-2 to primary-1;- 每个状态都有对应 border;- 文本使用 text-6,disabled 文本使用 text-7。请判断这个差异应该放在语义 Token 还是组件 Token。如果你认为应该是组件 Token,请帮我设计 token 名称,并接入现有 Button 样式的 fallback 机制。注意:1. 不要改 React 组件 API;2. 不要把渐变写死在通用 styles 里;3. 优先在主题包中新增 --ui-button-* 组件 token;4. 后续微调 hover、active、disabled 时,也应该优先调整这些组件 token。

这个提示词才是设计工程师真正的工作方式。

你不是让 AI 猜,而是把业务判断讲清楚,让 AI 帮你执行。

对应到 AI Screen 主按钮,我会让 AI 生成的是组件 Token,而不是改全局语义 Token:

--ui-button-primary-fill-from: var(--ui-ref-primary-6);--ui-button-primary-fill-to: var(--ui-ref-primary-5);--ui-button-primary-border: var(--ui-ref-primary-7);--ui-button-primary-fill-from-hover: var(--ui-ref-primary-7);--ui-button-primary-fill-to-hover: var(--ui-ref-primary-6);--ui-button-primary-border-hover: var(--ui-ref-primary-7);--ui-button-primary-bg: linear-gradient(  180deg,  var(--ui-button-primary-fill-from) 0%,  var(--ui-button-primary-fill-to) 100%);

这里的关键不是“用了渐变”,而是这个判断:

渐变和描边不是所有主操作都需要,它只属于当前业务下的 Button 表达,所以它应该沉淀为组件 Token,而不是污染语义 Token。

后续微调也应该优先发生在组件 Token 上。比如主按钮 Hover 觉得太亮,不应该回头改 --ui-color-action-primary-hover,更合理的是调整:

--ui-button-primary-fill-from-hover--ui-button-primary-fill-to-hover--ui-button-primary-border-hover

这样微调只影响 Button 的 primary hover,而不会污染 Link、Select、RadioGroup 这些同样可能使用主操作语义的组件。

同样的组件 API,同样的 variant="primary",在 Brand B 里可以继续是纯色,在 AI Screen 里可以是渐变。组件 Token 的目的不是让系统变复杂,而是让差异有地方放:

默认走语义 Token  → 遇到稳定业务差异  → 抽成组件 Token  → 仍然由同一份组件结构消费

这就是我理解的组件库可扩展性。

提示词 8:在 Storybook 里验收组件状态

请帮我检查 Button 的 Storybook 验收场景。我希望至少覆盖:1. Playground;2. variant 矩阵;3. default / loading / disabled;4. icon only;5. icon + text;6. danger / secondary / ghost;7. AI Screen 与 Brand B 的品牌对比。请优先补 Storybook 场景,不要为了展示效果去改 React API。

Token 写完之后,我不会只在 Figma 变量表里确认。因为 Token 进入真实组件后,会遇到很多状态组合:

  • Default;
  • Hover;
  • Active;
  • Focus;
  • Disabled;
  • Loading;
  • Icon only;
  • Icon + Text;
  • Danger;
  • Secondary;
  • Ghost;
  • 不同尺寸;
  • 不同主题。

仓库里的 Button Storybook 覆盖了这些场景:

PlaygroundVariantsStatesIconOnlyIconWithTextBrandComparison

对设计师来说,Storybook 不是开发文档,而是一个状态验收台。

它让我能看到:

  • 渐变按钮在深色背景里层级是否够;
  • 纯色按钮在浅色主题里是否过重;
  • Disabled 状态是否真的像不可用;
  • Loading 状态是否破坏按钮宽高;
  • Icon only 是否在不同尺寸下保持视觉居中;
  • 同一个组件在两个品牌下是否仍然像同一个体系。

很多 Token 调整,不是在 Figma 表格里发生的,而是在 Storybook 里对比状态后发生的。

这篇文章重点讲设计师如何填 Token,但组件库真正能长期跑起来,还需要工程边界兜底。

前端需要稳定提供组件 API、DOM、ARIA、焦点、键盘操作、Portal 等交互能力;设计师主要在 theme、styles、Storybook 场景和约定的 UI 协作区里工作。像 ui-* class、data-slot、data-state、data-size、data-loading 这些属性,就是设计师能安全写样式的接口。

主题切换、Portal 浮层继承、CSS Layers、发包流程这些技术细节不展开讲,但它们的作用很明确:让设计师填进去的视觉规则,不只停留在本地 demo,而是能稳定进入真实业务。

最后再收束一次 Token 分层

它不是从 Figma 导出一份 JSON,然后原样塞进代码。

更合理的流程是:

散装色值、字号、圆角、间距、数值  ↓Base Token  ↓语义 Token(主色、页面背景、默认边框、主文本等,引用 Base Token)  ↓喂具体组件设计稿  ↓让 AI 根据组件实现样式,并封装 Component Token  ↓在 Storybook / 业务场景中验证  ↓后续微调优先调整 Component Token

也就是:

先喂基础 token:比如 0、#ffffff、主色色阶、文本色阶、字号、间距、圆角。

再喂语义 token:比如页面背景、主文本、主操作、默认边框、控件背景、Focus ring。

然后应用到真实组件:看 Button、Input、Select、Tooltip 在各种状态下是否成立。

最后喂组件设计稿,让 AI 根据真实组件状态实现样式,并抽组件 token。

比如通用组件库里的按钮是纯色无描边,但真实业务里的主按钮需要 from XXX to XXX 的渐变和 border,这时就不能污染全局语义,而应该沉淀成 --ui-button-primary-bg、--ui-button-primary-border、--ui-button-primary-fill-from、--ui-button-primary-fill-to 这类组件 Token。

等组件跑起来以后,后续微调也主要调这些组件 Token。

比如主按钮 Hover 太亮,就调 --ui-button-primary-fill-from-hover / --ui-button-primary-fill-to-hover,而不是回头改全局的 --ui-color-action-primary-hover。

组件 Token 不是越多越好。

它是一种受控例外。

默认应该走语义 Token。

只有当某个差异稳定、明确属于某个组件、无法用通用语义表达时,才把它抽出来。

最  后

共创组件库的核心,不是让设计师代替前端写代码。

它真正做的是,把组件生产拆成两部分:

前端沉淀稳定的交互、结构、无障碍、测试和发布能力。

设计师把真实业务中的视觉判断,转成可复用、可验证、可维护的 Token 和样式规则。

在这个过程中,Figma MCP 可以帮助 AI 读取设计上下文,AI 可以帮助设计师把判断转成代码,Storybook 可以帮助设计师验证真实组件状态。

但真正重要的仍然是设计判断:

这个值是否通用?

这个状态是否合理?

这个差异是否应该上升为组件 Token?

这个主题是否真的适用于业务?

这个组件在真实场景里是否稳定?

当这些判断被结构化以后,组件库就不再是一套固定皮肤,而是一套可以持续生长的视觉生产系统。

它让交互能力稳定复用,也让不同业务能够在同一套工程边界里,长出自己的视觉表达。

相关学习资料