创建并维护 Figma Code Connect 模板文件,用于将 Figma 组件映射到代码片段。当用户提及 Code Connect、Figma 组件映射、设计稿转代码(design-to-code),或要求创建/更新 .figma.ts、.figma.js 文件时使用此 Skill。
Code Connect
概述
创建将 Figma 组件映射到代码片段的 Code Connect 模板文件 (.figma.ts)。获取 Figma URL 后,按照以下步骤创建模板。
注意:你只能编写
.figma.ts模板文件,绝不能编写.figma.tsx。 本 Skill 生成的是无解析器模板(parserless templates):即默认导出中使用figma.code`...`标签模板的.figma.ts文件。切勿编写.figma.tsx文件,也切勿使用figma.connect()—— 那是另一种独立的基于解析器的(parser-based) Code Connect 格式(通过不同方式发布),属于本 Skill 的错误产物;直接输出为.figma.tsx的文件将被硬性拒绝。如果组件已经存在.figma.tsx,请保持其原封不动,并在其旁边添加你的.figma.ts模板。能力较强的模型可能会习惯性使用记忆中更熟悉的.figma.tsx/figma.connect()模式 —— 请务必克制;在这里,正确的输出永远是.figma.ts+figma.code。
前置条件
- 必须已连接 Figma MCP 服务器 —— 在继续之前,请先验证 Figma MCP 工具(如
get_code_connect_suggestions)是否可用。如果不可用,请引导用户启用 Figma MCP 服务器并重启其 MCP 客户端。 - 组件必须已发布 —— Code Connect 仅适用于已发布到 Figma 团队库(Team Library)的组件。如果组件未发布,请告知用户并停止操作。
- 需要 Enterprise 或 Organization 团队计划 —— Code Connect 在免费版(Free)或专业版(Professional)计划中不可用。
- URL 必须包含
node-id—— Figma URL 中必须包含node-id查询参数。 - TypeScript 类型定义 —— 为了在
.figma.ts文件中获得编辑器自动补全和类型检查,必须在tsconfig.json的types中添加@figma/code-connect/figma-types:{ "compilerOptions": { "types": ["@figma/code-connect/figma-types"] } }
步骤 1:解析 Figma URL
从 URL 中提取 fileKey 与 nodeId:
| URL 格式 | fileKey | nodeId |
|---|---|---|
figma.com/design/:fileKey/:name?node-id=X-Y |
:fileKey |
X-Y → X:Y |
figma.com/file/:fileKey/:name?node-id=X-Y |
:fileKey |
X-Y → X:Y |
figma.com/design/:fileKey/branch/:branchKey/:name |
使用 :branchKey |
提取自 node-id 参数 |
务必将 nodeId 中的连字符转换为冒号:1234-5678 → 1234:5678。
完整示例:
给定 URL:https://www.figma.com/design/QiEF6w564ggoW8ftcLvdcu/MyDesignSystem?node-id=4185-3778
fileKey=QiEF6w564ggoW8ftcLvdcunodeId=4185-3778→4185:3778
步骤 2:发现未映射的组件
用户提供的 URL 可能指向画板(frame)、实例(instance)或变体(variant),而不一定是组件集(component set)或独立组件。使用以下参数调用 MCP 工具 get_code_connect_suggestions:
fileKey—— 提取自步骤 1nodeId—— 提取自步骤 1(冒号格式)excludeMappingPrompt——true(返回尚未映射组件的轻量级列表)
此工具用于识别所选内容中已发布但尚未建立 Code Connect 映射的组件。
处理响应结果:
- "No published components found in this selection"(在此选择中未找到已发布的组件) —— 该节点不包含已发布的组件。告知用户需要先将组件发布到 Figma 团队库中,然后停止操作。
- "All component instances in this selection are already connected to code via Code Connect"(在此选择中的所有组件实例均已通过 Code Connect 连接到代码) —— 所有内容已完成映射。告知用户并停止操作。
- 包含组件列表的正常响应 —— 提取每个返回组件的
mainComponentNodeId。在后续所有步骤中,请使用这些解析后的节点 ID(而非 URL 中的原始 ID)。如果返回了多个组件(例如用户选择了一个包含多个不同组件实例的画板),请对每个组件重复步骤 3–6。
步骤 3:获取组件属性
使用以下参数调用 MCP 工具 get_context_for_code_connect:
fileKey—— 提取自步骤 1nodeId—— 步骤 2 中解析出的mainComponentNodeIdclientFrameworks—— 根据figma.config.json的parser字段确定(例如"react"→["react"])clientLanguages—— 根据项目文件扩展名推断(例如 TypeScript 项目 →["typescript"],JavaScript 项目 →["javascript"])
若存在多个组件,请为每个节点 ID 分别调用一次该工具。
响应结果中包含 Figma 组件的属性定义 —— 请注意每个属性的名称与类型:
- TEXT —— 文本内容(标签、标题、占位符)
- BOOLEAN —— 开关控制(显示/隐藏图标、禁用状态)
- VARIANT —— 枚举选项(尺寸、变体、状态)
- INSTANCE_SWAP —— 绑定到特定组件的可替换嵌套实例(图标、头像)
- SLOT —— 灵活的内容区域(自由布局、混合子节点);在模板中使用
getSlot()(与 INSTANCE_SWAP 不同)
保存此属性列表 —— 你将在步骤 5 编写模板时用到它。
步骤 4:识别代码组件
如果用户未明确说明要连接哪个代码组件:
- 检查
figma.config.json中的paths和importPaths,查找组件所在的位置 - 在代码库中搜索与 Figma 组件名称匹配的代码组件。若
figma.config.json未指定路径,请检查常见目录(src/components/、components/、lib/ui/、app/components/) - 读取候选文件,对比其 Props 接口与步骤 3 获取的 Figma 属性 —— 查找匹配的变体类型、尺寸选项、布尔标记和插槽 Props
- 如果存在多个匹配的候选组件,挑选 Props 接口契合度最高的那个,并向用户说明你的判断理由
- 如果未找到匹配组件,展示契合度最高的 2 个候选组件,并请用户确认或提供正确的路径
在继续执行步骤 5 前与用户进行确认。展示匹配结果:找到了哪个代码组件、位于何处,以及匹配原因(Props 对应关系、命名、用途)。
读取 figma.config.json 以获取导入路径别名 —— importPaths 部分将 glob 模式映射到导入标识符,paths 部分将这些标识符映射到实际目录。
读取代码组件的源码以了解其 Props 接口 —— 这将为步骤 5 中如何将 Figma 属性映射到代码 Props 提供依据。
步骤 5:创建模板文件 (.figma.ts)
文件位置
将文件放置在现有 Code Connect 文件同级目录下。检查 figma.config.json 的 include 模式以确定正确的目录。将其命名为 ComponentName.figma.ts —— 切勿命名为 ComponentName.figma.tsx。 .figma.tsx 扩展名属于基于解析器的格式;不要创建此类文件,也不要修改已有的此类文件。
模板结构
每个模板文件均遵循以下结构:
// url=https://www.figma.com/file/{fileKey}/{fileName}?node-id={nodeId}
// source={步骤 4 中代码组件的路径}
// component={步骤 4 中代码组件的名称}
import figma from 'figma'
const instance = figma.selectedInstance
// 从 Figma 组件中提取属性(参见下方的属性映射)
// ...
export default {
example: figma.code`<Component ... />`, // 必需:代码片段
imports: ['import { Component } from "..."'], // 可选:导入语句
id: 'component-name', // 必需:唯一标识符
metadata: { // 可选
nestable: true, // true = 在父级中内联,false = 显示为胶囊块(pill)
props: {} // 可供父级模板访问的数据
}
}
属性映射
使用步骤 3 获取的属性列表来提取属性值。对于每种 Figma 属性类型,使用对应的提取方法:
| Figma 属性类型 | 模板方法 | 使用场景 |
|---|---|---|
| TEXT | instance.getString('Name') |
文本标签、标题、占位符文本 |
| BOOLEAN | instance.getBoolean('Name', { true: ..., false: ... }) |
显隐开关、条件 Props |
| VARIANT | instance.getEnum('Name', { 'FigmaVal': 'codeVal' }) |
尺寸、变体、状态等枚举类型 |
| INSTANCE_SWAP | instance.getInstanceSwap('Name') |
固定组件插槽中的可替换实例(配合 hasCodeConnect() / executeTemplate() 使用)—— 切勿与下方的 SLOT 属性混淆 |
| SLOT | instance.getSlot('Name') |
仅当 Figma 属性类型为 SLOT 时用于自由插槽内容 |
| (child layer) | instance.findInstance('LayerName') |
没有属性绑定的具名子实例 |
| (text layer) | instance.findText('LayerName') → .textContent |
来自具名图层的文本内容 |
TEXT —— 直接获取字符串值:
const label = instance.getString('Label')
VARIANT —— 将 Figma 枚举值映射为代码属性值:
const variant = instance.getEnum('Variant', {
'Primary': 'primary',
'Secondary': 'secondary',
})
const size = instance.getEnum('Size', {
'Small': 'sm',
'Medium': 'md',
'Large': 'lg',
})
BOOLEAN —— 原生布尔值或映射为具体属性值:
// 原生布尔值
const disabled = instance.getBoolean('Disabled')
// 映射为代码属性值(例如代码 prop 是枚举而非布尔值时)
const size = instance.getBoolean('Show Label', { true: 'large', false: 'small' })
在存在有效对应关系时,将 Figma 属性映射到代码 Props。 Figma 属性与代码 Props 并不总是 1:1 对应的 —— 有些 Figma 属性可以直接映射(通过名称或上述 API 方法),有些则没有对应的代码属性。存在映射关系时进行配置;没有合适映射时直接忽略该 Figma 属性,切勿凭空编造代码 prop。绝对不要生成代码组件 Props 接口中不存在的属性名。
穷尽式变体处理
当 VARIANT 属性包含多个可选值时,getEnum 的映射必须穷尽列出 get_context_for_code_connect 返回的每一个值。切勿遗漏任何值 —— 未映射的值会静默返回 undefined,导致生成错误的代码输出。
// 错误 —— 遗漏了 'Warning',会导致渲染为 undefined
const status = instance.getEnum('Status', {
'Success': 'success',
'Error': 'error',
})
// 正确 —— 每一个值都已映射
const status = instance.getEnum('Status', {
'Success': 'success',
'Error': 'error',
'Warning': 'warning',
'Info': 'info',
})
当两个或多个 VARIANT 属性组合产生不同的代码输出时,应生成穷尽的条件分支。例如,2 个变体 × 2 个取值 = 4 个分支:
const type = instance.getEnum('Type', { 'Filled': 'filled', 'Outlined': 'outlined' })
const status = instance.getEnum('Status', { 'Success': 'success', 'Error': 'error' })
let colorClass
if (type === 'filled' && status === 'success') {
colorClass = 'bg-green-500 text-white'
} else if (type === 'filled' && status === 'error') {
colorClass = 'bg-red-500 text-white'
} else if (type === 'outlined' && status === 'success') {
colorClass = 'bg-transparent border-green-500'
} else if (type === 'outlined' && status === 'error') {
colorClass = 'bg-transparent border-red-500'
}
如果变体组合产生的输出是重复性的(例如 Size 并不改变代码片段的结构 —— 只是单纯作为 prop 透传),则每个变体使用单个 getEnum 映射即可,无需编写交叉相乘的条件分支。
INSTANCE_SWAP —— 访问可替换的组件实例:
const icon = instance.getInstanceSwap('Icon')
let iconCode
if (icon && icon.type === 'INSTANCE') {
iconCode = icon.executeTemplate().example
}
SLOT —— 仅当步骤 3 返回的 Figma 组件属性类型为 SLOT 时,getSlot(propName) 才有效。切勿对 INSTANCE_SWAP 属性使用 getSlot()(该属性应使用 getInstanceSwap())。Slot 是组件定义中明确划定的“内容区域”,而非通用的嵌套实例。
- 方法签名:
getSlot(propName: string): ResultSection[] | undefined
// Figma 组件中的 "Content" 属性类型必须为 SLOT
<!-- truncated for translation batch; full body continues in source -->






