Updated July 10, 2026

Naming Color Tokens: brand-600 vs blue-600

Two token files meet the same rebrand. In the first, the palette was named by hue — blue-600 referenced across hundreds of files. The brand turns teal, and every option is bad: keep the name and blue-600 now stores a teal, lying to every future reader; rename it and touch every reference in the codebase. In the second file the same color was named brand-600. The rebrand is one edit — the value changes, the name keeps telling the truth, nothing downstream moves.

Color token naming works in layers — up to three. The primitive layer names a color’s place in the palette (brand-600); the semantic layer names UI jobs (background, text-primary, accent) and points at primitives; the optional component layer (button-bg) exists only where a component genuinely needs to detach from the semantics. At the primitive level, brand-600 beats blue-600 for a single-brand palette because it names the role a color plays, not the hue it happens to have — though hue names remain a defensible choice for multi-hue raw palettes. What the number itself means — the scale position behind the 600 — is covered in our color scales guide; this article is about the words in front of it.

Should primitives be named brand-600 or blue-600?

Both positions deserve their honest case.

The case for brand-600: a primitive’s stable fact is its position in this product’s palette, not its wavelength. The palette has a main hue, a set of neutrals, perhaps a secondary — those are roles, and they survive every event in the palette’s life. Hue is the volatile property: rebrands change it, and the opening scenario is what the name blue-600 costs when it does. Nobody consuming a single-brand palette ever needed to know the brand color is blue; they needed to know it is the brand color. The Scale Composer’s palette groups are named on exactly this principle — Brand, Secondaries, Neutral, Functional — roles first, hues nowhere.

The case for blue-600: in a multi-hue system there may be no role to name. A raw palette that ships twenty hues as general-purpose material — Tailwind’s position — has no “brand” among them; hue is the only honest name such a palette can offer, and blue-600 is exactly right there. The same logic covers categorical chart sets, where six hues are peers with no hierarchy to encode.

The rule of thumb falls out cleanly: if the palette belongs to one brand, name primitives by role; if it is a crayon box serving many masters, name them by hue. Most product design systems are the first kind and inherit the second kind’s names by copying a framework’s conventions — which is how blue-600 ends up lying after a rebrand nobody planned for.

What does the semantic layer add?

Indirection with meaning. Semantic tokens name jobs — background, surface, border, text-primary, text-secondary, accent, the interactive state colors — and each one points at a primitive. Components consume semantic tokens and never touch primitives directly.

The payoff is that meaning and value become independently changeable. A component written against text-primary works on any theme, because the name promises a job, not a value; a component written against brand-900 has hard-coded an assumption about which step happens to do that job today. The layer is also where accessibility lives naturally: a job like “primary text on this surface” carries a contrast requirement, so the token that names the job is the right place to enforce it. Scale Composer derives roughly seventeen semantic roles per surface this way — each role pointing at a scale step, checked against WCAG floors (4.5:1 for body text, 7:1 for the stricter level) with APCA shown alongside. Material Design’s token system documents the same layered architecture — reference, system and component tokens in their design tokens overview — under different layer names.

See the layers on a real palette in Scale Composer — the primitive ramps grouped by role, the semantic roles of one surface pointing into them, and the export panel carrying both layers out as DTCG, CSS, Tailwind or Figma Variables.

A palette in Scale Composer showing primitive ramps grouped as Brand, Secondaries, Neutral and Functional, with a surface's semantic roles pointing at specific steps

When does a component layer earn its place?

Rarely — and that is the layer’s design, not its weakness. A component token like button-bg is justified when a component must detach from the semantic layer: the marketing site re-points accent to a secondary hue, but the primary button must stay on the brand color — so button-bg stops following accent and pins itself to the brand primitive. That is a real decoupling, and the token records it.

Without such a divergence, a component token is indirection without meaning: button-bgaccentbrand-600, three names for one value that never varies independently. Multiplied across a component library, this produces the token sets nobody can navigate. A reasonable default: introduce the component token when the exception appears, not in advance of it.

What do the layers buy you when things change?

Three scenarios, with the blue seed #2563eboklch(0.546 0.215 262.9) — standing in for the brand.

Rebrand. The palette re-derives from a teal seed. Primitives keep their names and swap values — brand-600 no longer stores ≈#3E65B5, but it is still the brand ramp’s 600. The semantic layer, pointing at names rather than values, does not change at all. Components notice nothing.

Dark mode. Semantic names keep their meaning while their targets move: accent points at brand-600 (≈#3E65B5) on the light theme and at a lighter step like brand-300 (≈#71AEFF) on the dark one, where a dark background demands a lighter accent for contrast. The values even come from different ramps — a derived dark palette is generated with its own lightness curve and a chroma boost of roughly 20 % — yet a component still just says accent.

One primitive, several jobs. The same brand-600 can serve as accent text on one surface and as the resting button fill on another. One stored value, several meanings — and the meanings live in the semantic layer, which is the whole reason it exists. Collapse the layers and every one of these changes becomes a find-and-replace across components.

Naming is also the part of a token system that outlives the tool that made it: the names chosen here are what every export carries into code and design files, with hex alongside the OKLCH. And the migration path runs in both directions. Import your existing token file and rename a layer — load a DTCG file, rename hue-named primitives to role names, and re-export; the round-trip preserves the sections you didn’t touch, so a naming cleanup costs exactly the tokens it renames.

Keep reading

  • Why Color Steps Are Named 50–900

    Color scale numbers explained: where 50–900 came from, why numbers beat names like light and lighter, and why a 500 is a position, not a measurement.

  • What Is a Color Ramp (Color Scale)?

    What a color ramp is — one hue at ten ordered lightness steps — plus the anatomy: which steps do which UI jobs, and why ramps beat swatch-picking.