mcpField
F
figma-codegen

figma-codegen

github.com/awdr74100设计与 UI1.2k1.4k 次安装今天更新
代码仓库

关于 figma-codegen

figma-codegen 是一项将 Figma 选区转换为项目代码的技能,面向需要让实现贴合现有代码库的开发者。它通过读取设计结构、组件和令牌映射来优先复用现有实现,并支持按设计差异增量同步。

主要功能

  1. 01读取 Figma 结构与设计令牌
  2. 02将设计组件映射到代码组件
  3. 03复用项目令牌和样式
  4. 04导出图像资源并匹配图标
  5. 05检测设计变更并增量更新代码
  6. 06记录已确认的组件与令牌映射

适用场景

  1. 01根据 Figma 选区实现界面组件
  2. 02将设计稿适配到现有项目组件
  3. 03设计更新后仅修改对应代码
  4. 04为重复使用的映射建立记录

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/awdr74100/figwright --skill figma-codegen

安装后在 Claude Code 中输入/figma-codegen确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
assets-and-icons.md
grounding.md
motion.md
responsive.md
stylesheets.md
verify.md

详细介绍

figma-codegen

将 Figma 选区转换为代码,使其风格与项目其余部分一致:复用现有组件和设计令牌,只构建真正缺失的部分。基于实际设计信息的工具会承担大部分工作,因此你无需对着截图猜测。本文件是路由入口;详细内容位于 references/ 中——当某个步骤需要时,再加载对应参考文档。

适用场景

  • 用户粘贴 Figma URL 或选区,并要求生成代码(“把这个写成代码”“构建这个组件”)。
  • 用户希望扩展现有组件,使其与 Figma 画板一致。

同时打开多个 Figma 文件时

适用时,每个工具结果都会说明这一点,因此你无需预先检查:如果连接了两个或更多文件,且尚未指定要使用哪个文件,结果中就会包含一个 MORE THAN ONE FIGMA FILE IS OPEN 区块,并列出这些文件。之所以重要,是因为否则调用会使用用户上次操作的文件,而用户切换标签页时,这个文件也会随之改变——因此,任务可能会读取一个文件、写入另一个文件,却仍报告成功。

看到该提示时,先指定文件,再进行其他操作:list_files 会列出所有已连接的文件,use_file({ fileName }) 会为本次会话指定一个文件(如果两个打开的文件同名,则使用 use_file({ sessionId })——Figma 允许这种情况,x (Copy) 就是这样产生的)。之后的每次调用都会访问该文件,无论哪个文件处于前台,包括其标签页位于后台时。如果用户没有说明要使用哪个文件,请先询问,不要根据文件名猜测。

工作流

针对选区运行基于实际设计信息的工具,然后生成代码——以这些工具的结果为准,而不是渲染图像。

  1. get_design_context(详情级别 full,dedupeComponents: true)→ 获取结构树,其中的设计令牌已解析为名称(Primary/500、spacing/4),样式已去重到 globalVars,且每个实例都包含 mainComponent / componentProperties。这是布局和绑定的事实来源。保留 dedupeComponents: true,不要对要构建的子树进行深度限制。 → 关于如何读取结构树、各节点保真度目录(效果、逐边框线、描边对齐、逐角圆角、混合、蒙版、渐变、图像适配、图案、Figma Draw 重复组/笔刷描边/路径文字、自动布局/网格、宽高比、滚动/粘性、堆叠与描边空间)、作为事实依据的 Dev Mode 注释,以及如何为大到无法通过单次调用处理的页面建立设计依据:references/grounding.md。
  2. component_map → 每个 Figma 组件都会与一个本地代码组件关联,并附带 status (high / medium / low / unmapped)、candidate.filePath 和 matchedProps。
    • high / medium:复用该组件(从 candidate.filePath 导入),不要重新生成。 绝不要编造 component_map 未报告的组件名称。
    • candidate.ambiguousWith(一个经过数量限制的 { name, filePath } 列表):Figma 名称与两个或更多 代码组件的匹配度几乎相同,关联过程无法有把握地选出一个——这是一个需要核实的选项, 而非确定可复用的组件(类似于 token_map 的 ambiguousWith)。导入前,先检查获胜的 candidate 与这些次选项中,哪个才适用于_当前_上下文(错误复用会造成不易察觉的视觉错误), 然后将确认的组件记录到映射文件中,以确保下次运行时结果明确。如果选择没有歧义,则不会出现此字段。
    • 将每个条目的 instances[].props(解析后的变体/布尔/文本值)传给复用组件——每个实例对应一个元素, 且各自拥有自己的 props。
    • candidate.unmatchedProps:组件没有对应 prop 的 Figma 轴(例如前置图标、required 标志或激活状态)→ 将其列为组件扩展 TODO,绝不要用临时标记语言伪造。
    • unmapped:按照项目风格新建。如果一个未映射组件会重复出现 (instanceCount > 1),则从其第一个实例的子树构建;如果该子树返回 deduped / truncated,则对 instances[0].nodeId 调用一次 get_design_context 深入检查——不要凭直觉重建 重复组件。
    • 输出组件的自身定义(其 prop 类型,而不只是渲染它)时,对该组件/实例调用 get_component_api 可获得完整的属性 API——包含每个 VARIANT 选项,以及每个 BOOLEAN/TEXT/INSTANCE_SWAP prop 及其默认值——因此 prop 范围有依据,而非根据碰巧看到的实例推断。
    • 该 API 会命名 props;树则会命名每个 prop 所驱动的图层。COMPONENT 或 INSTANCE 内的子图层带有 componentPropertyReferences ({ characters | visible | mainComponent: "PropName#1:2" })。将该图层连接到 prop,而不是连接到它 恰好渲染出的内容:characters: "Label#1:2" 对应 {props.label},而不是设计中的字面字符串;visible: "Show Badge#3:4" 则会控制条件渲染。如果没有这一步,你输出的标记语言虽然正确,却会完全没有 props——每个实例都会被冻结为你看到的那个实例的状态。
  3. token_map → 每个 Figma 变量都会与一个项目令牌关联,并附带 status + ref + matchedBy。 文档的共享填充样式(单色填充样式——变量出现前文件中的令牌机制)也以同样方式关联,并标记为 source: 'style'。
    • mapped:引用 candidate.ref(bg-primary-500、var(--color-primary-500))——绝不要使用 get_design_context 解析出的原始 hex/px 值。若某个颜色通过 matchedBy: ['name'] 匹配(值已发生偏移),则使用它,但要标记出不匹配。
    • candidate.ambiguousWith(多个项目令牌共享完全相同的值,且名称无法区分它们):这是一个有数量上限、需验证的候选项——根据上下文选择语义上正确的同类令牌(或保留该值并指出缺口),绝不要将其视为已确认复用。
    • 对于变量很少或没有变量的文档(大多数真实项目文件都如此),get_design_context 自带的 projectTokens 映射是备用方案:负载中任何与项目令牌值完全相同的原始颜色,都会在此处加上注释({ "#6266F0": { ref, name, matchedBy: ["value"] } })。硬编码 hex 之前,先查找它;若在语义上符合上下文,则输出 ref。 matchedBy: ["value"] 表示这是不考虑名称、基于值相等得出的证据——只是有待验证的假设,并非已解析的绑定:带有 candidates 的条目会列出值相同的令牌,需根据含义从中选择;语义上错误的令牌比原始值更糟(应保留原始值并指出缺口),而已绑定的 Figma 变量始终优先于原始值匹配。
    • framework-builtin(项目实用工具框架内置的比例步长,例如 Tailwind 或 UnoCSS 中的 spacing/4、line-height/7、weight/Bold):包含 builtin: { scale, step }——组合使用实用工具(p-4/gap-4、leading-7、font-bold),不要使用任意值 p-[16px]。这不是缺口。
    • from(SCSS 变量):仅靠该引用无法解析。你编写的文件必须导入声明该变量的文件;而且 from 是相对于仓库根目录的路径,Sass 则相对于导入它的文件解析 @use——因此要从你正在编写文件的位置重新解析:在 src/components/card.scss 中,from: src/styles/_tokens.scss 应转换为 @use '../styles/tokens' as *,绝不能原样使用相对于仓库根目录的路径。as * 会让引用保持原样;也可以遵循项目自身的 @use 风格使用命名空间(@use '../styles/tokens' 会将 $color-primary-500 转换为 tokens.$color-primary-500)。未导入文件就输出引用会导致编译错误,不只是样式问题。
    • unmapped:使用该值,但要指出缺口(并提出将其添加到令牌来源);不要悄悄硬编码。
    • figmaModes({ Light: …, Dark: … },文件的主题轴位于 themedCollections 中):该令牌依赖主题——figmaValue 仅代表默认模式,并非全部情况。已映射:输出 candidate.ref,并确认项目令牌本身会随主题切换(.dark / [data-theme] / prefers-color-scheme / dark: 方案);如果项目只定义了一个值,则将另一模式的值接入该机制,或指出主题缺口。未映射:默认模式作为基础值,其他模式通过项目的深色模式机制处理(dark: 变体 / prefers-color-scheme)。通过不具备原生模式的方式编码的主题——成对集合或名称组(Color/Light/* + Color/Dark/*,这是受方案限制的变通方式)——也按同样方式处理。带有 variableModes({ color: "Dark" })的节点是在该模式下绘制的:令牌名称相同,使用该模式的值。保留令牌引用,并将子树放在该模式对应的项目机制之下;同一元素的 Light 和 Dark 画面是一个组件在两种主题下的呈现。 → references/grounding.md。
  4. 导出 grounding 无法承载的资源——Logo、照片、图标没有像素,否则会渲染为灰色块。对于 IMAGE 填充节点,使用 save_image_fills(原始资源,而不是裁剪后重新渲染的版本);图标优先使用 icon_map(复用精选的 .svg);只有需要合成后的效果时才使用 get_screenshot。 → 完整的资源/图标/svg/颜色契约工作流: references/assets-and-icons.md。

然后使用检测到的技术栈输出代码(技术栈信息会通过 component_map / token_map 返回;无需自行调用 analyze_project):组合复用的组件,封装未映射的部分,并应用颜色/间距/圆角/字体排版的 token 引用。

设计变更时保持代码同步

代码生成很少一次完成——设计会不断变化。为了让第二次处理成为增量编辑,而不是重新生成:

  • 生成代码后,针对区块/组件的 nodeId 执行 design_diff,将其 get_design_context 保存为基线,存放在 .figwright/snapshots/ 下。提交该文件后,团队成员即可共享基线;该工具不会操作 git。
  • 需要重新同步时(“设计变了,更新组件”),再次对同一个 nodeId 执行 design_diff:它会返回逐节点、逐属性的差异——包含已添加 / 已移除 / 已更改节点及其解析后的值(填充、内边距、文本字符串、token 重新绑定等),每项都有易读的 path(Card / Header / Title)。只编辑这些节点对应的代码;不要重新生成整个屏幕。像往常一样根据变更值进行 grounding(它是 get_design_context 的切片),然后使用 update: true 执行 design_diff,将新设计设为基线。
  • 使用你编写代码时相同的 nodeId 单位来限定范围。no-changes 表示自基线以来设计未变更——无需处理。
  • Motion 除外。 快照是完整且去重后的 get_design_context,其中只包含 Motion 摘要(预设名称、动画字段名称、时间线长度)——因此,变化的关键帧时间、值或缓动,或预设的配置或属性,都可能返回 no-changes;去重时被折叠的实例子节点则完全不包含摘要。要重新同步动画,请在根节点上重新运行 get_motion_context,并与代码实现进行比较。

记录已验证的映射(让下一次运行复用,而不是重新猜测)

每次运行都会从头重新推导关联。你确认过的映射——例如复用了某个组件并验证渲染正确,或将有歧义的颜色解析为语义正确的令牌——值得记录下来,这样下一次运行就会将其视为事实依据,而不是重新猜测。有两个只追加、不覆盖的映射文件,每次关联都会读取它们,并将其视为最高优先级依据:

  • docs/figma-component-map.md — 行格式为 | FigmaName | code/path |(或 FigmaName -> path)。 component_map 随后会以 source: 'map-file'、置信度为 1 的形式返回该组件。

  • docs/figma-token-map.md — 行格式为 | FigmaName | ref |。token_map 会以 matchedBy: ['map-file']、置信度为 1 的形式返回该令牌。ref 是你要输出的内容——工具类(bg-primary-500)、 var(--color-primary-500),或不带修饰的令牌名称。

  • 已记录的行会在所有后续运行中覆盖模糊关联——因此要记录经过验证的结果,而不是猜测。 门槛是你自己的验证步骤(§ 响应式与验证):只有在渲染结果并确认其与 Figma 节点匹配后,才记录你_验证过_的映射。错误的行不会显式报错——它会在之后每次生成时静默地将组件或令牌映射错误,直到有人发现,这比完全不记录更糟。如果你不确定,就不要记录;下一次运行重新猜测还可以补救,而记录了一个确信无疑但错误的映射则无法补救。

  • 只记录关联结果不确定的映射——你确认过的 low/medium 组件匹配、你构建的 unmapped 组件(记录其新文件),或返回 ambiguousWith / matchedBy: ['value'] / unmapped 并由你根据含义解决的令牌。跳过已经是 high 的确定性匹配;它们能正确地重新推导,为它们添加行只会造成冗余。

  • 这些文件是项目中会提交的文档——应像断言代码行正确那样对待每一行,而不是将其视为临时笔记。每行对应一个 Figma 名称 → 一个目标;保持内容便于审查。

  • 保持文件内容有效。 当 component_map / token_map 报告 staleOverrides(记录的目标已无法解析——文件或令牌已重命名或删除)时,关联已退化为模糊结果;请将该行修正为新目标,或删除该行。

响应式与验证

  • 默认采用响应式布局——根元素使用 w-full,绝不使用画板的固定宽度;根据文件中其他宽度的画框确定断点。→ references/responsive.md。
  • 完成前先进行视觉验证——使用项目的工具链进行渲染,在设计的视口尺寸下截图,与 Figma 节点进行差异比较,并从源头修复问题。 → references/verify.md。

动效(动画)

对于每个实现的根节点,都调用一次 get_motion_context:它会盘点子树中的所有 Motion 来源(包括实例子节点),并说明哪些内容无法读取。只有当 coverage.status: "complete" 且没有节点时,才能确认没有动画——get_design_context 中的 motion 摘要只是提示,可以在去重和预算时忽略。使用项目自身的动画机制实现其返回的内容,按照参考文档中经测量得出的规则进行读取;对于未明确说明的内容(轨道如何组合、循环或触发),将其视为你的假设并予以说明,然后根据源文件验证结果。遗漏画框的动画属于保真度缺失,与遗漏阴影性质相同。 → references/motion.md。

规则

  • 每个区块都要依据设计信息,绝不能凭截图估值。 所有像素尺寸、颜色、字号、圆角和间距,都必须针对每个区块从 get_design_context 获取。截图仅用于表达视觉意图;猜测“简单区块”的值是最严重的疏漏。如果页面过大,无法一次性获取完整设计信息,就按区块的 nodeId 限定范围——绝不能对整个页面设置深度上限,也绝不能重试超出限制的调用。
  • 复用优于重新生成。 必须导入并使用 component_map 中 high/medium 级别的候选项。
  • 引用设计令牌,不要使用字面值。 输出映射变量的 ref;仅在 unmapped 缺项时使用原始值,并明确指出这些缺项,不要将其隐藏。
  • 保留所有视觉属性,不能牺牲还原度。 效果、各边框及其 strokeAlign、各个角的圆角、混合模式、蒙版、渐变、图片 scaleMode、图案平铺、重复组中的副本(repeatTransforms),以及自动布局/网格间距,都包含在上下文中——逐项转换(属性目录见 references/grounding.md)。遗漏任何属性都是设计信息获取不到位,而非简化:重复组只绘制一次,就像一个有 12 个刻度的刻度盘只画了一个刻度。
  • 导出视觉资源,不要伪造。 灰色方框或手动输入的文字标识都不合格。
  • 匹配项目,而非套用固定风格。 遵循现有的导入风格、文件布局和命名方式。
  • 完整写出类名;不要用 & 拼接。 在 & 用于拼接的语言(SCSS / Sass / Less / Stylus / postcss-nested)中,.card { &__title {} } 会编译为 .card__title——这个名称只在编译后存在,因此标记中使用的类名不会出现在源码里;调整一条规则时,就得搜索 __title 这样的片段并逐一检查所有匹配项。应在顶层直接声明完整类名。profile.styling.classNaming(位于 component_map / token_map 中)会报告项目自身的惯例,以项目为准:ampersand → 使用 &__title;flat 或未提供时 → 直接写出完整类名。 → references/stylesheets.md 介绍了看似可行、实则无效的后代选择器陷阱,以及 & 适用的场景。
  • 完成前先渲染并验证。(参见 references/verify.md。)
  • 绝不编写配置文件或向导提示词;所有信息都应从项目和工具推断得出。

评论

支持 Markdown