mcpField
F
figma-generate-design

figma-generate-design

github.com/figma设计与 UI2.1k6.0k 次安装今天更新
代码仓库

关于 figma-generate-design

figma-generate-design 是用于在 Figma 中创建或更新组合式界面视图的技能,面向依据代码或描述制作界面的设计与开发流程。它强调复用已发布设计系统中的组件、变量和样式,并要求产物由可编辑图层构成。

主要功能

  1. 01创建或更新组合式界面
  2. 02复用设计系统组件与变量
  3. 03发现并应用 Code Connect 资源
  4. 04通过网页捕获辅助界面还原

适用场景

  1. 01依据现有代码构建界面
  2. 02更新已有 Figma 屏幕
  3. 03使用设计系统制作多区块视图

MCP 相关

该技能要求连接 Figma MCP 服务,并与 figma-use 配合调用 Figma 工具。

安装

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

$npx skills add https://github.com/figma/mcp-server-guide --skill figma-generate-design

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

附带文件references/componentization.mdreferences/discover-product-font.md

详细介绍

根据设计系统构建/更新屏幕和视图

**严格的交付门槛:**代码转设计的输出必须将 UI 还原为可编辑的文本、组件、图标和层级结构。 将完整 UI 的任何屏幕截图或扁平化渲染仅作为视觉参考:绝不要将其上传或导入到交付成果中,包括用作容器填充或子节点,即使它存在于代码库中,或看起来像素还原度更高。完成前,请检查结果;如果 UI 并非主要由可编辑图层构成,请以语义化方式重新构建,否则报告失败。

使用此技能在 Figma 中创建或更新屏幕、视图和多分区 UI 容器,方法是复用已发布的设计系统——组件、变量和样式,而不是用硬编码值绘制基本图形。这包括完整页面、模态框、对话框、抽屉、侧边栏、面板,以及任何包含多个分区的组合视图。关键在于:Figma 文件可能已发布设计系统,其中的组件、颜色/间距变量以及文本/效果样式都与代码库中的 UI 组件和设计令牌相对应。请找到并使用这些资源,而不是用十六进制颜色绘制方框。

**必须遵守:**在调用任何 use_figma 之前,还必须加载 figma-use。该技能包含关键规则(颜色范围、字体加载等),适用于你编写的每个脚本。

如果可用,请在读取或编辑文件之前,使用 fileKey 和 description 调用 create_session(如有需要,先创建文件),然后在每次接受该参数的调用中(包括后续调用和跨文件操作)原样传递返回的 sessionId。

**使用此技能调用 use_figma 时,skillNames 参数中必须始终包含 figma-generate-design,并以逗号分隔。如果此技能是通过 MCP 资源加载的,则必须为名称添加 resource: 前缀(例如 resource:figma-generate-design)。**此参数用于日志记录,不影响执行。

HTML 转 Figma 的例外情况

在以下情况下,初始创建请使用 html_to_figma:

  • 输入是现有的原始或静态 HTML 文档。直接将其传递给 html_to_figma。
  • 提示要求创建新设计,且没有可供还原的已渲染 UI 实现。请创建独立的 HTML 文档,并将其传递给 html_to_figma。

如果 html_to_figma 不可用,请遵循下方的现有工作流。

技能适用范围

  • 当交付成果是由设计系统组件实例构成的组合式 Figma 视图(新建或更新)时,请使用此技能——包括表单、仪表板、列表、表格、卡片、页眉、面板、对话框、消息预览或其他多分区容器。即使用户将组合视图称为组件,也适用此规则。
  • 如果主要交付成果是用于变体、令牌或发布的可复用库基本组件或基础元素,请改用 figma-generate-library 和 figma-use。
  • 如果用户希望编写 Code Connect 映射,请改用 figma-code-connect。

前提条件

  • 必须已连接 Figma MCP 服务
  • 目标 Figma 文件必须有已发布的设计系统和组件(或可访问团队资源库)
  • 用户必须提供目标 Figma 文件(URL 或 fileKey)。如果用户还没有文件,请先调用 /figma-create-new-file(或调用 create_new_file),并复用返回的 file_key。use_figma 和 generate_figma_design 都需要现有的 fileKey。
  • 要构建或更新的屏幕/视图的源代码或描述

使用 generate_figma_design 的并行工作流(仅限 Web 应用)

如果要构建的界面来自可在浏览器中渲染的 Web 应用,并行采用两种方法可获得最佳效果:

  1. 并行执行:
    • 针对目标 Figma 文件(fileKey),使用此技能的工作流(use_figma + 设计系统组件)开始构建界面。
    • 针对同一个 fileKey 运行 generate_figma_design,将正在运行的 Web 应用截取为像素级精准的屏幕截图,并写入该文件。generate_figma_design 始终需要 fileKey;如果用户还没有 Figma 文件,请先调用 /figma-create-new-file(或调用 create_new_file MCP 工具)获取文件,并将该 file_key 用于此技能和截图捕获。
  2. 两者都完成后: 更新 use_figma 的输出,使其与 generate_figma_design 捕获的像素级精准布局一致。捕获结果提供了应实现的精确间距、尺寸和视觉样式,而 use_figma 输出则包含与设计系统关联的正确组件实例。如果捕获结果中包含图像,请通过从捕获结果的图像填充中复制 imageHash 值,将这些图像转移到 use_figma 输出中(详情请参阅步骤 5)。
  3. 确认效果良好后: 删除 generate_figma_design 的输出——它仅用作视觉参考。

这样便能兼顾两者的优势:generate_figma_design 可确保布局精准到像素,而 use_figma 则提供与设计系统关联且可更新的正确组件实例。

如果源文件包含应用使用的独立内容图像(例如照片、头像、徽标或图标),则必须采用此并行工作流。截图或完整 UI 的扁平化渲染仅是视觉参考,不属于内容图像。 use_figma Plugin API 无法获取外部图像 URL——它只能通过复制文件中现有节点的 imageHash 值来设置图像填充。generate_figma_design 会将所有可见图像栅格化到 Figma 中,从而提供所需的哈希值。如果存在这些内容图像却跳过截图捕获,它们对应的图像框将会留白。

对于非 Web 应用(iOS、Android 等)或更新现有界面,请使用下方的标准工作流。

必需的工作流

请按顺序完成以下步骤。不要跳过任何步骤。

必须满足的要求:

  • 在修改交付成果之前,完成 Code Connect 发现并选择目标库。仅用于发现的导入和临时实例是允许的;请立即移除临时实例。
  • 在导入资产时应用每个选定资产。如果导入失败,请先尝试下一个适用的精确结果,再构建手动替代方案。
步骤 1:了解交付成果

开始操作 Figma 之前,先了解要构建的内容:

  1. 如果根据代码构建,请阅读相关源文件,了解结构、各个区块以及所用的组件。
  2. 确定视图中的主要区块(例如,页面包含页眉、主视觉区、内容面板和页脚;模态框包含标题栏、表单区块和操作栏;侧边栏包含导航、内容区和页脚操作)。
  3. 列出每个区块涉及的 UI 组件(按钮、输入框、卡片、导航胶囊、折叠面板等)。
  4. 从源文件中确定产品使用的字体系列。不要默认使用 Inter。 编写任何脚本之前,先找到产品使用的字体。有关查找位置(CSS 变量、组件文件)以及如何解析混乱的 Figma 字体名称,请参阅 references/discover-product-font.md。
  5. 检查视图是否包含图像(例如 <img>、<Image>、背景图、产品照片、头像、图标 URL)。如果包含图像且这是 Web 应用,必须运行并行的 generate_figma_design 截图捕获工作流——请与步骤 2 同时立即启动,以便在发现组件时同步进行截图捕获。 详情请参阅上方的“使用 generate_figma_design 的并行工作流”。
第 2 步:收集组件键、变量和样式

你需要从设计系统中获取三类内容:组件(按钮、卡片等)、变量(颜色、间距、圆角)和样式(文本样式、阴影等效果样式)。设计系统中存在令牌时,不要硬编码十六进制颜色或像素值。

2a:发现组件

2a-i — 必须:检查所需组件是否有 Code Connect 文件。 从你在第 1 步中整理的组件列表开始,检查代码库中每个组件是否都有 Code Connect 文件。Code Connect 文件位于组件源文件旁边,并按平台命名:

  • TypeScript/JS:*.figma.ts、*.figma.js
  • React(基于解析器):*.figma.tsx
  • Kotlin/Compose:包含 @FigmaConnect 的 .kt 文件
  • Swift:包含 FigmaConnect 的 .swift 文件

对于所需的每个组件(例如 Button、Card、Input),搜索其 Code Connect 文件——按组件名称使用 glob 或 grep 搜索(例如 **/Button.figma.tsx、**/Card.figma.ts)。只读取与你实际需要的组件匹配的文件。

从每个匹配的 Code Connect 文件中提取 Figma 组件 URL。解析 URL 中的 fileKey 和 nodeId(将连字符转换为冒号:123-456 → 123:456)。然后通过 use_figma 解析组件键:

示例: Code Connect 文件包含 // url=https://figma.com/design/ABC123/File?node-id=609-35535。解析得到 fileKey = ABC123、nodeId = 609:35535。针对库文件(fileKey ABC123,而非目标文件)运行 use_figma 来解析组件键:

const node = await figma.getNodeByIdAsync("609:35535");
const set = node?.parent?.type === "COMPONENT_SET" ? node.parent : node;
if (set?.type === "COMPONENT_SET") {
  return { assetType: "component_set", componentSetKey: set.key };
}
if (set?.type === "COMPONENT") {
  return { assetType: "component", componentKey: set.key };
}
throw new Error("Expected a component or component set");

在一次调用中批量执行多项查找。根据第 4 步中每个项目的 assetType,使用返回的键调用 importComponentByKeyAsync() 或 importComponentSetByKeyAsync()。

标记已解析的组件,然后继续处理尚未解析的组件。

2a-ii — 必须:选择库范围,然后搜索并检查整个视图。 调用 get_libraries。如果用户指定了一个或多个库,无论这些库出现在 libraries_added_to_file 还是 libraries_available_to_add 中,都使用其确切键。否则,在 libraries_added_to_file 中的所有库范围内进行搜索。在每次搜索中都通过 includeLibraryKeys 传入所选键。只有在未解析的缺口找不到合适匹配项时,才从 libraries_available_to_add 中添加明确相关的库,并重试这些未解析的查询;不要扩大范围以包含无关的可用库。在第一次批量调用 search_design_system 时,除了针对已通过源文件或 Code Connect 检查确认的未解析项目的查询,还要加入一个针对所请求视图或流程的组件查询。按用途和容器为整个视图查询命名(例如 billing settings drawer)。检查最匹配的候选项。如果它涵盖两个或更多所请求的部分,就将其选为基础;否则继续,不使用整个视图的组合项。

2a-iii — 检查现有屏幕。 检查目标文件中是否已有使用相同设计系统的屏幕。一次只读 use_figma 调用即可对现有框架进行清点,一次权威检查即可获取其组件键、绑定变量以及文本/效果样式。在此处运行一次,并在 2b 和 2c 中重复使用结果,而不要再次遍历该框架:

const frame = figma.currentPage.findOne(n => n.name === "Existing Screen");
const components = new Map();
const styles = { text: new Map(), effect: new Map() };
const variableIds = new Set();

// boundVariables and style ids can sit on any scene node, so walk them all.
for (const node of frame?.findAll(() => true) ?? []) {
  if (node.type === "INSTANCE") {
    const mc = node.mainComponent;
    const cs = mc?.parent?.type === "COMPONENT_SET" ? mc.parent : null;
    const key = cs ? cs.key : mc?.key;
    if (key && !components.has(key)) {
      components.set(key, { name: cs ? cs.name : mc.name, key, isSet: !!cs, sampleVariant: mc.name });
    }
  }
  for (const b of Object.values(node.boundVariables ?? {}).flat()) {
    if (b?.id) variableIds.add(b.id);
  }
  for (const [prop, bucket] of [["textStyleId", "text"], ["effectStyleId", "effect"]]) {
    if (prop in node && typeof node[prop] === "string" && node[prop]) {
      const s = await figma.getStyleByIdAsync(node[prop]);
      if (s) styles[bucket].set(s.id, { name: s.name, id: s.id, key: s.key });
    }
  }
}
const vars = await Promise.all([...variableIds].map(id => figma.variables.getVariableByIdAsync(id)));

return {
  components: [...components.values()],
  variables: vars.filter(Boolean).map(v => ({ name: v.name, id: v.id, key: v.key, type: v.resolvedType, remote: v.remote })),
  textStyles: [...styles.text.values()],
  effectStyles: [...styles.effect.values()],
};

将 components 与尚未解析的组件进行匹配;来自 2a-i 的 Code Connect 键仍具有权威性。标记新解析出的组件。

2a-iv — 仅搜索构建所需的缺项。 完成 Code Connect、整个视图的发现和现有屏幕检查后,搜索设计仍需要的未解析组件和令牌。将独立的单意图条目批量处理,将 includeLibraryKeys 限定在所选库范围内,并在构建时使用所选键。不要为了穷尽搜索每个未解析的角色而延迟构建。

// Step 1: Discover available libraries
get_libraries({ fileKey })
// Returns: {
//   libraries_added_to_file: [...],
//   libraries_available_to_add: [...],
//   libraries_available_to_add_next_offset: number | null
// }

// Step 2: Search within a specific library using its libraryKey
search_design_system({ queries: [{ entity: "component", query: "button" }], fileKey, includeLibraryKeys: ["lk-abc123..."] })

libraries_available_to_add 中的组织库采用分页方式(每页 20 个)。当 libraries_available_to_add_next_offset 不为 null 时,表示还有更多组织库可用——再次调用 get_libraries,并将 offset 设为该值,以获取下一页。社区 UI 工具包仅显示在第一页。如果用户指定了某个库,而你在当前页中没有找到,请继续翻页再决定是否放弃。

当文件包含许多库,而你想要精准的结果时,这尤其有用(例如,只搜索「iOS 26」或「Material 3」,而不是从每个库中获取匹配项)。

每个查询只表达一种意图。 search_design_system 不采用 OR 语义,因此切勿在一个字符串中堆入多个备选项或同义词(「Button IconButton icon」不会匹配到有用结果)。已知时使用准确的设计系统名称或组件类型;否则,按资源的 UI 用途搜索,例如「归档操作图标」或「主提交按钮」。 将每个选中的键映射到一个区段或属性。复用适用的复合后代,而不要并行构建替代项;除非只需分离示例/模板包装器,否则应保留嵌套实例。

在映射中包含组件属性——你需要知道每个组件公开了哪些 TEXT 属性,可用于文本覆盖。创建一个临时实例,读取其 componentProperties(以及嵌套实例的对应属性),然后移除该临时实例。

带属性信息的组件映射示例:

Component Map:
- Button → key: "abc123", type: COMPONENT_SET
  Properties: { "Label#2:0": TEXT, "Has Icon#4:64": BOOLEAN }
- PricingCard → key: "ghi789", type: COMPONENT_SET
  Properties: { "Device": VARIANT, "Variant": VARIANT }
  Nested "Text Heading" has: { "Text#2104:5": TEXT }
  Nested "Button" has: { "Label#2:0": TEXT }
2b:发现变量(颜色、间距、圆角半径)

先检查现有屏幕。 复用 2a-iii 清单中的 variables;如果跳过了该步骤,并且现有屏幕可用,请在此处运行清单。对于尚未解决的变量,使用 search_design_system,并在 queries 条目中将 entity 设为 "variable"。

WARNING:两种不同的变量发现方法——请勿混淆。

  • use_figma 搭配 figma.variables.getLocalVariableCollectionsAsync()——仅返回当前文件中定义的本地变量。如果返回空结果,不代表不存在变量。此 API 无法查看远程/已发布库中的变量。
  • search_design_system 搭配 entity: "variable" 查询条目——搜索远程和已发布库中的变量。每个查询都必须通过 includeLibraryKeys 限定为 2a-ii 中选定的库键。

切勿仅凭 getLocalVariableCollectionsAsync() 返回空结果,就断定「不存在变量」。 在决定创建自己的变量之前,务必也运行带变量查询条目的 search_design_system,检查库变量。

查询策略: search_design_system 根据变量名称匹配(例如「Gray/gray-9」、「core/gray/100」、「space/400」),而不是根据类别匹配。请在一次 queries 调用中放入多个简短、简单的搜索词,而不要使用一个复合查询。每个数组条目都必须是 { "entity": "variable", "query": "..." } 对象,不能是裸字符串:

  • 基础颜色: { "entity": "variable", "query": "gray" }、{ "entity": "variable", "query": "red" } 等。
  • 语义颜色: { "entity": "variable", "query": "background" }、{ "entity": "variable", "query": "surface" } 等。
  • 间距/尺寸: { "entity": "variable", "query": "space" }、{ "entity": "variable", "query": "radius" } 等。

如果初次搜索没有结果,请尝试更短的片段或不同的命名方式——不同库的命名差异很大(「grey」与「gray」、「spacing」与「space」、「color/bg」与「background」)。

对于库变量(remote = true),使用 figma.variables.importVariableByKeyAsync(key) 按键导入。对于本地变量,直接使用 figma.variables.getVariableByIdAsync(id)。

绑定模式请参阅 variable-patterns.md。

2c:发现样式(文本样式、效果样式)

复用 2a-iii 或 2b 清单中的 textStyles 和 effectStyles。如果没有清单,请检查使用相同脚本的可用屏幕。在硬编码尚未确定的可复用填充/描边、排版或效果角色之前,先发起聚焦的 search_design_system 搜索,并设置 entity: "style",例如“surface”“border”“heading”“body”“shadow”或“elevation”。可批量搜索互不依赖的条目,但不要穷尽搜索已由所选组件或现有屏幕样式涵盖的角色。搜索仍缺失的任何样式。

使用 figma.importStyleByKeyAsync(key) 导入库样式,然后通过 node.textStyleId = style.id 或 node.effectStyleId = style.id 应用。

详情请参阅 text-style-patterns.md 和 effect-style-patterns.md。

步骤 3:创建外层 Frame

不要将各个区块创建为页面顶层子节点,再稍后重新设置其父级——通过 appendChild() 在不同的 use_figma 调用之间移动节点会静默失败,并产生孤立的 Frame。先创建一个可变的外层 Frame,然后直接在其中构建每个区块。

在外层 Frame 中导入并实例化任何选定的整页复合组件。自定义其涵盖的后代节点,并将缺失的区块与它一同添加到外层 Frame;绝不要将子节点直接添加到实例中。将外层 Frame 放置在远离现有内容的位置,并返回其 ID:

// Find clear space
let maxX = 0;
for (const child of figma.currentPage.children) {
  maxX = Math.max(maxX, child.x + child.width);
}

const wrapper = figma.createAutoLayout("VERTICAL");

// --- Size the wrapper based on container type ---
// Full page:       wrapper.resize(1440, 100); wrapper.name = "Homepage";
// Modal/dialog:    wrapper.resize(640, 100);  wrapper.name = "Settings Modal";
// Drawer/sidebar:  wrapper.resize(360, 100);  wrapper.name = "Navigation Drawer";
// Panel:           wrapper.resize(400, 100);  wrapper.name = "Details Panel";
// Adapt width to match the source code's actual dimensions.

wrapper.name = "VIEW_NAME";
wrapper.primaryAxisAlignItems = "CENTER";
wrapper.counterAxisAlignItems = "CENTER";
wrapper.resize(WIDTH, 100);
wrapper.layoutSizingHorizontal = "FIXED";
wrapper.x = maxX + 200;
wrapper.y = 0;

return { success: true, wrapperId: wrapper.id };
步骤 4:自定义已涵盖的区块并构建缺失的区块

这是最重要的一步。 从选定的复合组件开始:自定义它已涵盖的后代节点,只构建缺失的区块。分阶段构建,确保可安全重试,并在安全时批量处理相关区块。只有遇到页面上下文边界、部分执行难以恢复,或需要针对失败进行定向重试时才拆分——不要仅仅为了创建验证检查点而拆分。每个脚本开始时,都要通过 ID 获取可变的外层 Frame。将新内容添加到该 Frame,而不是组件实例。

const createdNodeIds = [];

// Resolve the wrapper and import every design system dependency in parallel.
// Sequential awaits here serialize N independent IPC round-trips at the top
// of every section build; one Promise.all is dramatically faster.
const [wrapper, buttonSet, bgColorVar, spacingVar, shadowStyle] = await Promise.all([
  figma.getNodeByIdAsync("WRAPPER_ID_FROM_STEP_3"),
  figma.importComponentSetByKeyAsync("BUTTON_SET_KEY"),
  figma.variables.importVariableByKeyAsync("BG_COLOR_VAR_KEY"),
  figma.variables.importVariableByKeyAsync("SPACING_VAR_KEY"),
  figma.importStyleByKeyAsync("SHADOW_STYLE_KEY"),
]);
const primaryButton = buttonSet.children.find(c =>
  c.type === "COMPONENT" && c.name.includes("variant=primary")
) || buttonSet.defaultVariant;

// Build section frame with variable bindings (not hardcoded values)
const section = figma.createAutoLayout();
section.name = "Header";
section.setBoundVariable("paddingLeft", spacingVar);
section.setBoundVariable("paddingRight", spacingVar);
const bgPaint = figma.variables.setBoundVariableForPaint(
  { type: 'SOLID', color: { r: 0, g: 0, b: 0 } }, 'color', bgColorVar
);
section.fills = [bgPaint];

// Apply the effect style imported above
section.effectStyleId = shadowStyle.id;

// Create component instances inside the section
const btnInstance = primaryButton.createInstance();
section.appendChild(btnInstance);
createdNodeIds.push(btnInstance.id);

// Append section to wrapper
wrapper.appendChild(section);
section.layoutSizingHorizontal = "FILL"; // AFTER appending

createdNodeIds.push(section.id);
return { success: true, createdNodeIds };

每次调用都返回已创建的节点 ID,以及相关的计数、名称和边界——这是默认的结构验证方式。只有缺少这些证据,或相关变更已使其失效时,才单独执行结构读取。将视觉检查留到步骤 5。

使用 setProperties() 覆盖实例文本

组件实例自带占位文本(“Title”“Heading”“Button”)。使用在步骤 2 中发现的组件属性键,通过 setProperties() 覆盖这些文本——这比直接操作 node.characters 更可靠。完整模式请参阅 component-patterns.md。

对于提供自身 TEXT 属性的嵌套实例,请在该嵌套实例上调用 setProperties():

// Use the type-indexed criteria for the type filter, then narrow by name.
const nestedHeading = cardInstance
  .findAllWithCriteria({ types: ["INSTANCE"] })
  .find(n => n.name === "Text Heading");
if (nestedHeading) {
  nestedHeading.setProperties({ "Text#2104:5": "Actual heading from source code" });
}

只有当文本不受任何组件属性管理时,才退而使用直接设置 node.characters 的方式。

仔细读取源代码默认值

将代码组件转换为 Figma 实例时,要检查源代码中的组件默认属性值,而不只是显式传入的值。例如,<Button size="small">Register</Button> 未提供 variant 属性——请检查组件定义,确认默认值是否为 variant = "primary"。选择错误的变体(例如 Neutral 而不是 Primary)会导致视觉结果不正确,而且很容易被忽略。

手动构建与从设计系统导入的内容
手动构建从设计系统导入
外层框架组件:按钮、卡片、输入框、导航等
分区容器框架变量:颜色(填充、描边)、间距(内边距、间隙)、圆角
布局网格(行、列)文本样式:标题、正文、说明文字等
效果样式:阴影、模糊等

如果存在设计系统变量,绝不要硬编码十六进制颜色或像素间距。 使用 setBoundVariable 设置间距和圆角,使用 setBoundVariableForPaint 设置颜色。使用 node.textStyleId 应用文本样式,使用 node.effectStyleId 应用效果样式。

将重复和可复用元素组件化(必需)

组件化是默认工作流的一部分,不是可选的后续步骤。首次构建时就应生成组件化结构;不要先输出由一次性框架组成的扁平树,再等第二次提示要求“现在将其组件化”。

  • 设计系统实例已经组件化(步骤 2)。优先使用它们。
  • 对于设计系统未涵盖、但会重复出现或对应可复用源组件的内容,使用 figma.createComponent() 创建一个本地组件,并放置其实例,而不是手动构建 N 个几乎相同的框架。一个源组件对应一个 Figma 主组件。

请参阅 references/componentization.md,了解一次构建、多处放置实例的模式及代码。

图标:导入 SVG,绝不使用旋转图元重绘

图标是上述手动构建与导入的划分规则的主要例外。如果设计系统将图标提供为组件,请创建其实例(使用单个 INSTANCE_SWAP 属性,而不是为每个图标创建一个变体)。否则,最常见的情况是从代码库中获取图标并放入或替换到 Figma 中,此时应将图标的 SVG 源文件直接导入为矢量节点。这是图标的主要默认方式;不要重绘。

  1. 从代码库获取 SVG。 读取图标源文件——内联 <svg>、导入的 .svg 资源或图标库条目——并传入完全相同的 SVG 字符串。优先使用代码库自带的 SVG,不要手动编写。
  2. 使用 figma.createNodeFromSvg(svgString) 导入,该方法会返回包含可编辑矢量路径的 FrameNode。SVG 字符串必须包含 viewBox 以及明确的 width/height(例如 <svg width="24" height="24" viewBox="0 0 24 24" ...>)。如果没有 width/height,则会回退到 viewBox 尺寸,通常小于图标槽位——这通常就是“图标尺寸不正确”的原因。
  3. 调整至槽位大小。 createNodeFromSvg 创建的框架会在调整大小时缩放其内容,因此 icon.resize(size, size) 可以将整个图标(包括描边粗细)适配到目标框中。也可以将 width/height 设为目标尺寸。图标尺寸应与源文件一致,通常为 16/20/24px。
  4. 绝不要使用旋转的线条、矩形或椭圆图元重绘图标。 在 use_figma 上下文中,Figma 的线条旋转不可靠,会导致图标损坏、旋转方向错误(箭头折叠成一团,箭头尖端与箭杆分离)。导入 SVG 更可靠,也更便于编辑。
// Place / replace an icon from a codebase SVG into a 24px slot
const icon = figma.createNodeFromSvg(
  '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">' +
  '<path d="m9 18 6-6-6-6" stroke="#1A1A1A" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
);
icon.name = "icon/chevron-right";
icon.resize(24, 24);          // scales the whole icon to the slot
slotFrame.appendChild(icon);

代码库中的 SVG 通常使用 currentColor(例如 stroke="currentColor" / fill="currentColor"),而 createNodeFromSvg 会将其导入为黑色——它不会继承父级的颜色。导入后设置所需颜色:在导入前将 SVG 字符串中的颜色替换为具体颜色,或使用 setBoundVariableForPaint 将导入矢量的填充/描边绑定到设计系统颜色变量(与其他绘制属性相同)。若要将导入的 SVG 转为可复用的图标组件(用于 INSTANCE_SWAP),请参阅 figma-generate-library → 创建图标组件 和 INSTANCE_SWAP 模式。

步骤 5:验证完整视图并转移图像

在进行视觉验证之前,使用 use_figma 读取包装器,并返回其所有后代节点的总数、每种存在的后代节点类型的数量,以及每个填充了图像的节点的 ID、名称、节点类型和尺寸。这些计数是证据,不是数值通过门槛;不要根据截图推断可编辑性,也不要接受在完整 UI 栅格图上叠加少量可编辑节点的做法。如果包装器内任何位置存在完整 UI 的截图或扁平化渲染,请将其移除,并以语义化方式重建 UI,或报告失败;不得声称已完成。

组合好所有区块后,为包装器框架截取一张完整视图组合截图,并与源内容进行比较。如果发现明显的视觉缺陷,请使用 use_figma 进行针对性修复——不要重建整个视图——然后截取一张修复后截图。最新一张通过检查的截图就是最终检查结果:不要再额外截取一张没有改动的“最终”截图,也不要逐个区块截图。

进行视觉修复前,将包装器的实例、样式和绑定变量键与步骤 2 的映射进行比较。所有适用的已选资源都应出现在输出中;完成前请替换手动制作的等效内容和原始值。

检查组合截图中的以下问题:

  • 文本被裁切——行高或框架尺寸导致下行字母、上行字母或整行内容被截断
  • 内容重叠——由于尺寸不正确或缺少自动布局,元素彼此堆叠
  • 仍显示占位文本(“Title”“Heading”“Button”)
  • 因布局尺寸问题导致内容被截断
  • 组件变体错误(例如 Neutral 按钮误用了 Primary 变体)
  • 字体系列错误——文本使用的字体与产品字体不同(例如,产品使用 SF Pro,渲染结果却使用 Inter)。脚本运行无错误,因此乍看之下不易发现;请明确断言字体系列正确(见下方“断言字体系列正确”)
  • 空白图像占位符——如果缺少图像,请先从 generate_figma_design 捕获内容中转移图像,再考虑使用 generate_image 生成占位图(见下方“从 generate_figma_design 捕获内容中转移图像”)
断言字体系列正确

你必须明确断言,渲染后的文本使用步骤 1 中识别出的产品字体,并将任何不匹配视为验证失败。不要假设成功加载的字体就是正确字体:如果产品使用 SF Pro,而你加载的是 Inter,即使没有报错,也属于失败。如果有源参考(正在运行的 Web 应用、设计稿或 generate_figma_design 捕获内容),还必须比较渲染后的截图——字体系列正确的近似样式可能通过字体系列检查,但视觉上仍然不正确。

请参阅 references/discover-product-font.md,查看读取脚本(用于区分需要修复的独立文本和需要标记的问题设计系统管控文本)以及截图比较步骤。

从 generate_figma_design 捕获内容中转移图像

如果你并行运行了 generate_figma_design,请仅将应用使用的离散内容资源转移到设计系统输出中。切勿上传或转移捕获根节点,或完整 UI 的任何截图或扁平化渲染。

  1. 通过搜索 type === "IMAGE" 的填充,查找捕获输出中的所有图像节点:
    const capture = await figma.getNodeByIdAsync("CAPTURE_NODE_ID");
    const imageNodes = capture.findAll(() => true).flatMap(n => {
      if (!Array.isArray(n.fills)) return [];
      const imageFill = n.fills.find(f => f.type === "IMAGE");
      return imageFill ? [{ name: n.name, id: n.id, imageHash: imageFill.imageHash }] : [];
    });
    return imageNodes;
    
  2. 按位置、名称或顺序,将每张捕获的图像与 use_figma 输出中的对应框架匹配。
  3. 将图像哈希应用到目标框架:
    targetFrame.fills = [{ type: "IMAGE", imageHash: "hash_from_capture", scaleMode: "FILL" }];
    
  4. 转移完所有图像后,删除 generate_figma_design 捕获输出。
生成占位图片

优先复用已有的源图片、截图或图库图片。如果仍有占位图片,请调用 Figma generate_image 工具。图片生成后,告知用户使用了 Figma AI 点数来生成图片。

如果 Figma AI 不可用,或 AI 点数已达上限,请先向用户确认是否可以使用其他图片生成工具。仅使用 upload_assets 上传这些其他服务商生成的图片。

第 6 步:更新现有视图

如果是更新而不是从头创建:

  1. 使用 get_metadata 检查现有屏幕结构。
  2. 确定需要更新和可以保留的部分。
  3. 对于每个需要更改的部分:
    • 按 ID 或名称定位现有节点
    • 如果设计系统组件已更改,则替换组件实例
    • 根据需要更新文本内容、变体属性或布局
    • 移除已弃用的部分
    • 添加新部分
  4. 遵循与第 4–5 步相同的验证依据和截图节奏:依靠返回的 ID 以及相关计数、名称和边界来验证结构,然后在更新后截取一张完整视图的屏幕截图(仅在需要针对性的视觉修复时,才再截取一张修复后的屏幕截图)。
// Example: Swap a button variant in an existing screen.
// Batch the node lookup and component-set import in parallel — they are
// independent and awaiting them sequentially serializes two IPC round-trips.
const [existingButton, buttonSet] = await Promise.all([
  figma.getNodeByIdAsync("EXISTING_BUTTON_INSTANCE_ID"),
  figma.importComponentSetByKeyAsync("BUTTON_SET_KEY"),
]);
if (existingButton && existingButton.type === "INSTANCE") {
  const newVariant = buttonSet.children.find(c =>
    c.name.includes("variant=primary") && c.name.includes("size=lg")
  ) || buttonSet.defaultVariant;
  existingButton.swapComponent(newVariant);
}
return { success: true, mutatedNodeIds: [existingButton.id] };

参考文档

如需了解详细的 API 用法模式和注意事项,请根据需要从 figma-use 参考资料中加载以下文档:

  • component-patterns.md — 按 key 导入、查找变体、setProperties、文本覆盖、使用实例
  • variable-patterns.md — 创建/绑定变量、导入库变量、作用域、别名、发现现有变量
  • text-style-patterns.md — 创建/应用文本样式、导入库文本样式、字体比例
  • effect-style-patterns.md — 创建/应用效果样式(阴影)、导入库效果样式
  • gotchas.md — 布局陷阱(HUG/FILL 交互、counterAxisAlignItems、尺寸设置顺序)、填充/颜色问题、页面上下文重置

错误恢复

遵循 figma-use 错误恢复:

  • 如果 safeToRetryWithoutCanvasRead 为 true,请修复错误后重试。
  • 如果为 false,请读取画布,确定发生了什么变化,然后再进行更改。

由于此技能在可安全重试的构建阶段中工作,错误自然会限制在当前阶段。之前成功调用所创建的内容会保留。

最佳实践

  • 构建前务必先搜索。 设计系统中很可能已有你需要的组件、变量或样式。手动构建和硬编码值应是例外,而非常规做法。
  • 针对尚未解决的缺口进行搜索,每次查询表达一个意图。 将同义词和部分词条分别作为 { entity, query } 条目放入同一次 queries 调用中,切勿合并成一个字符串。例如,"NavigationPill" 可能以 "pill"、"nav"、"tab" 或 "chip" 为关键词找到,因此应传入四个组件条目。对于变量,使用 entity: "variable",并查询 "color"、"spacing" 和 "radius" 等词条。仅针对尚未解决的构建缺口执行此操作,找到合适的资源后即停止。
  • 优先使用设计系统令牌,而非硬编码值。 使用变量绑定设置颜色、间距和圆角。使用文本样式设置排版。使用效果样式设置阴影。这样可让屏幕与设计系统保持关联。
  • 优先使用组件实例,而非手动构建。 实例会保持与源组件的关联,并在设计系统演进时自动更新。
  • 默认将元素组件化。 将重复或可复用的元素构建为组件,然后放置其实例。不要交付由一次性框架组成的扁平树结构,否则还需要再进行一次“组件化”处理。
  • 分阶段构建,确保重试安全。 如果脚本可以安全重试,就在一次 use_figma 调用中批量处理相关部分;仅在页面上下文边界、难以恢复的变更,或实际失败后需要针对性重试时才拆分。
  • 每次调用都返回节点 ID 和验证证据。 返回已创建的 ID,以及相关的数量、名称和边界——这是默认的结构验证方式;你还需要这些 ID 来组合各部分并进行错误恢复。
  • 通过一张组合后的截图进行视觉验证。 组合完成后截取一张全视图截图;仅在针对性视觉修复后再截取一张。最近一张通过验证的截图即为最终截图。
  • 验证字体系列,而不只是确认字体加载成功。 脚本可能会加载错误的字体,却不报错。构建后,请验证渲染的文本使用的是步骤 1 中确定的产品字体(参见步骤 5)。
  • 遵循现有约定。 如果文件中已有屏幕,请沿用其命名、尺寸和布局模式。

评论

支持 Markdown