consolelog.tools

Design Token Generator

Pick a few brand colours and the tool builds a complete, production-ready token system: real perceptual 50→950 ramps (not a hard-coded scale), a shadcn-style semantic layer with matching light + dark themes, and a live component preview so you SEE the system before you ship it. Every text/background pair is checked against WCAG contrast, and you can export to CSS variables, Tailwind v4 @theme, Tailwind v3, SCSS, JS/TS, the W3C DTCG format, or Style Dictionary.

About this ToolHow it works, benefits & use cases

Most token generators dump a flat list of CSS variables. This one builds a real two-layer system. Pick a primary, accent, and neutral colour (plus success/warning/error) and it derives a perceptual 50→950 ramp for each — the lightness follows a contrast-friendly curve and saturation eases at the extremes, so the scale is actually derived from your colour instead of hard-coded. On top of the primitives it builds a shadcn/ui-style semantic layer — background, foreground, card, primary, secondary, muted, accent, destructive, border, input, ring — with matching light and dark values, so a component referencing --primary flips themes without touching markup. A live preview renders a real card, buttons, and input in both themes, and every text/background pair is checked against WCAG contrast as you edit. Export to CSS variables, Tailwind v4 @theme, Tailwind v3 config, SCSS, a JS or TypeScript token object, the W3C DTCG format, or Style Dictionary. The whole configuration lives in a shareable URL.

How to Use

  1. 1Start from a preset palette or set your primary, accent, and neutral colours with the colour pickers.
  2. 2Adjust the base radius and spacing unit, and set your sans/mono font stacks.
  3. 3Toggle the live preview between light and dark to see your semantic tokens on a real card and buttons.
  4. 4Read the contrast audit — it flags any text/background pair below the 4.5:1 WCAG AA threshold.
  5. 5Pick an export format and copy or download the tokens; share the URL to hand the exact system to a teammate.

Key Benefits

  • Perceptual 50→950 ramps actually derived from your colour, not a fixed hard-coded scale
  • Two-layer system: primitive ramps plus a shadcn-style semantic layer with light + dark themes
  • Live component preview (card, buttons, input) in both light and dark
  • WCAG contrast audit on every text/background pair, computed as you edit
  • Eight export formats including Tailwind v4 @theme, W3C DTCG, and Style Dictionary
  • Adjustable radius, spacing unit, and font stacks
  • Shareable URL captures the full token configuration

Common Use Cases

  • Bootstrapping a complete token foundation (primitives + semantic + dark) for a new design system
  • Generating a shadcn/ui-compatible :root and .dark block from your brand colours
  • Exporting a Tailwind v4 @theme or Tailwind v3 config that maps semantic tokens to CSS vars
  • Producing a W3C DTCG tokens.json or Style Dictionary source for a token pipeline
  • Validating that a dark theme’s muted text actually passes WCAG contrast before shipping

Live preview

Account settingsPro

Manage how your workspace looks and behaves across devices.

1 pair fail WCAG AA in light
  • Body text on background14.52AAA
  • Card text on card14.52AAA
  • Muted text on background3.51AA Large
  • Primary button label5.50AA
  • Accent button label8.29AAA
  • Destructive button label4.95AA
  • Secondary button label9.28AAA

CSS variables · light + dark

:root {
  /* Primitive colour ramps */
  --color-primary-50: #f5f8fc;
  --color-primary-100: #e7effb;
  --color-primary-200: #c6d9f9;
  --color-primary-300: #92b8f7;
  --color-primary-400: #4f8ff7;
  --color-primary-500: #2473f5;
  --color-primary-600: #0b5fe8;
  --color-primary-700: #0b4fbf;
  --color-primary-800: #0d4196;
  --color-primary-900: #0e3574;
  --color-primary-950: #0b2349;
  --color-accent-50: #f7f5fc;
  --color-accent-100: #ede8fa;
  --color-accent-200: #d5c6f8;
  --color-accent-300: #b192f6;
  --color-accent-400: #8351f5;
  --color-accent-500: #6426f3;
  --color-accent-600: #4f0de6;
  --color-accent-700: #420cbd;
  --color-accent-800: #370e95;
  --color-accent-900: #2e0f73;
  --color-accent-950: #1e0c48;
  --color-neutral-50: #f8f8f9;
  --color-neutral-100: #f1f1f1;
  --color-neutral-200: #dedee0;
  --color-neutral-300: #c2c2c6;
  --color-neutral-400: #a0a0a7;
  --color-neutral-500: #888891;
  --color-neutral-600: #74747e;
  --color-neutral-700: #616169;
  --color-neutral-800: #4f4f54;
  --color-neutral-900: #3f3f43;
  --color-neutral-950: #29292b;
  --color-success-50: #f6fbf8;
  --color-success-100: #eaf8ef;
  --color-success-200: #cbf3da;
  --color-success-300: #9decba;
  --color-success-400: #62e492;
  --color-success-500: #3bdd77;
  --color-success-600: #24cf63;
  --color-success-700: #1faa52;
  --color-success-800: #1d8744;
  --color-success-900: #1a6837;
  --color-success-950: #124224;
  --color-warning-50: #fcfaf5;
  --color-warning-100: #fbf3e7;
  --color-warning-200: #f9e6c5;
  --color-warning-300: #f8d291;
  --color-warning-400: #f8b94f;
  --color-warning-500: #f6a723;
  --color-warning-600: #e9960a;
  --color-warning-700: #c07c0a;
  --color-warning-800: #97630c;
  --color-warning-900: #754e0e;
  --color-warning-950: #49320b;
  --color-error-50: #fcf5f5;
  --color-error-100: #fae8e8;
  --color-error-200: #f7c7c7;
  --color-error-300: #f39595;
  --color-error-400: #f15656;
  --color-error-500: #ed2c2c;
  --color-error-600: #df1313;
  --color-error-700: #b81212;
  --color-error-800: #911212;
  --color-error-900: #701212;
  --color-error-950: #460e0e;

  /* Radius, spacing, type */
  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 8px;
  --radius-xl: 12px;
  --radius-2xl: 16px;
  --radius-full: 9999px;
  --spacing-0: 0px;
  --spacing-1: 4px;
  --spacing-2: 8px;
  --spacing-3: 12px;
  --spacing-4: 16px;
  --spacing-6: 24px;
  --spacing-8: 32px;
  --spacing-12: 48px;
  --spacing-16: 64px;
  --spacing-24: 96px;
  --font-sans: Inter, ui-sans-serif, system-ui, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* Semantic tokens (light) */
  --background: #ffffff;
  --foreground: #29292b;
  --card: #ffffff;
  --card-foreground: #29292b;
  --popover: #ffffff;
  --popover-foreground: #29292b;
  --primary: #0b5fe8;
  --primary-foreground: #ffffff;
  --secondary: #f1f1f1;
  --secondary-foreground: #3f3f43;
  --muted: #f1f1f1;
  --muted-foreground: #888891;
  --accent: #4f0de6;
  --accent-foreground: #ffffff;
  --destructive: #df1313;
  --destructive-foreground: #ffffff;
  --border: #dedee0;
  --input: #dedee0;
  --ring: #2473f5;
}

.dark {
  /* Semantic tokens (dark) */
  --background: #29292b;
  --foreground: #f8f8f9;
  --card: #3f3f43;
  --card-foreground: #f8f8f9;
  --popover: #3f3f43;
  --popover-foreground: #f8f8f9;
  --primary: #2473f5;
  --primary-foreground: #29292b;
  --secondary: #4f4f54;
  --secondary-foreground: #f8f8f9;
  --muted: #4f4f54;
  --muted-foreground: #a0a0a7;
  --accent: #6426f3;
  --accent-foreground: #29292b;
  --destructive: #ed2c2c;
  --destructive-foreground: #f8f8f9;
  --border: #4f4f54;
  --input: #4f4f54;
  --ring: #4f8ff7;
}

Start from a palette

Colours

Primary
Accent
Neutral
Success
Warning
Error

Shape & type

px
px

Adds a .dark semantic layer (and prefers-color-scheme block in Tailwind v4).

Export format

Tokens, not a colour dump

A design token system has two layers. Primitives are the raw scale — primary-500, neutral-200. Semantic tokens (background, foreground, primary, border) give those values meaning and are what your components actually reference, so a single token can flip between light and dark without touching markup.

Why the contrast check matters

A dark theme that looks fine can still fail WCAG — muted grey text on a dark surface is the usual culprit. The preview audits every text/background pair against the 4.5:1 AA threshold so you catch it here, not in an accessibility report later.

Was this tool helpful?

Share Your Experience

Help others discover this tool!

Related tools