Section 2 · Design Tokens
Naming Tokens So They Survive
18 min3 min readChoose wisely
Lesson at a glance
Name design tokens with a written grammar of category, concept, property, variant and state, so names stay true through dark mode, new brands and years of growth.
- 1A grammar, not a list
- 2Name the purpose, not the look
- 3Scales: numbers or sizes
- 4Enforce the grammar
- 5Renaming without breaking people
No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.
In Northwind’s old token file there was a token called --color-blue-new. Two years later there was also --color-blue-new-2 and --color-blue-newer. Nobody knew which was the brand blue. Naming is the part of a design system that looks like bikeshedding and turns out to be architecture: names are the API every designer and engineer types hundreds of times a week.
A grammar, not a list
Good token names come from a grammar: a fixed set of parts in a fixed order. Northwind’s semantic tokens follow this one:
--nw-{category}-{concept}-{property}-{variant}-{state}
--nw-color-action-bg category=color concept=action property=bg
--nw-color-action-bg-hover … state=hover
--nw-color-danger-text concept=danger property=text
--nw-color-text-subtle concept=text variant=subtle
--nw-space-inset-md category=space concept=inset variant=md
--nw-radius-control category=radius concept=controlNot every token uses every part, but the parts that appear always appear in that order. That buys you two things. People can guess names they’ve never seen: if --nw-color-action-bg-hover exists, --nw-color-danger-bg-hover probably does too. And sorted alphabetically, related tokens cluster together in every editor and in Figma’s variable panel.
The nw prefix is a namespace. It stops collisions with third-party CSS and makes system tokens easy to search for, which you’ll use for adoption metrics later.
Name the purpose, not the look
At the primitive tier, naming the look is correct: --nw-blue-600 is a blue. At the semantic tier, the look is exactly what themes change, so names must describe purpose.
| Fragile name | Why it breaks | Durable name |
|---|---|---|
--nw-color-red-bg |
Tidewater’s error color is orange | --nw-color-danger-bg |
--nw-color-text-light |
In dark mode it is not light | --nw-color-text-subtle |
--nw-color-header-bg |
Named after its first user | --nw-color-surface-inverse |
--nw-color-text-2 |
Says nothing | --nw-color-text-muted |
Scales: numbers or sizes
Primitive scales need a naming scheme too. There are two common choices:
- Numeric, like
100to900for color lightness or1to12for spacing steps. You can insert150later without renaming anything. The numbers carry little meaning on their own. - T-shirt sizes, like
xs,sm,md,lg,xl. Easy to read in code review. When designers need a step betweensmandmd, you are stuck with names likesm-plus.
Northwind uses numeric scales for primitives and t-shirt sizes for the handful of semantic spacing tokens (--nw-space-inset-sm, -md, -lg), because designers think in sizes and that set rarely grows. Pick one scheme per scale and stick to it. Mixing them inside one scale, such as --nw-space-2, --nw-space-md and --nw-space-24px, is the fastest way to make a scale nobody trusts, because people can no longer tell which values are siblings.
Enforce the grammar
A grammar that lives only in a wiki page lasts until the first busy contributor. Turn it into a check that runs in CI:
const grammar = /^--nw-(color|space|radius|font|shadow|motion)(-[a-z]+)+(-[0-9]+)?$/;
const banned = /-(red|blue|green|light|dark|new|old|[0-9]+px)(-|$)/;
const proposed = [
'--nw-color-action-bg-hover',
'--nw-color-text-light',
'--nw-color-blue-new',
'--nw-space-inset-md',
'--nwColorDangerText',
'--nw-color-danger-text',
];
for (const name of proposed) {
const ok = grammar.test(name) && !banned.test(name);
console.log(ok ? 'ok ' : 'reject', name);
}The banned list catches the habits that break first: color words, “light” and “dark”, “new” and “old”, and raw pixel values. Run it against every token file in pull requests, and print the rule that failed so contributors learn the grammar from the error instead of from a wiki page. It’s a blunt tool, and it will occasionally reject a good name. That’s fine; a contributor who hits it asks the core team, and the conversation is the point.
Renaming without breaking people
You will get some names wrong; everybody does. When you rename a token, keep the old name as an alias of the new one for at least one release, mark it deprecated, and announce it in the changelog. Section 4 covers the full deprecation path. In the exercise below, you review a batch of proposed names the way the Northwind core team does every week. Next, you put the semantic tier to work: one set of components, several themes.
Key takeaways
- Semantic token names describe purpose (
danger,subtle), never appearance (red,light), because appearance changes with themes. - A fixed order of name parts, such as category-concept-property-variant-state, makes tokens predictable to guess and easy to sort.
- Numeric scales like 100 to 900 leave room to insert values later; t-shirt sizes read better but fill up.
- Write the naming grammar down and enforce it with a lint rule, or every contributor invents their own.