Use Cases (Atualizado: 03/06/2026)

Design Tokens com Claude Code: do Figma a variáveis CSS, Tailwind e React

Implemente design tokens com Claude Code, Style Dictionary, variáveis CSS, Tailwind e React.

Design Tokens com Claude Code: do Figma a variáveis CSS, Tailwind e React

Design tokens são um contrato para mudar a UI

Design tokens guardam decisões de design como dados nomeados: cores, espaçamento, tipografia, raios, sombras e estados. Em vez de espalhar #2563eb, 16px e 0.5rem por vários componentes, você mantém a fonte da verdade em tokens.json e gera variáveis CSS, configuração do Tailwind e valores consumidos por React.

Claude Code funciona bem nesse fluxo porque o trabalho é revisável. Ele pode ler o CSS atual, encontrar valores hardcoded, sugerir nomes semânticos, atualizar componentes, rodar o build e resumir o diff. O pedido “deixe a UI consistente” é amplo demais. Um pedido melhor define o arquivo de tokens, os componentes no escopo, as regras de contraste e os comandos que precisam passar.

Para continuar, veja design system com Claude Code e acessibilidade com Claude Code. Use como referência oficial o Design Tokens Format Module 2025.10, Claude Code docs, Figma Variables plugin API, Tailwind theme docs, a documentação do Style Dictionary, MDN CSS custom properties e WCAG sobre contraste.

Raw tokens e semantic tokens

Raw tokens descrevem a matéria-prima: color.blue.600, space.4, font.size.base. Semantic tokens descrevem a intenção: color.action.primary.bg, color.text.muted, color.surface.default. Component tokens descrevem regras locais, como button.primary.paddingX.

TipoExemploUso
Rawcolor.blue.600Paletas, escalas de espaço e tipografia
Semanticcolor.action.primary.bgSentido de produto, temas e dark mode
Componentbutton.primary.paddingXExceções estáveis de componentes

Comece com raw e semantic. Se um botão usa color.blue.600 diretamente, uma mudança de marca pode deixar nomes errados. Se ele usa color.action.primary.bg, o valor muda sem perder o significado.

Transformar uma Figma-like spec em contrato de código

Figma Variables ajudam, mas Claude Code deve receber um handoff revisável, não um export bruto de nomes. Uma Figma-like spec declara arquivo de origem, modos, mudança pedida, componentes afetados e regras de review. Isso reduz o risk de copiar Blue / 600 para React quando o produto precisa de color.action.primary.bg.

{
  "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."
  ]
}

Peça primeiro uma tabela de impacto e só depois autorize edição. Esse workflow evita um pitfall comum: um token pode mexer ao mesmo tempo em Button, Link, Card e focus outline.

tokens.json executável

Salve como 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)" }
  }
}

Gerar CSS com Style Dictionary

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" }]
    }
  }
};

Script:

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

Saída esperada:

: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;
}

Tailwind e React Button

/** @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)" }
    }
  }
};
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;
}

Casos de uso, armadilhas e revisão

Três casos aparecem com frequência. No handoff do Figma para código, Claude Code compara o export com tokens.json e lista valores adicionados, removidos, renomeados e componentes afetados. No dark mode, você sobrescreve tokens semânticos como surface, text e action, sem duplicar CSS. Em rebranding ou landing pages, o build de tokens e screenshots no Storybook evitam drift visual.

Armadilhas concretas: criar muitos component tokens no primeiro dia, nomear pela aparência (blueButton) em vez da intenção (primaryAction), editar manualmente o tokens.css gerado e deixar contraste para o fim. Para texto normal, WCAG AA exige pelo menos 4.5:1.

Review checklist:

  • tokens/tokens.json é a única fonte editada; o CSS gerado não foi alterado manualmente.
  • Button, Link e Card foram revisados em light, dark, hover, disabled e focus.
  • React e Tailwind consomem semantic tokens, não raw palette tokens.
  • O PR explica Figma-like spec, use case, pitfall, risk e workflow.
  • O contraste WCAG 2.2 AA foi validado para texto e estados interativos.
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.

Fechamento

O fluxo prático é manter tokens.json, gerar variáveis CSS com Style Dictionary, mapear no Tailwind, consumir semantic tokens nos componentes e revisar drift e contraste em cada PR. Testei o caminho do exemplo gerando CSS variables e conectando um Button React a cor, espaçamento, radius, shadow e focus outline. Para prompts e checklists reutilizáveis, veja produtos ClaudeCodeLab. Em produção, acrescente Storybook, axe e revisão visual; para adoção em equipe, veja treinamento e consultoria ClaudeCodeLab.

#Claude Code #design tokens #design system #CSS #UI design
Grátis

PDF grátis: cheatsheet do Claude Code

Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.

Cuidamos dos seus dados e não enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro focado em workflows práticos com Claude Code.