关于 sb-figma
sb-figma 是面向 Storybook 项目的 Figma 交付技能,将已批准的设计数据整理为生产组件,并把代码与设计的差异反馈到 Figma 流程中。它还支持变量令牌对齐和 Code Connect 映射。
主要功能
- 01捕获并持久化 Figma MCP 输出
- 02比较 Figma 变量与代码令牌
- 03将已批准的组件交付到 Storybook
- 04处理 Code Connect 映射
- 05记录差异并维护项目规则
适用场景
- 01从已批准的 Figma 设计构建生产组件
- 02检查不同主题下的设计令牌差异
- 03为发布的组件库建立 Code Connect 映射
MCP 相关
使用 Figma MCP 的结构化工具读取变量、组件上下文和节点结构,并将调用结果保存到项目存储。支持 Code Connect 相关工具,以及可选的 Figma 写入操作。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ strongeron/ storybook-workbench --skill sb-figma安装后在 Claude Code 中输入/sb-figma确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CONTEXT.mdagents/openai.yamldecorators/withLayoutFrame.tsxreferences/figma-token-sync.mdread-figma-variables.jsworkbench.schema.jsonwrite-figma-variables.jsscripts/build-code-connect.mjsbuild-figma-variables.mjsbuild-token-parity.mjscapture-figma.mjscss-tokens.mjspull-figma-variables.mjsrecord-figma-delivery.pyworkbench-settings.mjstemplates/figma-inventory.stories.tsxwrappers/FigmaInventory.tsxicons.tsxReportIntro.tsxresolve-paint.tsTokenMatrix.tsxTokensCanvas.tsxusage-index.tsxusage-stamp.tsx详细介绍
sb-figma — Figma ↔ Storybook 桥接
sb-figma 将已批准的设计交付到生产环境中的 Storybook(任务 1–2),并将代码中的实际情况回传到 Figma(任务 3,以及选择启用的写入操作)。它使用 Figma MCP,但不是探索技能。
前置条件 — 首次调用前检查
| 任务 | 要求 | 工具 |
|---|---|---|
| 读取令牌(任务 1,首选) | 文件的编辑权限;远程服务 | use_figma(只读脚本) |
| 读取令牌(备用) | 任意席位 | get_variable_defs |
| 交付组件(任务 2) | 任意席位 | get_design_context、get_metadata、download_assets |
| Code Connect(任务 3) | Organization 或 Enterprise 方案、已发布的库组件 | get_code_connect_suggestions、get_context_for_code_connect、send_code_connect_mappings |
| 写入 Figma(选择启用) | 针对现有文件需要 Full 席位(任意席位均可写入草稿);远程服务;Beta 版 | use_figma、generate_figma_design |
- 优先使用远程服务(
https://mcp.figma.com/mcp)。桌面服务不支持写入、代码转画布或技能。 - 速率限制取决于方案和席位(Starter View/Collab 席位每月只能调用少数几次;Dev/Full 席位每天约 200 次)。
whoami、add_code_connect_map和create_new_file不计入限制。 - 调用因访问、权限或速率限制错误而失败 → 调用
whoami(查看方案和席位),并说明缺少什么,不要重试。 - Figma 自带的技能(
figma-use、figma-design-to-code、figma-code-connect、figma-generate-design)随 Figma 插件提供;没有插件时,可通过 MCP 使用skill://figma/<name>/SKILL.md读取。需要技能的工具会在说明中指出——先加载技能,再传入skillNames。
生命周期流程(先加载此项)。 尚未决定/正在尝试不同方案 →
sb-explore(Lab 沙盒,针对 Figma 节点迭代)→sb-ship(将 Lab 实验投入使用)。已在 Figma 中获批 →sb-figma(直接交付到生产环境)。二者都会使用 Figma MCP;区别在于探索与交付。 如果用户仍在考虑,请转交给sb-explore。参见references/figma-token-sync.md。
从每次运行中学习 — 差距与项目规则
每次运行都从这里开始,也在这里结束:
- 先查看未解决的差距:
node scripts/workbench-settings.mjs gaps。每项都会说明之前的运行无法完成什么,以及如何修复。开始新工作前,先向用户展示这些内容。 - 脚本会在运行过程中记录差距到
.storybook/figma/gaps.json:collision(多个 Figma 变量对应一个令牌)、weak-match(仅按最后一个词匹配)、unmapped-name(没有对应代码令牌的 Figma 变量)、unsupported-value(奇偶校验无法读取的颜色语法)、unmapped-variant-value(没有对应代码值的 Figma 变体值)。后续运行不再发现的差距会标记为已解决。 - 记录只有你能发现的问题: 缺少令牌、你不得不询问其含义的值(
missing-token);Figma 拒绝执行的工具(tool-refused):node scripts/workbench-settings.mjs add --kind missing-token --detail "icon #116932 has no token" --suggestion "…". - 用项目规则修复差距,而不是编辑技能。 规则存放在
.storybook/workbench.json中(创建初始文件:node scripts/workbench-settings.mjs --init;架构:references/workbench.schema.json);该文件归项目所有,因此技能更新不会覆盖它,且命令行标志仍优先:css— 令牌 CSS 的位置 ·darkSelectors— 标记深色主题的内容nameMap—"fg/error": "--color-error-text":优先于名称猜测,并解决冲突ignore— 要排除的 Figma 变量("Size/*") ·variantValues—"status - success": "success"codeConnectLabel— 默认的 Code Connect 标签
- 规则无法修复的问题(不支持的颜色语法、错误结果)→
report-issue.sh --gaps会创建一份已清理的 issue 草稿,其中按类型统计未解决差距的数量——不包含名称或值。
任务 0 — 捕获 MCP 输出(始终先于其他操作)
强制使用原生结构化工具 — 绝不要依据截图操作。 截图只有像素;无法提供变量、样式或组件属性。完整信息只能通过原生 MCP 工具获取,并且在构建或连接之前,必须拉取以下三个类别:
- 变量 →
get_variable_defs(令牌值:颜色/间距/排版/效果,均已解析)。- 组件 + 样式 →
get_design_context(参考代码、应用的样式、属性/变体)。- 结构 →
get_metadata(节点树;如果结果被截断,就深入获取子节点 ID — 绝不要停在父节点)。get_screenshot仅供视觉参考 — 在根据结构化数据构建完成后,用于肉眼比对。绝不要从截图中读取令牌、属性或布局。如果工具在页面 ID 上返回“未选择任何内容”,就深入到具体的组件节点(页面不是图层)。
脚本无法调用 Figma MCP,MCP 结果也只存在于 Agent 的上下文中 — 它们是临时的,下一个会话就会消失,无头模式下也不可用。因此,每次调用 Figma MCP 后,都要先通过通用存储将结果持久化,再使用它。这样才能确保流水线可复现、可迭代。
# pipe each tool's output straight in (JSON, code text and XML are all stored as returned):
<get_variable_defs output> | node scripts/capture-figma.mjs --tool get_variable_defs --file <FILE> --node <NODE> --from-mcp -
<get_design_context output> | node scripts/capture-figma.mjs --tool get_design_context --file <FILE> --node <NODE> --from-mcp -
<get_metadata output> | node scripts/capture-figma.mjs --tool get_metadata --file <FILE> --node <NODE> --from-mcp -
<get_code_connect_map out> | node scripts/capture-figma.mjs --tool get_code_connect_map --file <FILE> --node <NODE> --from-mcp -
# get_screenshot returns an image — save it, then register the file:
node scripts/capture-figma.mjs --tool get_screenshot --file <FILE> --node <NODE> --image /tmp/frame.png
# see the whole inventory (degrade / iterate):
node scripts/capture-figma.mjs --list
存储布局:.storybook/figma/manifest.json + .storybook/figma/<tool>/<node>.json(图像保留原扩展名)。重新捕获同一个 (tool,node) 时会覆盖原内容 — 与 git 中的版本对比,即可查看 Figma 中的改动。后续步骤读取存储内容,绝不重新调用 MCP。
MCP 实际情况(经实测确认于 2026-06-22;工具架构已于 2026-10-01 重新检查)
实时 Figma MCP 实际返回的内容 — 脚本已能处理这些情况;了解这些细节,避免与输出作无谓斗争:
get_variable_defs返回的是扁平的{ "name": "value" }映射(不是嵌套 DTCG,也不是数组)。颜色会直接解析为十六进制值("semantic/background":"#fbfcfc"),包括 8 位 alpha("#e4e5e580")。数字是裸字符串("spacing-2":"8"、"wght/semibold":"650")。排版值是不可解析的Font(family: …, size: …)字符串 —pull-figma-variables会将其解析为{family,size,weight,lineHeight,…}(字段本身也可能是类似size/text-lg的变量名引用)。阴影会返回Effect(…)→ 归入effect类别。classify()根据值进行分类。get_metadata返回 XML,遇到较大的框架时会被截断(某个表格视图超出了令牌限制)。如果结果被截断:从不完整的 XML 中读取子节点 ID,然后对子节点调用get_design_context/get_metadata,不要对父节点调用。将每个子节点都捕获到存储中,避免重复获取。- 节点 ID:URL 使用
1-6965,API 示例使用1:6965;所有工具都接受两种格式。capture-figma会以带连字符的格式保存捕获结果,因此两种格式都能找到。每个工具还需要从 URL 中获取fileKey(figma.com/design/<fileKey>/…;如果是分支 URL,则使用分支键)。 get_design_context默认返回代码文本和截图;get_metadata返回 XML。 只有get_variable_defs和use_figma读取脚本返回 JSON。- 任务 0 已解决持久化及截图↔节点关联问题 — 存储会将每个输出及其节点 ID 保存在清单中,因此无需手动交叉引用截图,也无需重新调用 MCP(这两点过去都确实造成了阻碍)。
各项任务(均读取任务 0 的存储内容)
作业 1 — 基础令牌 → Foundations/Colors|Tokens|Type(sb-figma 直接写入这些内容)
没有其他技能会将 Figma variables 映射为代码令牌,因此 sb-figma 负责端到端实现基础令牌的一致性。
- 读取变量 — 每种模式都要读取。 首选:加载 Figma 的
figma-use技能(或skill://figma/figma-use/SKILL.md资源),然后将references/read-figma-variables.js的内容作为code,并将skillNames: "figma-use"传给use_figma。它只读取数据:每个本地集合、每种模式(Light、Dark、……),并解析别名。大型系统(输出上限约为 20 kB):将ONLY设为一个集合,并对每个集合调用一次。保存结果(作业 0)。 如果无法运行use_figma(没有文件编辑权限),则使用备用方案:对使用这些令牌的节点调用get_variable_defs。它只返回该节点使用的变量,且仅限一种模式——不会对比深色模式。 对于文件使用但不归其所有的库变量:调用get_libraries,然后使用{"entity":"variable", …}调用search_design_system。 - 规范化 —
node scripts/pull-figma-variables.mjs --from-mcp .storybook/figma/<tool>/<NODE>.json --out .storybook/figma-variables.json。 它接受任一格式;默认模式会填充color/spacing/type,其他模式会写入modes。 如果未指定--from-mcp,则会重用上次的缓存(无头模式降级路径)。 - 构建一致性对比 —
node scripts/build-token-parity.mjs --variables .storybook/figma-variables.json --css <token-css-glob> --out .storybook/figma-token-parity.json。 CSS 会按主题读取::root是默认主题,.dark/[data-theme=dark]/ 深色@media块是深色主题。Figma 的默认模式会与默认主题比较,Figma 的 “Dark” 模式会与深色主题比较(输出中的modes.Dark)。OKLCH 通道三元组会解析为十六进制值;semantic/*会映射到项目的--token,并沿着var()别名链解析。 - 接入基础令牌故事 — 将
figmaParity传给TokenMatrix(它会读取figma-token-parity.json),以便在颜色表格的问题列中显示偏差(悬停时显示figma Δ、code #X vs figma #Y)。这些字段是可选的:没有 Figma 文件的项目仍会按原样渲染。 - 在 sb-health 格式中报告偏差:Figma 值 ≠ 代码值(颜色采用 OKLCH→十六进制容差,间距/类型要求完全一致),并按模式区分;仅应用中使用的角色(
--popover、--ring、……)属于预期情况,不算失败。
任务 2 — 已批准的 Figma 组件 → 生产环境(sb-figma 负责交付;sb-stories 负责编写)
- 先确定交付规模 — 将大型画板拆分。 多画板功能(完整流程、包含许多区块的屏幕)会超出 MCP 令牌预算。按画板或区块拆分:交付、验证并记录一部分,然后再处理下一部分。Figma Inventory(步骤 8)会合并各部分的 stories。
- 加载 Figma 的设计转代码指南。
get_design_context现在要求提供该指南:使用/figma-design-to-code技能(Figma 插件),或读取skill://figma/figma-design-to-code/SKILL.mdMCP 资源,并在调用时传入skillNames: "figma-design-to-code"(从资源读取时传入"resource:figma-design-to-code")。设置clientFrameworks/clientLanguages(例如react、typescript)。 - 提取(到 Job 0 存储区)。 一次
get_design_context调用会返回参考代码、资源下载 URL 和屏幕截图;请将其保存。如果返回的只有元数据(内容过大),请获取其中列出的子节点,而不是父节点。仅需要结构时,get_metadata会提供树形结构。 - 先复用,再构建。 Code Connect 映射的组件会在设计上下文中以实际导入项的形式返回,请使用它们。否则,搜索是否有涵盖相同概念的现有组件,并对其进行扩展(guardrails §8 步骤 3);
search_design_system可按名称查找组件库中的组件。 - 资源。 优先使用项目中已有的精确匹配资源(例如应用所用图标包中的同一图标)。否则,按照
get_design_context响应中的说明下载每项资源,并放入项目的资源文件夹。不要使用占位符,不要新增图标包,也不要在代码中留下临时 Figma 资源 URL。 - 仅使用已批准的令牌和基元进行构建 — 使用令牌,不用魔法数字。Figma 值没有对应令牌 → 停止并询问(缺少令牌的任务:Job 1 或用户)。参考代码是供调整的起点,不是直接粘贴的内容。
- 按照
sb-stories的约定编写 story(仅覆盖有实质差异的状态;3 个或更多 story 共享相同结构时使用工厂),在文件顶部注释和parameters.design中标注节点 ID(Shared plumbing),然后对照保存的屏幕截图验证浅色 / 深色 / 移动端效果。 - 在 Figma Inventory 中记录交付内容 — 这样此功能创建的 stories 就不会散落在分类体系中。此操作是幂等的;每次交付后重新运行,stories 会按 id 合并:
然后确保根级界面存在:使用python3 scripts/record-figma-delivery.py . \ --figma-url "<board url>" [--feature "<Name>"] --spec-url "<spec node url>" --node-ids 101-9717 \ --description "<one line>" \ --story "Hunts/Hunt Packs:hunts-hunt-packs--default:component" # repeat per story you createdscaffold-wrapper.sh --figma进行一次脚手架搭建,放入figma-inventory.stories.tsx模板(标题为Figma Inventory),每个功能添加一个导出项(export const Hunts = { args: { feature: 'Hunts' } }),并通过.storybook/preview中的options.storySort.order: ['Figma Inventory', '*']将其固定在顶部。FigmaInventorywrapper 会读取figma-inventory.json,并渲染索引、各功能的画板链接,以及该功能引入的 stories。
任务 3 — 连接:Storybook → Figma(代码 → 设计)
将代码中的真实情况同步回 Figma,让 Figma Dev Mode 显示你的真实组件。Code Connect 需要 Organization 或 Enterprise 计划以及已发布的库组件(参见前置条件)。按照 Figma 的顺序操作;每次调用都通过任务 0 的存储进行:
- 检查访问权限 —
whoami。没有 Org/Enterprise 计划 → 停止并说明;Dev Mode 不会显示映射。 - 查找组件 — 在页面或画板上调用
get_code_connect_suggestions(对于精简的未映射组件列表,设置excludeMappingPrompt: true)。 - 读取每个组件 — 针对每个组件节点调用
get_context_for_code_connect:获取其属性、变体选项和后代节点。将它与代码组件匹配(带有该节点parameters.design的 story 是最强信号;否则使用组件名称)。 - 构建负载 — 写入
comps.json(component、codeFile、figmaNode、可选的componentName、label、tokens、variantProperties、modes),然后:node scripts/build-code-connect.mjs --components comps.json --file <FILE_KEY> \ --parity .storybook/figma-token-parity.json --usage .storybook/component-usage.json \ --out .storybook/code-connect.jsonsend是精确的send_code_connect_mappings输入(fileKey、nodeId、mappings[{nodeId, componentName, source, label}]);context包含用于审查的 tokens、实际属性和变体 → 属性映射;reverseParity列出没有 Figma 节点或没有来源的组件、不受支持的标签以及不一致的 tokens。 - 确认后再发送 — 向用户展示映射;获得批准后,原样使用
send调用send_code_connect_mappings。只有一个映射时,也可以使用add_code_connect_map。两者都会写入 Figma。 - 属性级代码片段(可选) — 普通映射会显示导入和组件。要映射属性(变体选择器 → 代码属性),请编写 Code Connect 模板:适用于
@figma/code-connectCLI 2.x 的Component.figma.ts(自 2.0 起,模板文件是唯一维护的格式;.figma.tsx+figma.connect()仅用于迁移),或在映射中传入template。Figma 的/figma-code-connect技能介绍了模板;context[].propMappings是其输入。
没有 Figma 节点的组件(componentsWithoutNode)没有可连接的对象;创建它们属于写入操作(见下文)。
闭环如下:交付时(任务 1–2)添加的 parameters.design 节点 ID,正是任务 3 用来回连的内容。
写入 Figma(可选加入,默认关闭)
仅在用户明确提出请求时操作,并且每次写入前都要确认——这会修改他们的文件。现有文件需要 Full 席位(参见前置条件)。
- 默认使用
use_figma(先加载figma-use,设置skillNames: "figma-use")。根据文件自身的组件和变量构建(search_design_system),返回并记录每个已创建节点的 ID。 - Tokens → Figma 变量(创建集合或更新集合,包含 Light + Dark):
将一个条目作为node scripts/build-figma-variables.mjs --css "src/**/*.css" --prefix "--color-bg,--color-text-" \ --collection "Code tokens" --out .storybook/figma-variables-push.jsonPAYLOAD粘贴到references/write-figma-variables.js,并通过use_figma运行——先设置DRY = true:它会返回将要创建和更新的内容。向用户展示结果,然后设置DRY = false运行。它会复用同名集合或变量并覆盖其值;不会删除任何内容。通过任务 1 检查:读回集合并运行一致性检查,应显示零偏差。 - 仅在首次捕获渲染页面时使用
generate_figma_design— 例如,单独渲染的 story:http://localhost:6006/iframe.html?id=<story-id>&viewMode=story。它会生成像素副本;使用use_figma基于库组件对其进行优化。更新已捕获的页面 → 使用use_figma。 - 写入后,将新节点 ID 写回 story 的
parameters.design,这样任务 2–3 就能看到它。
共享基础设施 — Figma 设计嵌入(文档)
sb-figma 涉及的每个 story 都会在其目录页面中保留设计来源:
parameters: { design: { type: 'figma', url: 'https://figma.com/file/<FILE_ID>?node-id=<NODE_ID>' } }
这是 @storybook/addon-designs(“Design”选项卡——与 sb-explore 用于画板的机制相同)。此外,还会在 parameters.docs.description 中添加节点 ID 标记和链接。只要知道节点 ID,sb-explore 和 sb-stories 就可以复用此代码片段。
边界——绝不重复同级工具的职责
- 探索 /“试试 v2” / 尚未决定 →
sb-explore(Lab)。sb-figma 仅用于已批准的设计。 - 将 Lab 实验升级 →
sb-ship(保留cp,重写调用点)。sb-figma 从 Figma 交付,而不是从/explore/实验交付。 - 记录现有代码组件(无 Figma) →
sb-stories。sb-figma 会调用 sb-stories 的规则来 编写;绝不会重新实现这些规则。 - 代码内部的令牌健康状况 / 孤立项 →
sb-health/sb-inventory(不涉及 Figma)。sb-figma 补充它们无法看到的 设计↔代码一致性。
Agent 必须先确认的输入
- Figma 文件 URL → 所有工具都需要的
fileKey;任务 2–3 还需要节点 URL(get_variable_defs回退方案也需要:一个使用这些令牌的框架)。如果用户未粘贴,请询问。 - 令牌 CSS 路径——
--token: <value>声明所在的位置(例如src/styles/**/*.css)。 - 设计是否已获批准? 如果用户仍在迭代 → 停止,转交给
sb-explore。 - 任务 3 和写入操作所需的计划和席位——参见前置条件(
whoami)。
后续步骤
先运行任务 1(令牌),这样任务 2 中构建的组件才能使用经过真实、一致性校验的令牌。将进度追加到
.storybook/audit/status.md,以便顺利恢复。完整调用顺序及 OKLCH→hex 说明:
references/figma-token-sync.md。