Use Cases (更新: 2026/6/3)

用 Claude Code 实践 Design Tokens:从 Figma 交接到 CSS 变量与 Tailwind

用 Claude Code 落地 Design Tokens,串起 Style Dictionary、CSS 变量、Tailwind 和 React。

用 Claude Code 实践 Design Tokens:从 Figma 交接到 CSS 变量与 Tailwind

Design Tokens 是 UI 变更的契约

Design Tokens 是把颜色、间距、字号、圆角、阴影等设计决策保存为数据的做法。简单说,不要在组件里到处写 #2563eb16px0.5rem,而是把这些值放进 tokens.json,再生成 CSS、Tailwind 配置或组件能消费的变量。

Claude Code 很适合这类工作,因为 token 是可读、可审查、可构建的。它可以检查现有 CSS,找出重复的硬编码值,建议语义化命名,修改组件,运行构建并总结差异。不要只说“让 UI 统一”。更好的方式是指定 token 源文件、组件范围、对比度标准和必须执行的命令。

相关内容可以继续看用 Claude Code 构建设计系统用 Claude Code 改善无障碍。官方参考包括稳定版 Design Tokens Format Module 2025.10Claude Code docsFigma Variables plugin APITailwind theme docsStyle DictionaryMDN CSS 自定义属性WCAG 对比度说明

raw token 与 semantic token

raw token 描述原材料,例如 color.blue.600space.4font.size.base。semantic token 描述用途,例如 color.action.primary.bgcolor.text.mutedcolor.surface.default。component token 则描述某个组件自己的契约,例如 button.primary.paddingX

类型示例适合场景
rawcolor.blue.600色阶、间距、字号等基础尺度
semanticcolor.action.primary.bg业务含义、主题切换、暗色模式
componentbutton.primary.paddingX组件确实需要稳定局部规则时

建议先从 raw 和 semantic 开始。按钮不要直接消费 color.blue.600,否则品牌色从蓝色换成绿色后,名字会变得误导。按钮消费 color.action.primary.bg 时,值可以换,意图仍然清楚。

把 Figma-like spec 变成代码契约

Figma Variables 很有用,但给 Claude Code 的不应是原始命名导出,而是可审查的 handoff。Figma-like spec 写清来源文件、模式、请求变更、受影响组件和 review rules。这样可以降低 risk:不要让 Blue / 600 这种视觉名称直接进入 React,而应映射到 color.action.primary.bg 这类语义 token。

{
  "figmaSource": {
    "file": "Marketing UI Kit",
    "collection": "Brand v2",
    "modes": ["light", "dark"]
  },
  "changeRequest": {
    "type": "replace-token",
    "from": "color.blue.600",
    "to": "color.action.primary.bg",
    "components": ["Button", "Link", "Card"]
  },
  "reviewRules": [
    "Do not use raw color tokens in component CSS.",
    "Keep focus and hover tokens explicit.",
    "List affected use case and pitfall before editing files."
  ]
}

先让 Claude Code 输出影响表,再决定是否编辑文件。这个 workflow 能提前发现常见 pitfall:一个 token 可能同时影响 Button、Link、Card 和 focus outline。

可运行的 tokens.json

把下面内容保存为 tokens/tokens.json

{
  "color": {
    "blue": {
      "50": { "$type": "color", "$value": "#eff6ff" },
      "600": { "$type": "color", "$value": "#2563eb" },
      "700": { "$type": "color", "$value": "#1d4ed8" }
    },
    "slate": {
      "50": { "$type": "color", "$value": "#f8fafc" },
      "100": { "$type": "color", "$value": "#f1f5f9" },
      "700": { "$type": "color", "$value": "#334155" },
      "900": { "$type": "color", "$value": "#0f172a" }
    },
    "white": { "$type": "color", "$value": "#ffffff" },
    "focus": { "$type": "color", "$value": "#f59e0b" },
    "surface": {
      "default": { "$type": "color", "$value": "{color.white}" },
      "muted": { "$type": "color", "$value": "{color.slate.50}" },
      "inverse": { "$type": "color", "$value": "{color.slate.900}" }
    },
    "text": {
      "default": { "$type": "color", "$value": "{color.slate.900}" },
      "muted": { "$type": "color", "$value": "{color.slate.700}" },
      "inverse": { "$type": "color", "$value": "{color.white}" }
    },
    "action": {
      "primary": {
        "bg": { "$type": "color", "$value": "{color.blue.600}" },
        "bgHover": { "$type": "color", "$value": "{color.blue.700}" },
        "text": { "$type": "color", "$value": "{color.white}" }
      }
    }
  },
  "dark": {
    "color": {
      "surface": {
        "default": { "$type": "color", "$value": "{color.slate.900}" },
        "muted": { "$type": "color", "$value": "{color.slate.700}" }
      },
      "text": {
        "default": { "$type": "color", "$value": "{color.white}" },
        "muted": { "$type": "color", "$value": "{color.slate.100}" }
      },
      "action": {
        "primary": {
          "bg": { "$type": "color", "$value": "{color.blue.50}" },
          "bgHover": { "$type": "color", "$value": "{color.white}" },
          "text": { "$type": "color", "$value": "{color.slate.900}" }
        }
      }
    }
  },
  "space": {
    "2": { "$type": "dimension", "$value": "0.5rem" },
    "3": { "$type": "dimension", "$value": "0.75rem" },
    "4": { "$type": "dimension", "$value": "1rem" },
    "6": { "$type": "dimension", "$value": "1.5rem" }
  },
  "font": {
    "size": {
      "sm": { "$type": "dimension", "$value": "0.875rem" },
      "base": { "$type": "dimension", "$value": "1rem" },
      "lg": { "$type": "dimension", "$value": "1.125rem" }
    },
    "weight": {
      "medium": { "$type": "fontWeight", "$value": "500" },
      "bold": { "$type": "fontWeight", "$value": "700" }
    }
  },
  "radius": {
    "md": { "$type": "dimension", "$value": "0.5rem" },
    "lg": { "$type": "dimension", "$value": "0.75rem" }
  },
  "shadow": {
    "button": { "$type": "shadow", "$value": "0 1px 2px rgb(15 23 42 / 0.16)" }
  }
}

用 Style Dictionary 生成 CSS 变量

npm install --save-dev style-dictionary

创建 style-dictionary.config.js

export default {
  source: ["tokens/tokens.json"],
  hooks: {
    formats: {
      "css/variables-with-dark": ({ dictionary }) => {
        const light = dictionary.allTokens
          .filter((token) => !token.path.includes("dark"))
          .map((token) => `  --${token.name}: ${token.value};`)
          .join("\n");

        const dark = dictionary.allTokens
          .filter((token) => token.path[0] === "dark")
          .map((token) => `  --${token.path.slice(1).join("-")}: ${token.value};`)
          .join("\n");

        return `:root {\n${light}\n}\n\n[data-theme="dark"] {\n${dark}\n}\n`;
      }
    }
  },
  platforms: {
    css: {
      transformGroup: "css",
      buildPath: "src/styles/",
      files: [{ destination: "tokens.css", format: "css/variables-with-dark" }]
    }
  }
};

package.json 中加入:

{
  "scripts": {
    "tokens:build": "style-dictionary build --config style-dictionary.config.js"
  }
}

生成的 src/styles/tokens.css 会类似这样:

:root {
  --color-action-primary-bg: #2563eb;
  --color-action-primary-bg-hover: #1d4ed8;
  --color-action-primary-text: #ffffff;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --font-size-base: 1rem;
  --font-weight-bold: 700;
  --radius-md: 0.5rem;
  --shadow-button: 0 1px 2px rgb(15 23 42 / 0.16);
}

[data-theme="dark"] {
  --color-surface-default: #0f172a;
  --color-text-default: #ffffff;
  --color-action-primary-bg: #eff6ff;
  --color-action-primary-text: #0f172a;
}

CSS 自定义属性就是浏览器原生变量。给 htmlbody 加上 data-theme="dark" 后,同一个组件会读取暗色主题的值。

连接 Tailwind

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./src/**/*.{ts,tsx,js,jsx,mdx}"],
  theme: {
    extend: {
      colors: {
        surface: { DEFAULT: "var(--color-surface-default)", muted: "var(--color-surface-muted)" },
        text: { DEFAULT: "var(--color-text-default)", muted: "var(--color-text-muted)", inverse: "var(--color-text-inverse)" },
        action: { primary: "var(--color-action-primary-bg)", "primary-hover": "var(--color-action-primary-bg-hover)" }
      },
      spacing: { 3: "var(--space-3)", 4: "var(--space-4)", 6: "var(--space-6)" },
      borderRadius: { md: "var(--radius-md)", lg: "var(--radius-lg)" },
      boxShadow: { button: "var(--shadow-button)" }
    }
  }
};

React Button 示例

import "./Button.css";

type ButtonProps = {
  children: React.ReactNode;
  onClick?: () => void;
  disabled?: boolean;
};

export function Button({ children, onClick, disabled = false }: ButtonProps) {
  return (
    <button className="Button" onClick={onClick} disabled={disabled}>
      {children}
    </button>
  );
}
.Button {
  background: var(--color-action-primary-bg);
  border: 0;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-button);
  color: var(--color-action-primary-text);
  cursor: pointer;
  font-size: var(--font-size-base);
  font-weight: var(--font-weight-bold);
  padding: var(--space-3) var(--space-4);
}

.Button:hover:not(:disabled) {
  background: var(--color-action-primary-bg-hover);
}

.Button:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}

.Button:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

真实使用场景与常见坑

第一个场景是 Figma 到代码交接。不要把 Figma 导出的名字直接当成最终答案,而是让 Claude Code 对比现有 tokens.json,列出新增、删除、重命名和影响到的组件。

第二个场景是暗色模式。不要复制整套组件 CSS,只覆盖 surfacetextaction 等语义 token。

第三个场景是品牌刷新或活动页改版。用 token 构建和截图审查,可以防止颜色、间距在不同页面慢慢漂移。

第四个场景是 PR 审查。Claude Code 可以检查组件是否直接使用 raw 颜色、生成的 CSS 是否被手改、focus 状态是否缺失、按钮文字是否满足 WCAG AA 4.5:1 对比度。

常见坑包括:一开始就创建过多 component token;用 blueButton 这类外观命名;手动编辑生成的 tokens.css;把对比度检查留到最后。更稳妥的做法是从小范围开始,先迁移 Button、Link、Card 三个组件。

团队落地时还要补一个流程约定:设计师提交 Figma 变更时,同时说明这是新增 token、替换 token,还是只调整现有 token 的值;工程侧由 Claude Code 先生成影响清单,再由人确认命名和品牌含义。这样可以避免“看起来只是换个蓝色”,实际却影响按钮、链接、焦点状态和暗色主题的情况。

Review checklist:

  • 只编辑 tokens/tokens.json,没有手动修改生成的 CSS。
  • Button、Link、Card 在 light、dark、hover、disabled、focus 状态下都检查过。
  • React 和 Tailwind 使用 semantic token,而不是 raw palette token。
  • PR 写清 Figma-like spec、use case、pitfall、risk 和 workflow。
  • 已验证文本与交互状态的 WCAG 2.2 AA 对比度。

Claude Code 审查提示词

Design token review task:
- Read tokens/tokens.json, style-dictionary.config.js, src/styles/tokens.css, tailwind.config.js, and src/components/Button.tsx.
- Check that components use semantic tokens, not raw color tokens.
- Verify light and dark theme values for button, surface, and text tokens.
- Flag any generated CSS file that was edited manually.
- Check WCAG 2.2 AA contrast for normal text and button text.
- Suggest the smallest safe diff. Do not rename tokens unless you list every affected component.
- After changes, run npm run tokens:build and the focused component tests.

总结

Design Tokens 把 Figma、CSS、Tailwind、React、无障碍和代码审查连接到同一套语言里。实际落地时,把 tokens.json 作为源头,用 Style Dictionary 生成 CSS 变量,在组件里只消费 semantic token,并让 Claude Code 在 PR 中检查漂移和对比度。

我按本文示例验证了从 token 文件生成 CSS 变量,并让 React Button 读取背景色、文字色、间距、圆角、阴影和焦点轮廓。需要可复用 prompts 和 checklists 时,可以查看 ClaudeCodeLab 产品。生产项目中建议再加入 Storybook 状态、axe 检查和截图审查;需要团队级导入时,可以查看 ClaudeCodeLab 培训与咨询

#Claude Code #design tokens #design system #CSS #UI design
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。