关于 figma-use
figma-use 是一项技能,可通过 `use_figma` 工具运行 JavaScript,借助 Plugin API 操作 Figma 文件。它面向处理 Figma 设计的 Agent,强调分步修改、查阅 API 参考资料并返回受影响的节点 ID。
主要功能
- 01通过 `use_figma` 运行 Plugin API JavaScript
- 02查阅 API 类型定义与文档
- 03分步修改画布
- 04文本与变量编辑指导
- 05按页面操作的规则
适用场景
- 01检查或修改 Figma 节点
- 02构建或更新 Figma 布局
- 03编辑文本和设计变量
MCP 相关
该技能说明如何使用 `use_figma` 工具,以及在 Figma MCP 工具延迟加载时如何加载其工具架构;未说明 MCP 工具具体提供什么。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ thedesignproject/ agent-skills --skill figma-use安装后在 Claude Code 中输入/figma-use确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-reference.mdcommon-patterns.mdcomponent-patterns.mdeffect-style-patterns.mdgotchas.mdplugin-api-patterns.mdplugin-api-standalone.d.tsplugin-api-standalone.index.mdtext-style-patterns.mdvalidation-and-recovery.mdvariable-patterns.mdreferences/working-with-design-systems/wwds-components--creating.mdwwds-components--using.mdwwds-components.mdwwds-effect-styles.mdwwds-text-styles.mdwwds-variables--creating.mdwwds-variables--using.mdwwds-variables.mdwwds.md详细介绍
use_figma — Figma 插件 API 技能
使用 use_figma 工具,通过 Plugin API 在 Figma 文件中执行 JavaScript。所有详细参考文档都位于 references/ 中。
调用 use_figma 时,始终传入 skillNames: "figma-use"。 这是用于跟踪技能使用情况的日志参数,不会影响执行。
如果 Figma MCP 工具显示为延迟加载的工具,请使用 select: 语法,在一次 ToolSearch 调用中批量加载它们的所有架构,例如:ToolSearch query="select:use_figma,get_screenshot,get_metadata,create_new_file"。一次往返胜过六次。
如果任务涉及从代码在 Figma 中构建或更新完整页面、屏幕或多区块布局,还要加载 figma-generate-design。它提供了通过 search_design_system 查找设计系统组件、导入组件并逐步组装屏幕的工作流。这两项技能可以配合使用:本技能负责 API 规则,另一项负责屏幕构建工作流。
如果任务涉及在 Figma 中创建或构建组件(即使只是单个组件),还要加载 figma-generate-library。它提供了组件创建工作流,包括变量基础、变体集和设计令牌绑定,这些内容仅靠 figma-use 无法覆盖。
首先,加载 plugin-api-standalone.index.md,了解可以实现哪些操作。当被要求编写插件 API 代码时,请利用这些上下文,在 plugin-api-standalone.d.ts 中 grep 相关类型、方法和属性。该文件是 API 范围的权威依据。它是一个很大的类型定义文件,因此不要一次性全部加载;请根据需要 grep 相关部分。
重要:每当使用设计系统时,都要先从 working-with-design-systems/wwds.md 开始,了解在 Figma 中使用设计系统的关键概念、流程和指南。然后根据需要加载组件、变量、文本样式和效果样式的具体参考资料。
1. 关键规则
- 使用
return返回数据。 返回值会自动序列化为 JSON(对象、数组、字符串、数字)。不要调用figma.closePlugin(),也不要将代码包装在异步 IIFE 中——这些会自动为你处理。 - 使用顶层
await和return编写纯 JavaScript。 代码会自动包装在异步上下文中。不要将代码包装在(async () => { ... })()中。 figma.notify()会抛出“not implemented”错误——切勿使用。 3a.use_figma不支持getPluginData()/setPluginData()——不要使用。请改用getSharedPluginData()/setSharedPluginData()(这些受支持),或通过返回节点 ID 并在后续调用中传入来跟踪节点。console.log()的输出不会被返回——请使用return输出。- 逐步以小步骤操作。 将大型操作拆分为多个
use_figma调用,并在每一步后进行验证。这是避免错误最重要的做法。 - 颜色的取值范围是 0–1(不是 0–255):
{r: 1, g: 0, b: 0}= 红色。 - 填充和描边是只读数组——请克隆、修改后重新赋值。
- 每次文本编辑都遵循规范流程:加载字体 →
await→ 修改 → 返回受影响的节点 ID。 跳过字体加载会触发Cannot write to node with unloaded font "<family> <style>"。此规则不仅适用于characters,也适用于任何涉及未加载字体节点的操作(appendChild、insertChild、setBoundVariable、setExplicitVariableModeForCollection、setValueForMode、会触及文本的findAll回调)。修改现有文本时,请通过getStyledTextSegments(['fontName'])加载节点的当前字体,而不是使用硬编码的默认字体。大多数环境中都会预加载 Inter,因此其他字体系列更容易暴露此问题——所有字体都遵循相同流程。如果样式字符串未经验证,请先使用await figma.listAvailableFontsAsync()。参阅规范文本编辑流程。 - 页面会逐步加载——请使用
await figma.setCurrentPageAsync(page)切换页面并加载其内容。同步设置器figma.currentPage = page不起作用,并会抛出错误(参见下方的页面规则)。 setBoundVariableForPaint会返回一个新的 paint——必须捕获并重新赋值。createVariable接受集合对象或 ID 字符串(优先使用对象)。layoutSizingHorizontal/Vertical的可用值受结构上下文限制——FIXED始终有效,HUG和FILL则不一定。'HUG'仅适用于自动布局框架本身,或其文本子节点。'FILL'仅适用于自动布局框架的子节点,且该子节点不能是绝对定位、位于不可变框架内或属于画布网格子节点。实际操作中,应先将节点添加到自动布局父节点中,再设置HUG/FILL——新创建或未挂载的节点暂时无法满足此规则。每个SceneNode上都存在此属性;报错是因为值不被接受,而不是“属性不存在”。参阅注意事项。 12a. 包含相关子节点的容器请使用自动布局。 如果子节点之间存在结构关系——堆叠、并排、对齐、有间距或紧贴内容——请用figma.createAutoLayout()将它们包起来,而不要使用带绝对x/y坐标的figma.createFrame()。绝对坐标决定容器在画布上的位置;自动布局决定其内部子节点之间的关系。不使用容器会导致文本重排、内容变化或元素重叠时缺乏保护。- 将新的顶层节点放置在远离 (0,0) 的位置。 直接添加到页面的节点默认位于 (0,0)。请扫描
figma.currentPage.children,找到空白位置(例如最右侧节点的右边)。这仅适用于页面级节点——嵌套在其他框架或自动布局容器中的节点由其父节点定位。参阅注意事项。 use_figma出错时,立即停止。不要立刻重试。 失败的脚本具有原子性——如果脚本出错,就完全不会执行,也不会更改文件。请仔细阅读错误消息、修正脚本,然后重试。参阅错误恢复。- 必须
return所有创建或修改的节点 ID。 每当脚本在画布上创建新节点或修改现有节点时,请收集每个受影响的节点 ID,并在结构化对象中返回(例如return { createdNodeIds: [...], mutatedNodeIds: [...] })。这对于后续调用引用、验证或清理这些节点至关重要。 - 创建变量时,始终显式设置
variable.scopes。 默认的ALL_SCOPES会污染所有属性选择器——这几乎从来不是你想要的。请使用特定作用域,例如背景用["FRAME_FILL", "SHAPE_FILL"],文本颜色用["TEXT_FILL"],间距用["GAP"]等。完整列表请参阅 variable-patterns.md。 - 对每个 Promise 都使用
await。 切勿留下未等待的 Promise——未等待的异步调用(例如未使用await的figma.loadFontAsync(...)或figma.setCurrentPageAsync(page))会以即发即弃的方式运行,导致无声失败或竞态条件。脚本可能会在异步操作完成之前返回,从而造成数据缺失或更改只应用了一部分。
每条规则的 WRONG/CORRECT 详细示例,请参阅 易错点与常见错误。
2. 页面规则(重要)
每次调用 use_figma 后,页面上下文都会重置——每次调用时,figma.currentPage 都会从第一页开始。
切换页面
使用 await figma.setCurrentPageAsync(page) 切换页面并加载其内容。同步设置器 figma.currentPage = page 不起作用——在 use_figma 中会抛出 "Setting figma.currentPage is not supported"。请始终使用异步方法。
// Switch to a specific page (loads its content)
const targetPage = figma.root.children.find((p) => p.name === "My Page");
await figma.setCurrentPageAsync(targetPage);
// targetPage.children is now populated
每次调用 use_figma 最多调用一次 setCurrentPageAsync——将多页面工作拆分后并行执行
**单个脚本最多只能切换一次页面。**切勿遍历 figma.root.children 并在循环中切换页面。
如果工作涉及多个页面,请拆分为 N 次 use_figma 调用(每个目标页面一次),并并行发出——在一条助手消息中包含 N 个 use_figma 工具调用块。运行环境会并发执行它们;每个脚本只设置一次 currentPage。
明确说明:并行拆分时,必须在同一条消息中发出 N 次工具调用。不要分多轮发送。不要等一次调用完成后再发出下一次。按页面顺序逐次调用,比本规则要取代的循环内模式更慢,也会浪费拆分工作的全部优势。
// AVOID — switches pages N times in one script, reloads the file each time
for (const page of figma.root.children) {
await figma.setCurrentPageAsync(page);
// ... touch this page ...
}
// PREFER — read-only discovery call to get page IDs, then in the NEXT message
// emit N parallel use_figma tool calls (one per page), each setting currentPage once.
任何涉及多个页面的工作,无论读取还是写入,默认都应并行拆分。完整说明请参阅 gotchas.md → 每次 use_figma 调用只设置一次当前页面。
跨脚本运行
每次调用 use_figma 开始时,figma.currentPage 都会重置为第一页。如果工作流跨越多次调用且目标页面不是默认页面,请在每次调用开始时调用 await figma.setCurrentPageAsync(page)。
你可以多次调用 use_figma,逐步构建文件状态,或先获取信息再编写另一个脚本。例如,先编写脚本获取现有节点的元数据并 return 这些数据,然后在后续脚本中使用这些数据修改节点。
3. return 是你的输出通道
Agent 只能看到你 return 的值。其他所有内容都不可见。
- 返回 ID(重要):每个创建或修改画布节点的脚本都必须返回所有受影响节点的 ID——例如
return { createdNodeIds: [...], mutatedNodeIds: [...] }。这是硬性要求,并非可选项。 - 进度报告:
return { createdNodeIds: [...], count: 5, errors: [] } - **错误信息:**抛出的错误会自动捕获并返回——只需让错误继续传递,或明确执行
throw。 console.log()的输出不会返回给 Agent- 始终返回可执行的数据(ID、数量、状态),以便后续调用引用已创建的对象
4. 编辑器模式
use_figma 在设计模式下工作(editorType "figma",默认值)。FigJam("figjam")和 Slides("slides")可用的节点类型集不同——大多数设计节点在 FigJam 中不可用,而 FigJam 专属节点在 Slides 中不可用。
**通过 URL 判断编辑器:**设计 = figma.com/design/...,FigJam = figma.com/board/...,Slides = figma.com/slides/...。在假设某个 API 可用之前,请先确认。
设计模式下可用:Rectangle、Frame、Component、Text、Ellipse、Star、Line、Vector、Polygon、BooleanOperation、Slice、Page、Section、TextPath。
设计模式下不可用:Sticky、Connector、ShapeWithText、CodeBlock、Slide、SlideRow、SlideGrid、InteractiveSlideElement、Webpage。
Slides 模式下可用:Rectangle、Frame、Component、Text、Ellipse、Star、Line、Vector、Polygon、BooleanOperation、Slice、Section、TextPath、Slide、SlideRow、SlideGrid、InteractiveSlideElement。
Slides 模式下不可用:Sticky、Connector、ShapeWithText、CodeBlock、Webpage、Page。
仅限设计模式的 API(不只是节点类型):figma.createPage() 仅在设计文件(figma.com/design/...)中可用。在 FigJam(figma.com/board/...)和 Slides(figma.com/slides/...)中调用时,会抛出 TypeError: figma.createPage no such property 'createPage' on the figma global object。请勿在 FigJam 或 Slides 工作流中调用 figma.createPage()。
**Slides 说明:**目前还没有专门用于读取 Slides 文件的工具。请使用
use_figma配合只读脚本进行检查(参见第 6 节“先检查”模式),并使用get_screenshot/await node.screenshot()获取视觉上下文。有关 Slides 专属 API 的指南,请加载 figma-use-slides 技能。
5. 高效 API——优先使用这些 API,而不是冗长的替代方案
这些 API 可减少样板代码、避免排序错误,并压缩令牌输出。始终优先使用它们,而不是冗长的替代方案。
node.query(selector)——类似 CSS 的节点搜索
使用类似 CSS 的选择器在子树中查找节点。可替代冗长的 findAll + 过滤循环。
// BEFORE — verbose traversal
const texts = frame.findAll(n => n.type === 'TEXT' && n.name === 'Title')
// AFTER — one-liner with query
const texts = frame.query('TEXT[name=Title]')
选择器语法:
- 类型:
FRAME、TEXT、RECTANGLE、ELLIPSE、COMPONENT、INSTANCE、SECTION(不区分大小写) - 属性精确匹配:
[name=Card]、[visible=true]、[opacity=0.5] - 属性子串匹配:
[name*=art](包含)、[name^=Header](以……开头)、[name$=Nav](以……结尾) - 点路径遍历:
[fills.0.type=SOLID]、[fills.*.type=SOLID](通配索引) - 实例匹配:
[mainComponent=nodeId]、[mainComponent.name=Button] - 组合器:
FRAME > TEXT(直接子节点)、FRAME TEXT(任意后代节点)、A + B(相邻兄弟节点)、A ~ B(一般兄弟节点) - 伪类:
:first-child、:last-child、:nth-child(2)、:not(TYPE)、:is(FRAME, RECTANGLE)、:where(TEXT, ELLIPSE) - 节点 ID:
#nodeId或不带前缀的 GUID - 逗号:
TEXT, RECTANGLE(并集) - 通配符:
*(任意类型)
QueryResult 方法:
| 方法 | 说明 |
|---|---|
.length | 匹配节点的数量 |
.first() | 第一个匹配节点(或 null) |
.last() | 最后一个匹配节点(或 null) |
.toArray() | 转换为常规数组 |
.each(fn) | 使用回调进行迭代,返回 this 以便链式调用 |
.map(fn) | 映射为新数组 |
.filter(fn) | 筛选并返回新的 QueryResult |
.values(keys) | 提取属性值:.values(['name', 'x', 'y']) → [{name, x, y}, ...] |
.set(props) | 为所有匹配节点设置属性(参见下文的 node.set()) |
.query(selector) | 在匹配节点中执行子查询 |
for...of | 可迭代——可用于 for 循环 |
范围:node.query() 会在该节点的子树中搜索。要搜索整个页面,请使用 figma.currentPage.query('...')。没有全局的 figma.query()。
示例:
// Recolor all text inside cards
figma.currentPage.query('FRAME[name^=Card] TEXT').set({
fills: [{type: 'SOLID', color: {r: 0.2, g: 0.2, b: 0.8}}]
})
// Get names and positions of all frames
return figma.currentPage.query('FRAME').values(['name', 'x', 'y'])
// Find the first component named "Button"
const btn = figma.currentPage.query('COMPONENT[name=Button]').first()
// Find all instances of a specific component
figma.currentPage.query(`INSTANCE[mainComponent=${compId}]`)
// Find nodes with solid fills using dot-path traversal
figma.currentPage.query('[fills.0.type=SOLID]')
node.set(props) — 批量更新属性
一次调用中设置多个属性。返回 this,以便链式调用。
// BEFORE — one line per property
frame.opacity = 0.5
frame.cornerRadius = 8
frame.name = "Card"
// AFTER — single call
frame.set({ opacity: 0.5, cornerRadius: 8, name: "Card" })
**优先级键排序:**无论对象键的顺序如何,始终先应用 layoutMode,再应用其他属性(如 width/height)。这可以避免一个常见问题:resize() 的行为因是否设置了 layoutMode 而异。
宽度/高度处理:width 和 height 会自动通过 node.resize() 处理——设置 { width: 200 } 会调用 resize(200, currentHeight)。
与查询链式调用:
// Find all rectangles named "Divider" and update them
figma.currentPage.query('RECTANGLE[name=Divider]').set({
fills: [{type: 'SOLID', color: {r: 0.9, g: 0.9, b: 0.9}}],
cornerRadius: 2
})
figma.createAutoLayout(direction?, props?) — 自动布局框架
创建一个已启用自动布局且两条轴均贴合内容的框架。只要子元素之间存在结构关系,就默认使用此容器(参见规则 12a)。
// BEFORE — manual setup, easy to get ordering wrong
const frame = figma.createFrame()
frame.layoutMode = 'VERTICAL'
frame.primaryAxisSizingMode = 'AUTO'
frame.counterAxisSizingMode = 'AUTO'
frame.layoutSizingHorizontal = 'HUG'
frame.layoutSizingVertical = 'HUG'
// AFTER — one call, layout ready
const frame = figma.createAutoLayout('VERTICAL')
添加子元素后,可以立即将 layoutSizingHorizontal/Vertical = 'FILL';无需手动设置尺寸模式。
可将可选的 props 对象作为第一个或第二个参数传入:
figma.createAutoLayout({ name: 'Card', itemSpacing: 12 }) // HORIZONTAL + props
figma.createAutoLayout('VERTICAL', { name: 'Column', itemSpacing: 8 }) // VERTICAL + props
node.placeholder — 用于反馈 AI 正在处理的微光覆盖层
在节点上设置视觉微光覆盖层,表示工作正在进行。完成后务必移除微光效果——残留的微光会令用户困惑,也表示工作尚未完成。
// Mark as in-progress
frame.placeholder = true
// ... build out the content ...
// MUST remove when done — never leave shimmers on finished nodes
frame.placeholder = false
构建复杂布局时,先在各个分区上设置 placeholder = true,再填充内容;每个分区完成后,将其设置为 placeholder = false。
await node.screenshot(opts?) — 内联截图
将节点捕获为 PNG,并以内联形式在响应中返回。无需另行调用 get_screenshot。
// Take a screenshot of a frame (returned inline in the tool response)
await frame.screenshot()
// Custom scale (default auto-scales: 0.5x or capped so max dimension ≤ 1024px)
await frame.screenshot({ scale: 2 })
// Include overlapping content from sibling nodes
await frame.screenshot({ contentsOnly: false })
**适用场景:**创建或修改节点后,调用 screenshot(),在同一脚本中直观验证结果。无需另行调用 get_screenshot。
**自动命名:**图片说明中包含节点元数据——"Card (300x150 at 0,60).png"——无需解析图片即可了解其空间上下文。
**默认缩放:**使用 0.5x 缩放,但会自动限制输出尺寸,确保最大边不超过 1024px。显式设置 { scale: N } 则不受此限制。
6. 增量式工作流(如何避免错误)
尝试在一次 use_figma 调用中完成过多操作,是最常见的错误原因。分小步操作,并在每一步后进行验证。
关键规则
- 每次
use_figma调用最多执行 10 个逻辑操作。“逻辑操作”指创建节点、设置其属性并为其指定父节点。如果需要创建 20 个节点,请拆分为 2 到 3 次调用。 - **自上而下构建,从占位内容开始。**先创建外部结构,并在每个分区上设置
placeholder = true,然后在后续调用中逐步用实际内容替换占位内容。
工作模式
- **先检查。**创建任何内容之前,先运行只读的
use_figma,了解文件中已有的内容——页面、组件、变量、命名约定。与现有内容保持一致。 - **构建骨架。**创建带有占位分区的顶层结构。在每个分区上设置
placeholder = true,以便用户看到进度。 - **逐步填充分区。**在每次后续调用中填充一个分区,完成后将其
placeholder = false。调用screenshot()进行验证。 - **每次调用都返回 ID。**务必以对象形式
return创建的节点 ID、变量 ID、集合 ID(例如,return { createdNodeIds: [...] })。后续调用需要将这些 ID 作为输入。 - **每一步后都进行验证。**使用
get_metadata验证结构(数量、名称、层级、位置)。在主要里程碑后,使用内联的await node.screenshot()或调用get_screenshot,以发现视觉问题。 - **修复问题后再继续。**如果验证发现问题,请先修复,再进行下一步。不要在有问题的基础上继续构建。
复杂任务的建议步骤顺序
Step 1: Inspect file — discover existing pages, components, variables, conventions
Step 2: Create tokens/variables (if needed)
→ validate with get_metadata
Step 3: Create individual components
→ validate with get_metadata + get_screenshot
Step 4: Compose layouts from component instances
→ validate with get_screenshot
Step 5: Final verification
每个步骤需要验证的内容
| 完成……后 | 使用 get_metadata 检查 | 使用 get_screenshot 检查 |
|---|---|---|
| 创建变量 | 集合数量、变量数量、模式名称 | — |
| 创建组件 | 子项数量、变体名称、属性定义 | 变体可见且未折叠,网格清晰可读 |
| 绑定变量 | 节点属性是否反映绑定关系 | 颜色/令牌是否正确解析 |
| 组合布局 | 实例节点是否具有 mainComponent,层级是否正确 | 文本未被裁切,无元素重叠,间距正确 |
7. 错误恢复与自我纠正
use_figma 是原子操作——脚本失败时不会执行。 如果脚本报错,不会对文件做出任何更改。文件会保持调用前的状态。这意味着不会留下不完整的节点,也不会因脚本失败而产生孤立元素,修正后重试是安全的。
use_figma 返回错误时
- 停止。 不要立即修正代码并重试。
- 仔细阅读错误消息。 准确理解出错原因——API 用法错误、缺少字体、属性值无效等。
- 如果错误含义不明确, 调用
get_metadata或get_screenshot了解文件的当前状态。 - 根据错误消息修正脚本。
- 重试修正后的脚本。
常见的自我纠正模式
| 错误消息 | 可能原因 | 修复方法 |
|---|---|---|
"not implemented" | 使用了 figma.notify() | 移除它——使用 return 输出结果 |
"node must be an auto-layout frame or a child of an auto-layout frame" / "FILL can only be set on children of auto-layout frames" / "HUG can only be set on auto-layout frames or text children of auto-layout frames" / "FILL cannot be set on absolute positioned auto-layout children" / "FILL cannot be set on canvas grid children" | 尝试将 HUG/FILL 指定给结构上下文不允许使用它们的节点(例如,父节点不是自动布局、在 appendChild 之前运行、非文本子节点尝试使用 HUG,或绝对定位的子节点尝试使用 FILL) | 使用 figma.createAutoLayout() 将父节点设为自动布局;先调用 appendChild;仅对自动布局框架本身或 TEXT 子节点使用 HUG;对于绝对定位/不可变/网格子节点,使用 FIXED + resize()。参见 gotchas.md |
"Setting figma.currentPage is not supported" | 使用了同步页面设置器(figma.currentPage = page),该方式不起作用 | 使用 await figma.setCurrentPageAsync(page)——这是切换页面的唯一方式 |
| 属性值超出范围 | 颜色通道大于 1(使用了 0–255,而非 0–1) | 除以 255 |
"Cannot read properties of null" | 节点不存在(ID 错误或页面错误) | 检查页面上下文,验证 ID |
| 脚本挂起/无响应 | 无限循环或未解析的 promise | 检查是否存在 while(true) 或缺少 await;确保代码能够结束 |
"The node with id X does not exist" | 子节点的 detachInstance() 隐式分离了父实例,导致 ID 发生变化 | 从稳定的(非实例)父框架开始遍历,重新发现节点 |
脚本成功但结果看起来不正确时
- 调用
get_metadata检查结构是否正确(层级、数量、位置)。 - 调用
get_screenshot检查视觉效果。仔细查看文本是否被裁切(行高导致内容被截断),以及是否存在元素重叠——这些问题很常见,也容易被忽略。 - 找出差异——是结构问题(层级错误、缺少节点)还是视觉问题(颜色错误、布局损坏、内容被裁切)?
- 编写有针对性的修复脚本,仅修改出问题的部分——不要重新创建所有内容。
完整的验证工作流请参见 验证与错误恢复。
8. 提交前检查清单
提交任何 use_figma 调用前,请确认:
- 代码使用
return返回数据(而不是figma.closePlugin()) - 代码没有包装在异步 IIFE 中(会自动为你包装)
-
return值包含可操作的结构化数据(ID、数量) - 未在任何位置使用
figma.notify() - 未使用
console.log()输出(改用return) - 所有颜色都使用 0–1 范围(而不是 0–255)
- Paint 的
color对象仅使用{r, g, b},不包含a字段(不透明度应设置在 paint 层级:{ type: 'SOLID', color: {...}, opacity: 0.5 }) - Fills/strokes 通过重新赋值为新数组来更新(而不是原地修改)
- 页面切换使用
await figma.setCurrentPageAsync(page)(同步 setterfigma.currentPage = page不起作用) -
layoutSizingVertical/Horizontal = 'FILL'在parent.appendChild(child)之后设置 - 每次文本修改都遵循规范流程:
loadFontAsync→await→ 修改characters/字体/字号等 → 返回受影响节点的 ID。该流程适用于任何字体系列/样式,而不只是 Inter(Inter 只是碰巧预加载了)。 - 样式名称已通过
listAvailableFontsAsync()验证,而不是凭记忆猜测("SemiBold"与"Semi Bold"是常见陷阱) - 对于作用域为
FONT_FAMILY的变量,在调用setBoundVariable("fontFamily", …)、setValueForMode或setExplicitVariableModeForCollection之前,已加载所有相关模式中的每个值 -
lineHeight/letterSpacing使用{unit, value}格式(而不是纯数字) - 在设置尺寸模式之前调用
resize()(它会将尺寸模式重置为 FIXED) - 对于多步工作流,前序调用返回的 ID 以字符串字面量形式传入(而不是变量)
- 新建的顶层节点放置在远离 (0,0) 的位置,以避免与现有内容重叠
- 含有结构相关子节点的容器使用
figma.createAutoLayout(),而不是绝对 x/y 坐标(见规则 12a) - 收集所有已创建/修改节点的 ID,并包含在
return值中 - 每个异步调用(
loadFontAsync、setCurrentPageAsync、importComponentByKeyAsync等)都使用await等待完成,不要让 Promise 在后台运行
9. 创建前了解约定
创建任何内容前,请务必检查 Figma 文件。 不同文件使用的命名约定、变量结构和组件模式各不相同。你的代码应遵循文件中已有的约定,而不是强加新的约定。
如果不确定某项约定(命名、作用域、结构),请先检查 Figma 文件,再检查用户的代码库。只有两者都不存在相关约定时,才使用常见模式。
快速检查脚本
列出所有页面和顶层节点:
const pages = figma.root.children.map(p => `${p.name} id=${p.id} children=${p.children.length}`);
return pages.join('\n');
列出所有页面中的现有组件:
search_design_system 可用于已发布的组件。对于画布上的组件,请使用两步扇出流程——不要在一个脚本中循环处理页面。
第 1 步:使用一次只读 use_figma 获取页面 ID:
return figma.root.children.map(p => ({ id: p.id, name: p.name }));
第 2 步:在下一轮助手回复中,并行地为每个页面发出一次 use_figma(在一条消息中包含 N 个工具调用块)。每次调用运行:
// Read-only inspection — skip invisible instance interiors for the
// hundreds-of-times-faster findAllWithCriteria.
figma.skipInvisibleInstanceChildren = true;
const page = await figma.getNodeByIdAsync(PAGE_ID);
await figma.setCurrentPageAsync(page);
// findAllWithCriteria uses an indexed type lookup — hundreds of times faster
// than the findAll(n => n.type === '…') side-effect-in-predicate antipattern.
const matches = page.findAllWithCriteria({ types: ['COMPONENT', 'COMPONENT_SET'] });
return matches.map(n => ({ page: page.name, name: n.name, type: n.type, id: n.id }));
列出现有变量集合及其约定:
const collections = await figma.variables.getLocalVariableCollectionsAsync();
const results = collections.map(c => ({
name: c.name, id: c.id,
varCount: c.variableIds.length,
modes: c.modes.map(m => m.name)
}));
return results;
10. 参考文档
根据任务需要加载以下文档:
| 文档 | 何时加载 | 涵盖内容 |
|---|---|---|
| gotchas.md | 调用任何 use_figma 之前 | 所有已知陷阱及 WRONG/CORRECT 代码示例——从规范的文本编辑方案开始 |
| common-patterns.md | 需要可运行的代码示例时 | 脚本框架:形状、文本、自动布局、变量、组件、多步骤工作流 |
| plugin-api-patterns.md | 创建或编辑节点时 | 填充、描边、自动布局、效果、分组、克隆、样式 |
| api-reference.md | 需要准确了解 API 范围时 | 节点创建、变量 API、核心属性、可用与不可用的功能 |
| validation-and-recovery.md | 多步骤写入或错误恢复时 | get_metadata 与 get_screenshot 工作流、强制错误恢复步骤 |
| component-patterns.md | 创建组件或变体时 | combineAsVariants、组件属性、INSTANCE_SWAP、变体布局、发现现有组件、元数据遍历 |
| variable-patterns.md | 创建或绑定变量时 | 集合、模式、作用域、别名、绑定模式、发现现有变量 |
| text-style-patterns.md | 创建或应用文本样式时 | 字号阶梯、通过 listAvailableFontsAsync 查找字体、列出样式、将样式应用到节点 |
| effect-style-patterns.md | 创建或应用效果样式时 | 投影、列出样式、将样式应用到节点 |
| plugin-api-standalone.index.md | 需要了解完整 API 范围时 | Plugin API 中所有类型、方法和属性的索引 |
| plugin-api-standalone.d.ts | 需要准确的类型签名时 | 完整类型定义文件——使用 grep 查找特定符号,不要一次性加载全部内容 |
11. 代码片段示例
你会在本文档中看到各种代码片段。这些片段包含了可重复使用的实用 Plugin API 代码。可以直接使用,也可以在开始操作时将其作为起始代码。如果有适合整理成通用代码片段的关键概念,请明确指出并写入磁盘,以便日后复用。