figmascope 的默认导出目标是 Jetpack Compose。但包是 Agent 无关的——IR 节点类型、令牌格式和字符串引用同样可以干净地映射到 React + Tailwind。你只需告诉 Agent 以 JSX 为目标,而不是 Kotlin。
本指南涵盖 IR 到 JSX 的映射、如何用 tokens.json 中的令牌扩展 tailwind.config.js,以及在 React 端产生最少偏差的提示模式。
一个重要的前置说明
Compose 是 figmascope 测试最多的目标。IR、令牌格式和 CONTEXT.md 约束都是以 Compose 为设计出发点的。React + Tailwind 可以正常工作——IR 映射是干净的——但你会看到略多的偏差,尤其是在排版和 overlay 布局方面。标记任何看起来不对的地方,并在第一遍后运行令牌检查。
步骤 1:生成并解压包
unzip ~/Downloads/context-bundle.zip -d ./design/
ls design/
# CONTEXT.md _meta.json components/ screens/ strings.json tokens.json
步骤 2:用设计令牌扩展 Tailwind 配置
在提示之前,将 tokens.json 映射到你的 tailwind.config.js。这是使 Tailwind 令牌感知的关键步骤——不是在 className 字符串中使用硬编码十六进制值,而是使用可追溯回设计的语义名称。
// tailwind.config.js
const tokens = require('./design/tokens.json')
// 构建颜色映射:{ 'brand-7f5cfe': '#7F5CFE', ... }
const colors = Object.fromEntries(
Object.entries(tokens.color).map(([key, val]) => [
`brand-${key}`, val
])
)
// 构建间距映射:{ 'ds-4': '4px', 'ds-8': '8px', ... }
const spacing = Object.fromEntries(
Object.entries(tokens.spacing).map(([key, val]) => [
`ds-${key}`, `${val}px`
])
)
// 构建圆角映射
const borderRadius = Object.fromEntries(
Object.entries(tokens.radius).map(([key, val]) => [
`ds-${key}`, val === 9999 ? '9999px' : `${val}px`
])
)
module.exports = {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {
colors,
spacing,
borderRadius,
}
}
}
这会生成如 bg-brand-7f5cfe、p-ds-16、rounded-ds-12 这样的 Tailwind 类。类名不算好看,但可追溯——每个类都映射回一个令牌键。
如果你更喜欢语义别名,可以添加一个别名层:
// 在 theme.extend.colors 中:
primary: tokens.color['7f5cfe'],
background: tokens.color['f6f2ea'],
surface: tokens.color['ffffff'],
给 Agent 两者——原始令牌配置和语义别名——这样它可以在上下文中选择正确的名称。
步骤 3:提示 Agent 以 React + Tailwind 为目标
CONTEXT.md 说默认目标是 Compose。在你的提示中明确覆盖它:
将 ./design/screens/home.json 实现为使用 Tailwind CSS 的 React 函数式组件。
框架覆盖:忽略 CONTEXT.md 中的 Compose 指令。目标是 React + Tailwind。
规则:
- 读取 ./design/tokens.json。令牌已扩展到 Tailwind 配置中——
使用对应令牌键的 Tailwind 类(例如 bg-brand-7f5cfe、p-ds-16)。
- UI 字符串来自 ./design/strings.json。按键导入和引用它们。
- IR 节点类型映射:
stack (axis:vertical) → <div className="flex flex-col gap-[Xpx]">
stack (axis:horizontal) → <div className="flex flex-row gap-[Xpx]">
overlay → <div className="relative"> 带绝对定位子元素
absolute → <div className="absolute" style={{"{{"}}top, left, width, height{{"}}"}}>
leaf (text) → <span> 或 <p> 带 Tailwind 文本类
leaf (rectangle) → <div> 带 bg 和 rounded 类
- 不要硬编码十六进制值。所有颜色必须使用令牌配置中的 Tailwind 类。
- 不要硬编码字符串。使用 strings.json 键。
输出到:src/screens/HomeScreen.tsx
IR 到 JSX 的映射
以下是 React + Tailwind 的完整映射表:
| IR 类型 | 属性 | JSX 模式 |
|---|---|---|
stack | axis: "vertical" | <div className="flex flex-col gap-ds-{n}"> |
stack | axis: "horizontal" | <div className="flex flex-row gap-ds-{n}"> |
overlay | 分层子元素 | <div className="relative"> 带 className="absolute ..." 子元素 |
absolute | x、y、w、h | <div className="absolute" style={{"{{"}}top: y, left: x, width: w, height: h{{"}}"}}> |
leaf | type: "text" | <span className="text-{size} font-{weight} leading-{lh} text-brand-{color}"> |
leaf | type: "rectangle" | <div className="bg-brand-{color} rounded-ds-{r}"> |
间距和内边距值:使用 Tailwind 配置扩展中的 ds-{n} 间距类。如果间距值不是干净的令牌键,使用 Tailwind 的任意值语法:gap-[20px]。
真实示例:主屏幕 IR 转 JSX
使用 Compose 演练中相同的 IR:
import strings from '../../design/strings.json'
export function HomeScreen() {
return (
<div className="flex flex-col gap-ds-24 p-ds-16 bg-brand-f6f2ea min-h-screen">
<h1 className="text-2xl font-bold leading-tight text-brand-1a1a2e">
{strings['home.title'].value}
</h1>
<div className="flex flex-col gap-ds-12">
<div className="bg-white rounded-ds-12 p-ds-16">
<span className="text-xs font-medium text-brand-7f5cfe">
{strings['home.card.label'].value}
</span>
</div>
</div>
</div>
)
}
每个 className 都是可追溯的。gap-ds-24 → spacing.24 → 24px。text-brand-7f5cfe → color.7f5cfe → #7F5CFE。如果某个值偏离了(例如,Agent 写了 gap-6 而不是 gap-ds-24),在代码审查中立即可见。
为什么 tokens.json + Tailwind 配置有效
两个系统都是令牌优先的。Tailwind 用自定义值扩展基础配置;tokens.json 已经构建为自定义值映射。扩展步骤(上面的步骤 2)是一次性设置——之后,Agent 使用语义上绑定到设计系统的 Tailwind 类名,而不是任意工具类。
结果是:当设计令牌改变时(例如主色从 #7F5CFE 变为 #6B4EE6),你更新 tokens.json 中的一个值,重新运行配置导入,Tailwind 重新生成。组件代码不需要改变。
令牌漂移检查
实现后,要求 Agent 审计漂移:
审计 src/screens/HomeScreen.tsx 中的令牌漂移。
检查:
1. 任何未通过令牌配置中的 Tailwind 类引用的十六进制颜色值。
2. 任何应该是 ds-{n} 类的硬编码 px 或 rem 间距值。
3. 任何未来自 design/strings.json 的 UI 字符串。
列出违规。生成修复它们的差异。
Overlay 和 absolute——棘手的情况
Overlay 节点需要一个 relative 父元素和 absolute 定位的子元素。IR 按 z 顺序列出子元素(第一个 = 底层)。告诉 Agent 在 JSX 中保持这个顺序——React 按 DOM 顺序渲染,CSS position: absolute 相应地叠加。
Absolute 节点使用来自 Figma 的原始像素坐标。这几乎总是来自没有使用自动布局构建的设计。如果你看到很多 absolute 节点,通常意味着 Figma 文件有手动定位——生成的代码在不同视口尺寸下会很脆弱。考虑标记这一点并重构为 flex 布局。
React 中的字符串处理
与 Android(strings.json 键映射到 R.string.* 资源 ID)不同,在 React 中你直接导入 JSON:
import strings from '../../design/strings.json'
// 用法
{strings['home.title'].value}
// 或带后备值
{strings['home.title']?.value ?? strings['home.title']?.fallback ?? 'Untitled'}
如果你使用 i18n 库(react-i18next、next-intl),strings.json 中的点记法键直接映射到翻译键命名空间。告诉 Agent 你使用的 i18n 库,这样它可以生成正确的调用模式。
React 端的诚实局限
排版工具类。Tailwind 的文本工具类(text-xs、text-2xl)与 tokens.json 中的 typography 令牌不是 1:1 对应的。Tailwind 有固定的类型比例;令牌文件有任意大小。你需要用令牌值扩展 Tailwind 的 fontSize 配置,或使用任意值(text-[24px])。两者都有效;扩展配置更干净。
行高。同样的问题——Tailwind 的 leading 工具类与任意 lineHeight 值不匹配。使用 leading-[{value}] 或扩展配置。
渐变。IR 中不支持。任何渐变填充在 _meta.json 中显示为警告,并从节点的填充属性中省略。手动处理。
这些都不是阻碍——它们是已知的局限。令牌感知的基础是稳固的;边缘情况只需手动处理。
从 figmascope 导出你的包开始,然后将本指南与 Cursor 工作流或 Claude Code 工作流一起使用来驱动实现。