Skip to content
Browse all prompts
design-token-system.md Markdown · 50 lines Raw
This project has accumulated colour and spacing values one commit at a time. Turn them into a token system. The visible design should not change — this is a refactor, and a screenshot before and after should be nearly identical.

## 1. Inventory first, decide later

Go through the stylesheets and components and collect every hard-coded value: colours in any notation, font sizes, spacing, radii, shadows, transition durations. Group them by what they were trying to be, not by their value — `#1a1a1a`, `#181818` and `rgb(26,26,26)` are three attempts at one colour.

Show me the inventory before you change anything, with a count per group. That count is the argument: seven near-identical greys is the finding.

## 2. Name them for their job

A token is named for what it does, not what it looks like. `--color-surface`, not `--color-white`; `--color-ink-muted`, not `--color-gray-500`. The site will get a dark mode one day and `--color-white: black` is where that goes wrong.

Keep the palette small — but extraction and consolidation are two steps, and this is the first one. Give every distinct value its own token even when two are nearly identical, then hand me a separate list of the merges you would make, with the callers each one touches. Two values being close is not proof they mean the same thing: a body colour and a border colour that happen to match today may need to diverge in dark mode, and merging two text colours can cross a contrast threshold. I decide the merges; you do not apply them in this pass.

## 3. Declare them in `@theme`

Tailwind 4 has no config file. Tokens live in the CSS entry:

```css
@import 'tailwindcss';

@theme {
	--color-surface: oklch(0.99 0.003 265);
	--color-ink: oklch(0.21 0.02 265);
	--color-ink-muted: oklch(0.52 0.02 265);
	--color-accent: oklch(0.62 0.18 265);

	--radius-control: 0.5rem;
}
```

Use `oklch()` for colour. It makes "the same hue, a bit lighter" a change to one number, which is the whole reason to have tokens.

Anything a consumer is meant to override goes through a public custom property with a private fallback, so overriding it does not require editing the component:

```css
.thing {
	background: var(--component-thing-bg, var(--_thing-bg));
}
```

## 4. Migrate the callers

Replace the hard-coded values with the tokens, one group at a time. Every class name must appear complete somewhere Tailwind scans: `bg-surface` is fine, and so is picking between two complete class names with a conditional or a lookup map. What does not work is assembling one from fragments — `` `bg-${tone}` `` — because the finished name never appears in the source for the scanner to find.

## 5. Prove nothing moved

Screenshot the main pages before and after and diff them. This pass preserves values, so the diff should be empty. Any pixel that moved is a mistake, not a consolidation — the merges are still a proposal at this point.

Finish by telling me: how many distinct values you found, how many tokens you ended up with, the merges you are proposing and what each would change, and anything you left hard-coded on purpose.