Matthew Huntsberry

Field guide

Field guide · 02

Name the part that won’t change.

A name is the only part of a token system anyone types. Values change, tiers get refactored, modes get added; the name is what everyone has already written into their code. There are 485 tokens on this page and they follow two different naming rules. Knowing which one applies is where teams get it wrong.

00

The bad name is the one that is right today

--gray-for-buttons is a perfectly accurate name the day it is written. Then a card wants the same grey. Now someone either uses a token that says “buttons” on a card, or adds a second token holding the identical value. The system gets bigger either way and no better.

Every name bakes in a guess about what stays put. Guess wrong and tooling will not dig you out, because by then the wrong word is in everyone else’s code.

01

Primitives are named after their value

167 tokens here state their own value in their name. The number is not a sequence position — it is the measurement:

name

--_palette-gray-11

hsl(0, 0%, 11%)

name

--_size-44

44px

name

--_duration-150

150ms

This is why a primitive can be renamed safely and almost never needs to be. --_size-44 is 44px in every theme, every brand, every density. The name cannot go stale because the thing it describes cannot change without becoming a different token.

One nuance worth stealing: --_type-size-18 is named in pixels and valued in rem. The name records the intent; the value honours the user’s text settings. Naming it --_type-size-1125 would have been accurate and useless.

02

Semantic tokens are named after their job

The other 184 name a role and resolve through something else. --space-md promises a medium gap, not twelve pixels. That is why density can re-point it and nobody has to go and correct the callers.

Walk the grammar

Every option below is a segment that exists. Pick one to see what the next position allows.

--incomplete

segment completes a token

The vocabularies split cleanly along the same line: 265 tokens end in a number and 72 end in a t-shirt step. Numbers where the value is absolute, steps where it is relative. Mixing them is how you end up with --space-16 that is no longer 16px.

03

Name the pairing, not just the colour

A foreground colour is meaningless without the surface it sits on, so the name carries it. There are 3 such pairs here:

on

--brand-on-solid

sits on brand-solid

on

--brand-on-tinted

sits on brand-tinted

on

--brand-accent-on-tinted

sits on brand-accent-tinted

You notice the value of this the first time someone adds a brand. They cannot hand over a solid colour without the naming scheme asking what text sits on it. Contrast gets decided at that moment instead of in an audit six months later.

04

States are a suffix, not a token family

-hover (4), -active (3), -disabled (1). That is the whole state vocabulary — a handful of suffixes on tokens that already exist, rather than a parallel set of names.

The alternative, a --button-hover-background for every component, multiplies with the component count and drifts the moment one of them is updated alone. Derivation beats enumeration: hover states here are computed from the base role, so a new brand gets them for free.

05

Length is a signal, not a style choice

Names here run two to four segments — 115 use four, and only 3 use five. That ceiling is not a rule anyone enforced; it is what happens when each segment has a job and none is decoration.

2 parts

▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊

184

3 parts

▊▊▊▊▊▊▊▊▊▊▊▊▊▊▊

177

4 parts

▊▊▊▊▊▊▊▊▊▊

115

5 parts

3

When a name needs a fifth segment, it is usually encoding something that belongs in a mode. A token called --brand-solid-hover-dark-dense is four dimensions pretending to be a name.

06

The test

Read the name and say what would have to be true for it to change.

If the answer is a fact about the world — --_size-44 changes when 44 stops being 44 — it is a primitive and the name is safe.

If the answer is a design decision — --surface-1 changes when the page’s background should be different — it is semantic, and the name is right precisely because it says nothing about the value.

If you cannot answer at all, the name is doing two jobs. --gray-for-buttons changes when the grey changes or when buttons change, which is why it will eventually be wrong about one of them.

07

Where this comes from

None of the above is original. The tier split and the vocabulary for talking about it come from Nathan Curtis, whose Naming Tokens in Design Systems is still the piece that gets handed to every team starting out — the base/applied distinction, the argument for namespaces, the case against encoding component names into values.

The structural half — Brad Frost’s Atomic Design — is why the component vocabulary here has levels at all, and why the smallest tier stays small.

What changes per engagement is the fit. A team shipping one product on one framework does not need six mode dimensions; a team with four brands and a legacy CMS needs the on- convention on day one, not in year two. The grammar is inherited; which parts of it earn their keep is the actual work — and getting that judgement wrong is how a system ends up with a beautiful naming document nobody follows.