Design tokens die at the third layer
Primitive, semantic, component. The third one is where systems quietly become unmaintainable.
Contents
The three-layer token model is right: primitives (--blue-600), semantics (--color-action), components (--button-primary-bg). Everyone draws that diagram. What nobody mentions is that the third layer grows without limit, and after eighteen months you have 900 component tokens, 60% of which are aliases that were never overridden by anything.
The check we added
A build step that walks the compiled CSS and reports every component token whose value is identical to the semantic token it references, in every theme. Those are not tokens. They are indirection with a changelog. We deleted 340 of them in one PR and nothing changed visually, which was exactly the point.
Earn the third layer
A component token is justified when at least one of these is true:
- Some theme genuinely overrides it (our high-contrast theme overrides eleven).
- The component is themeable by a consumer as a documented, supported API.
- The value is a computed relationship, not a copy — a border colour derived from the surface it sits on.
Otherwise the component consumes the semantic token directly. background: var(--color-action) in Button.css is not a layering violation. It is a button using the action colour, which is what the semantic layer is for.
Naming is the actual system
We renamed --color-primary to --color-action and support tickets about "which primary" stopped within a month. Primary describes importance, which is subjective and therefore arguable. Action describes a role, and a role can be checked: is this thing something you click? Then it is action. Done.
If your token names require a decision, they will be used inconsistently. Every time.
Written by
Lena Fischer
Front-end engineer on a design systems team. I maintain the token pipeline and the component library four product teams build on. Strong opinions about focus rings, colour contrast, and the fact that most "theming" problems are really naming problems. CSS is a real language and I will keep saying so.
3 Comments
Sign in to join the discussion
The build step that flags a component token identical to its semantic token in every theme — is that published anywhere? We would run it tomorrow.