ARTICLE · 1267233
设计系统代码化同构:设计师如何用 AI 把 Figma Token 填进真实业务组件
作者:丹丹
在组件库建设里,设计师经常会遇到一些很熟悉的对话。比如:
“这个按钮圆角能不能再大一点?”
“这个描边颜色不太对,和页面层级不搭。”
“Hover 状态能不能更明显一点?现在用户感知不到。”
“这个业务是深色场景,主按钮如果还是普通纯色,会有点压不住。”
前端的回答也很真实:
“组件库里就是这样的”
或者更准确一点:
“能改,但一改就是全局组件,可能会影响其他业务。”
这就是很多设计系统落到业务里时最尴尬的地方:
组件库 提供了统一性,但业务需要差异;
设计师 看到了问题,但没有安全修改的入口;
前端 能改代码,但不应该为每一次视觉微调重新维护一套组件。
所以在组件库建设里,很多团队都会遇到一个看似简单、实际很难的问题:交互逻辑是稳定的,但视觉表达一直在变。
Button、Input、Select、Tooltip、Dropdown 这些组件,在不同业务里通常不会改变最底层的交互逻辑。按钮还是按钮,选择器还是选择器,浮层还是浮层。但不同产品、不同品牌、不同业务场景,对颜色、圆角、层级、密度、阴影、状态反馈和动效节奏的要求都不一样。
如果每次视觉变化都走一遍“UI 出稿 → 前端还原 → UI 验收”,交付链路会很长。
如果每个业务都单独做一套组件库,又会重复维护交互、焦点、键盘操作、无障碍、测试和缺陷修复。
所以这次做 UI 共创组件库,我真正想解决的不是“再做一套组件库”,而是建立一种新的协作方式:
前端沉淀稳定交互,设计师持续填入视觉规则。
一套组件行为,多种业务视觉表达。
这篇文章更偏设计工程师视角,聊聊我是怎么把 Figma 里的 Token、业务里的视觉判断,以及 AI 编程助手的代码执行能力串起来的。
这不是简单换肤
一开始很容易把这件事理解成“做几套主题皮肤”,但真实业务里,主题差异不只是颜色不同。有些业务按钮是扁平的,纯色、无描边;有些业务按钮需要渐变、描边和更强的高光感;有些产品需要轻量克制的边界,有些产品需要更明确的层级;有些页面追求高密度,有些页面需要更强的呼吸感。
同样是 Hover 状态,不同业务里可能一个只需要轻微变色,另一个需要明显的边框和背景变化。所以组件库不能只解决“换颜色”,还要承接:
品牌色差异; 明暗模式差异; 控件密度差异; 圆角和阴影差异; 状态反馈强弱; 组件级特殊样式; 真实业务里的例外规则。
这也是为什么我没有把 Token 当成一张变量表,而是把它看作一种设计判断的结构化方式。
整体架构:行为、样式、主题分离
当前仓库大致分成几类包:
@your-org/ui-react | |
@your-org/ui-styles | |
@your-org/ui-theme-a | |
@your-org/ui-theme-b | |
@your-org/ui-docs |
可以简单理解为三层:
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?
这个主题是否真的适用于业务?
这个组件在真实场景里是否稳定?
当这些判断被结构化以后,组件库就不再是一套固定皮肤,而是一套可以持续生长的视觉生产系统。
它让交互能力稳定复用,也让不同业务能够在同一套工程边界里,长出自己的视觉表达。



















































































