mcpField
S
sb-figma

sb-figma

github.com/strongeron设计与 UI3974 次安装4 周前更新
代码仓库

关于 sb-figma

sb-figma 是面向 Storybook 项目的 Figma 交付技能,将已批准的设计数据整理为生产组件,并把代码与设计的差异反馈到 Figma 流程中。它还支持变量令牌对齐和 Code Connect 映射。

主要功能

  1. 01捕获并持久化 Figma MCP 输出
  2. 02比较 Figma 变量与代码令牌
  3. 03将已批准的组件交付到 Storybook
  4. 04处理 Code Connect 映射
  5. 05记录差异并维护项目规则

适用场景

  1. 01从已批准的 Figma 设计构建生产组件
  2. 02检查不同主题下的设计令牌差异
  3. 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.md
agents/
openai.yaml
decorators/
withLayoutFrame.tsx
references/
figma-token-sync.md
read-figma-variables.js
workbench.schema.json
write-figma-variables.js
scripts/
build-code-connect.mjs
build-figma-variables.mjs
build-token-parity.mjs
capture-figma.mjs
css-tokens.mjs
pull-figma-variables.mjs
record-figma-delivery.py
workbench-settings.mjs
templates/
figma-inventory.stories.tsx
wrappers/
FigmaInventory.tsx
icons.tsx
ReportIntro.tsx
resolve-paint.ts
TokenMatrix.tsx
TokensCanvas.tsx
usage-index.tsx
usage-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。

从每次运行中学习 — 差距与项目规则

每次运行都从这里开始,也在这里结束:

  1. 先查看未解决的差距: node scripts/workbench-settings.mjs gaps。每项都会说明之前的运行无法完成什么,以及如何修复。开始新工作前,先向用户展示这些内容。
  2. 脚本会在运行过程中记录差距到 .storybook/figma/gaps.json:collision(多个 Figma 变量对应一个令牌)、weak-match(仅按最后一个词匹配)、unmapped-name(没有对应代码令牌的 Figma 变量)、unsupported-value(奇偶校验无法读取的颜色语法)、unmapped-variant-value(没有对应代码值的 Figma 变体值)。后续运行不再发现的差距会标记为已解决。
  3. 记录只有你能发现的问题: 缺少令牌、你不得不询问其含义的值(missing-token);Figma 拒绝执行的工具(tool-refused): node scripts/workbench-settings.mjs add --kind missing-token --detail "icon #116932 has no token" --suggestion "…".
  4. 用项目规则修复差距,而不是编辑技能。 规则存放在 .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 标签
  5. 规则无法修复的问题(不支持的颜色语法、错误结果)→ 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 负责端到端实现基础令牌的一致性。

  1. 读取变量 — 每种模式都要读取。 首选:加载 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。
  2. 规范化 — node scripts/pull-figma-variables.mjs --from-mcp .storybook/figma/<tool>/<NODE>.json --out .storybook/figma-variables.json。 它接受任一格式;默认模式会填充 color/spacing/type,其他模式会写入 modes。 如果未指定 --from-mcp,则会重用上次的缓存(无头模式降级路径)。
  3. 构建一致性对比 — 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() 别名链解析。
  4. 接入基础令牌故事 — 将 figmaParity 传给 TokenMatrix(它会读取 figma-token-parity.json),以便在颜色表格的问题列中显示偏差(悬停时显示 figma Δ、code #X vs figma #Y)。这些字段是可选的:没有 Figma 文件的项目仍会按原样渲染。
  5. 在 sb-health 格式中报告偏差:Figma 值 ≠ 代码值(颜色采用 OKLCH→十六进制容差,间距/类型要求完全一致),并按模式区分;仅应用中使用的角色(--popover、--ring、……)属于预期情况,不算失败。
任务 2 — 已批准的 Figma 组件 → 生产环境(sb-figma 负责交付;sb-stories 负责编写)
  1. 先确定交付规模 — 将大型画板拆分。 多画板功能(完整流程、包含许多区块的屏幕)会超出 MCP 令牌预算。按画板或区块拆分:交付、验证并记录一部分,然后再处理下一部分。Figma Inventory(步骤 8)会合并各部分的 stories。
  2. 加载 Figma 的设计转代码指南。 get_design_context 现在要求提供该指南:使用 /figma-design-to-code 技能(Figma 插件),或读取 skill://figma/figma-design-to-code/SKILL.md MCP 资源,并在调用时传入 skillNames: "figma-design-to-code"(从资源读取时传入 "resource:figma-design-to-code")。设置 clientFrameworks/clientLanguages(例如 react、typescript)。
  3. 提取(到 Job 0 存储区)。 一次 get_design_context 调用会返回参考代码、资源下载 URL 和屏幕截图;请将其保存。如果返回的只有元数据(内容过大),请获取其中列出的子节点,而不是父节点。仅需要结构时,get_metadata 会提供树形结构。
  4. 先复用,再构建。 Code Connect 映射的组件会在设计上下文中以实际导入项的形式返回,请使用它们。否则,搜索是否有涵盖相同概念的现有组件,并对其进行扩展(guardrails §8 步骤 3);search_design_system 可按名称查找组件库中的组件。
  5. 资源。 优先使用项目中已有的精确匹配资源(例如应用所用图标包中的同一图标)。否则,按照 get_design_context 响应中的说明下载每项资源,并放入项目的资源文件夹。不要使用占位符,不要新增图标包,也不要在代码中留下临时 Figma 资源 URL。
  6. 仅使用已批准的令牌和基元进行构建 — 使用令牌,不用魔法数字。Figma 值没有对应令牌 → 停止并询问(缺少令牌的任务:Job 1 或用户)。参考代码是供调整的起点,不是直接粘贴的内容。
  7. 按照 sb-stories 的约定编写 story(仅覆盖有实质差异的状态;3 个或更多 story 共享相同结构时使用工厂),在文件顶部注释和 parameters.design 中标注节点 ID(Shared plumbing),然后对照保存的屏幕截图验证浅色 / 深色 / 移动端效果。
  8. 在 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 created
    
    然后确保根级界面存在:使用 scaffold-wrapper.sh --figma 进行一次脚手架搭建,放入 figma-inventory.stories.tsx 模板(标题为 Figma Inventory),每个功能添加一个导出项(export const Hunts = { args: { feature: 'Hunts' } }),并通过 .storybook/preview 中的 options.storySort.order: ['Figma Inventory', '*'] 将其固定在顶部。FigmaInventory wrapper 会读取 figma-inventory.json,并渲染索引、各功能的画板链接,以及该功能引入的 stories。
任务 3 — 连接:Storybook → Figma(代码 → 设计)

将代码中的真实情况同步回 Figma,让 Figma Dev Mode 显示你的真实组件。Code Connect 需要 Organization 或 Enterprise 计划以及已发布的库组件(参见前置条件)。按照 Figma 的顺序操作;每次调用都通过任务 0 的存储进行:

  1. 检查访问权限 — whoami。没有 Org/Enterprise 计划 → 停止并说明;Dev Mode 不会显示映射。
  2. 查找组件 — 在页面或画板上调用 get_code_connect_suggestions(对于精简的未映射组件列表,设置 excludeMappingPrompt: true)。
  3. 读取每个组件 — 针对每个组件节点调用 get_context_for_code_connect:获取其属性、变体选项和后代节点。将它与代码组件匹配(带有该节点 parameters.design 的 story 是最强信号;否则使用组件名称)。
  4. 构建负载 — 写入 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.json
    
    send 是精确的 send_code_connect_mappings 输入(fileKey、nodeId、mappings[{nodeId, componentName, source, label}]);context 包含用于审查的 tokens、实际属性和变体 → 属性映射;reverseParity 列出没有 Figma 节点或没有来源的组件、不受支持的标签以及不一致的 tokens。
  5. 确认后再发送 — 向用户展示映射;获得批准后,原样使用 send 调用 send_code_connect_mappings。只有一个映射时,也可以使用 add_code_connect_map。两者都会写入 Figma。
  6. 属性级代码片段(可选) — 普通映射会显示导入和组件。要映射属性(变体选择器 → 代码属性),请编写 Code Connect 模板:适用于 @figma/code-connect CLI 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.json
    
    将一个条目作为 PAYLOAD 粘贴到 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。

评论

支持 Markdown