
Label Studio 前端 Design Tokens 转换工具从 Figma JSON 到 CSS 变量与 Tailwind 主题的工程化实践【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio在 Label Studio 的前端仓库web/目录基于 bun Vite Tailwind CSS 的 monorepo中设计系统通过一条自动化流水线落地设计师在 Figma 中维护的 Design Tokens 以design-tokens.json形式导出再由 design-tokens-converter 转换脚本批量编译为 CSS 变量文件和供 Tailwind 消费的 JavaScript 模块从而同时支撑 CSS 直接取值var(--color-...)与 Tailwind 语义化类名text-primary-content两种使用方式。读完本文你将掌握该转换工具的完整用法、design-tokens.json的集合结构与参考引用解析机制、明暗主题与响应式字体的输出策略以及产物如何接入 Tailwind 配置。一、输入格式Figma 导出的 design-tokens.json转换的输入是放置在web/工作区根目录的 design-tokens.json约 180KB当前仓库中已包含真实设计数据。从该文件的顶层结构看它包含四个集合collection顶层键含义处理函数源码位置color语义化颜色neutral / primary / accent 等带 light/dark 模式processColorTokensprimitives基础色板$color、基础间距$spacing、基础字体$typography、圆角$corner-radiusprocessPrimitiveColors/processPrimitiveSpacing/processPrimitiveTypography/processPrimitiveCornerRadiussizing派生尺寸类 token含嵌套命名如圆角processSizingTokenstypography语义化排版 tokenfont-family、font-size、font-weight、line-height、letter-spacing桌面 移动模式processTypographyTokens每个 token 节点的典型形态是{ $type: color, $value: {primitives.$color.$sand.100}, $variable_metadata: { modes: { light: ..., dark: ... } } }$type标明值类型$value可能是字面量也可能是形如{primitives.$color.$sand.100}的token 引用。例如当前仓库中color下的--color-neutral-surface即引用{primitives.$color.$sand.100}primary系列则引用$grape色族——引用解析是该工具最核心的能力之一见下文。二、使用方法三步完成转换按 README 的说明流程如下从 Figma 导出 design tokens 为design-tokens.json放到label-studio/web/目录前端工作区根目录运行转换脚本。README 中给出的入口命令是nx design-tokens ui在当前仓库中等价入口已改为 bun 脚本——web/package.json 中定义了design-tokens: bun tools/design-tokens-converter/design-tokens-converter.mjs因此也可以直接在web/下执行bun run design-tokens两种方式最终都运行同一个脚本 design-tokens-converter.mjs其 package.json 将其同时声明为包humansignal/design-tokens-converter的 bin 可执行文件另有一个 无扩展名的入口 shim 仅import该 .mjs 文件便于直接node调用生成覆盖写入两个产物web/libs/ui/src/tokens/tokens.prefix.css—— 明/暗主题 CSS 变量 移动端响应式排版变量web/libs/ui/src/tokens/tokens.js—— 供 Tailwind 配置消费的 JS 对象。脚本自身会先通过findWorkspaceRoot()源码 L74-L86从脚本所在目录逐级向上查找以web结尾的目录定位工作区根找不到则抛出Could not find workspace root directory随后校验design-tokens.json是否存在缺失时打印The design-tokens.json file does not exist at ...并以退出码 1 结束源码 L1110-L1159。三、转换管线从 JSON 到两份产物的源码剖析processDesignVariables()源码 L150-L203是整个管线的调度中心它按固定顺序处理各集合最终产出{ cssVariables: { light, dark, mobile }, jsTokens: { colors, spacing, typography, cornerRadius } }的中间结构再分别交给generateCssContent()L956-L983与generateJsContent()L1094-L1105生成文件。几个值得关注的实现细节3.1 参考引用解析{primitives...}不落地为字面量resolveReference()L886-L913按.分段沿对象导航解析{...}形式的引用。但对指向基础值的引用转换器更聪明的做法是在 CSS 中保留为变量链而非解算成字面量当引用的目标是primitives集合时直接改写为对应 CSS 变量。例如--corner-radius-*引用 spacing 时输出--xxx: var(--spacing-xxx)L391-L405颜色引用{primitives.$color.$sand.100}则经resolveColor()L835-L878改写为var(--color-sand-100)。这样基础色板只定义一次语义 token 全部引用它改基础值即全局生效——产物tokens.prefix.css中可以看到这种结构:root { --color-neutral-surface: var(--color-sand-100); --color-primary-surface: var(--color-grape-700); --spacing-50: 0.125rem; --font-size-14: 0.875rem; /* ... */ }引用解析失败时路径在 JSON 中不存在resolveReference会原样返回未解析的字符串不会中断转换属于容错设计。3.2 单位换算与字体家族规范化数值类 token 统一经convertToRem()L100-L107换算以 16px 为基准保留 4 位小数并去掉尾随零14px → 0.875rem0保持无单位字体家族列表经formatFontFamilyForCss()L127-L143格式化具体字体名加双引号sans-serif、monospace、system-ui等 CSS 通用家族按规范保持不加引号Figma 会把斜体字重如Medium Italic作为非数值 font-weight 导出转换器会跳过这些条目isFontWeightItalicVariantL528-L535改而在 CSS 中直接注入--font-style-normal: normal与--font-style-italic: italic两条变量L364-L375。3.3 颜色输出RGB 化 -raw变量 暗色模式颜色 token 经hexToRgb()L765-L794从 3/6 位 hex 转为rgb(r g b)格式目的是配合 CSS 的rgb(var(--x) / alpha)用法支持透明度。此外对名称包含primary、shadow、outline、surface、accent、background这组关键词的语义色RAW_COLOR_VALUE_TOKENSL64还会额外输出--color-xxx-raw: r g b形式的裸三元组变量例如产物中的--color-neutral-surface: var(--color-sand-100); --color-neutral-surface-raw: 249 248 246;-raw变量专门用于rgb(var(--color-neutral-surface-raw) / 0.5)这类半透明写法源码注释见 L723-L724。暗色模式则依据$variable_metadata.modes.dark输出到[data-color-schemedark]选择器块——当前产物中该块位于tokens.prefix.css第 567 行起与:root块一一对应。3.4 响应式排版只输出“与桌面不同的”移动值typography集合的 token 带有desktop与mobile两种模式与颜色的 light/dark 类似。processTokenCollection()L510-L562会为每个 token 计算桌面值写入:root再取$variable_metadata.modes.mobile解析出移动值仅当移动值与桌面值不同时才追加进media (max-width: 767px)块常量MOBILE_MEDIA_QUERYL67媒体查询上限对齐 Tailwind 的md断点768px。当前产物中该块第 866 行起形如media (max-width: 767px) { :root { --font-size-body-medium: var(--font-size-14); --font-size-title-large: var(--font-size-22); --line-height-label-medium: var(--line-height-20); /* ... 仅桌面与移动不同的 token ... */ } }由于 Tailwind 工具类与Typography组件最终都通过var(--font-size-body-medium)这类语义变量解析768px 以下会自动应用移动端字号无需逐组件覆盖README 也建议只有在刻意切换到“另一个”token 以调整布局密度时才显式使用max-md:text-*。3.5 已知问题与尾差修正Figma 源数据中圆角集合写作corder-radiustypo转换器在processSizingTokens()的嵌套 key 拼接中做了replace(corder, corner)修正L436-L437确保产物中 CSS 变量名与 JS key 都是正确的corner-radius。3.6 JS 产物面向 Tailwind 的结构整形generateJsContent()生成的tokens.js头部声明“此文件由工具生成请改design-tokens.json而不是本文件”。序列化前先经过两步整形mergePrimitiveValues()L1058-L1087把各级primitive子树向上合并使最终对象按类别扁平化transformColorObjectForTailwind()L990-L1034把surface-hover这类连字符变体重组为嵌套对象——基础名下的默认值收进DEFAULT变体作为兄弟属性从而匹配 Tailwind 的colors扩展结构。实际产物 tokens.js 开头即为const designTokens { colors: { neutral: { surface: { DEFAULT: var(--color-neutral-surface), hover: var(--color-neutral-surface-hover), active: var(--color-neutral-surface-active), inset: var(--color-neutral-surface-inset), }, /* ... */ }, /* primary / accent / spacing / typography / cornerRadius ... */ }, }; export default designTokens;序列化函数serializeToJsLiteral()L29-L58会尽量输出不带引号的合法标识符 key数字 key 输出为数字字面量以匹配仓库 Biome 的代码风格约束。四、产物使用方式CSS 变量与 Tailwind 双通道4.1 在样式表中导入 CSS 变量import libs/ui/src/tokens/tokens.prefix.css;之后即可在任意样式中使用语义变量均取自 README 示例变量名可在产物中逐一核对存在/* 颜色 */ .my-element { color: var(--color-primary-content); background-color: var(--color-neutral-surface); } /* 间距 */ .padded { padding: var(--spacing-base); margin: var(--spacing-wide); } /* 排版 */ .heading { font-family: var(--font-family-sans); font-size: var(--font-size-24); line-height: var(--line-height-32); font-weight: var(--font-weight-bold); } /* 圆角 */ .rounded { border-radius: var(--corner-radius-medium); }暗色模式通过在body上切换data-color-schemedark属性生效对应产物中的[data-color-schemedark]块body>// tailwind.config.js (ESM) import designTokens from ./libs/ui/src/tokens/tokens.js; export default { theme: { extend: { colors: { ...designTokens.colors, }, spacing: designTokens.spacing, fontSize: designTokens.typography.fontSize, lineHeight: designTokens.typography.lineHeight, letterSpacing: designTokens.typography.letterSpacing, fontFamily: designTokens.typography.fontFamily, fontWeight: designTokens.typography.fontWeight, borderRadius: designTokens.cornerRadius, }, }, };CommonJS 环境下用require(./libs/ui/src/tokens/tokens.js).default获取默认导出。当前仓库的实际接入方式与之同构web/tailwind.config.js 只有一行转发到 libs/ui/src/tailwind.config.js后者用createRequire加载同目录的./tokens/tokens.js并在theme.extend中展开...tokens.colors、...tokens.typography.fontSize、...tokens.spacing等L57-L129。由于每个工具类的值本身就是var(--xxx)字符串Tailwind 类名最终也走 CSS 变量天然获得暗色模式与响应式排版能力。接入后即可直接使用语义类名div classtext-primary-content bg-neutral-surface…/div !-- 颜色 -- div classp-base my-large…/div !-- 间距 -- h1 classfont-sans text-24 leading-32 font-bold…/h1 !-- 排版 -- div classrounded-medium…/div !-- 圆角 --libs/ui/src/tokens/目录下的 tokens.stories.tsx 还配套了 Storybook 示例可通过 web/package.json 的storybook:serve端口 4400启动查看同目录的colors.prefix.css、typography.prefix.css是拆分主题文件prefix命名对应仓库的 postcss-prefix-lsf.cjs 前缀化方案。五、设计 token 更新流程与注意事项当 Figma 侧产出新版 token 时README 的 “Updating Design Tokens” 一节用新导出的文件替换工作区根目录的design-tokens.json重新运行转换命令nx design-tokens ui或bun run design-tokens两份产物文件即被完整重新生成不需要手工修补。使用上的注意事项两个产物文件都带DO NOT EDIT DIRECTLY头注释任何改动都应回到design-tokens.json再重新生成脚本要求工作区根目录名以web结尾且design-tokens.json必须存在且是合法 JSON否则进程以非零码退出并打印诊断信息移动端字号只覆盖“桌面/移动不一致”的 token若某 token 两侧一致产物中不会出现在媒体查询块里这是预期行为圆角的corder-radius拼写问题只在sizing集合内做修正L437如未来 Figma 导出结构变化例如键名调整需要回到processDesignVariables()的各分支条件核对。六、小结Label Studio 前端的这条 token 流水线体现了“设计数据即单一事实源”的常见做法Figma 导出 JSON → 一次性编译 → CSS 变量tokens.prefix.css JS 主题对象tokens.js双产物 → 同时服务原生 CSS 与 Tailwind。理解它的内部实现引用改写成变量链、hex 转 RGB -raw透明度通道、data-color-scheme暗色块、768px 断点的差异化排版输出、Tailwind 颜色结构整形既有助于排查“某个类名/变量不存在”类问题也为在其他项目中自建同类工具提供了可参照的完整样本。【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考