Field Notes /Design · 8 min read

Naming is half the system

A short essay on why color.brand.500 beats colorBrand500, why we don't use semantic-only systems, and how the right name disappears.

Naming is half the system. essay · 8 min
Field Notes № 08 · Essay

There is a running joke in design-system circles that the hardest problems are naming and cache invalidation — borrowed, of course, from programming. I've stopped laughing at it. In five years of design-system work, naming has caused more rework, more cross-team friction, and more silent system failures than any other single decision. And it's usually treated as an afterthought.

What a name actually does

A token name does three things at once. It locates the value in the system hierarchy. It communicates intent to the person reaching for it. And it survives refactoring — or it doesn't, which is a catastrophic failure mode that only reveals itself months after the token was named.

Most token names do the first two reasonably well and fail completely at the third. A name like color.yellow.500 locates the value (color, yellow family, 500 stop) and communicates something about its appearance. But the moment your brand moves from yellow to orange, the name is a lie. Every engineer who reads that token in source code now has incorrect information about what they're applying.

A token name that describes appearance is a token name with an expiration date.— Naming review, February 2026

The case against description

Descriptive names feel intuitive because they match how designers talk: "use the warm yellow," "put the dark navy there," "the light gray background." This is fine for verbal communication and fatal for token catalogs. Verbal descriptions are for moments. Token names are for years.

Consider color.warm-orange vs. color.brand.500. The first name tells you what the color looks like right now. The second tells you where it lives in the system. When the brand changes to teal, color.brand.500 still makes sense — it's the 500 stop of the brand scale, whatever color that happens to be. color.warm-orange is now a lie embedded in a thousand component files.

  • Avoid: color names (color.blue, color.warm-yellow)
  • Avoid: size descriptions (space.large, space.small) — large relative to what?
  • Avoid: emotion words (color.danger-red) — "danger" is semantic and fine, "red" is descriptive and dangerous
  • Prefer: positional names (color.brand.500, space.8)
  • Prefer: role names (color.surface.base, color.text.muted)
  • Prefer: relationship names (space.gap.md, radius.card)
TOKEN NAMING · category.variant.modifier colorcategory . brandvariant . 500modifier color.brand.500 → resolves to portica.500 → #F7F9B2 color.surface.elevated
Fig. 01Token name taxonomy — the UISqueezy three-part naming convention.

Semantic vs. component scope

One of the recurring debates in naming is whether to use semantic scope (color.text.primary) or component scope (color.button.label). Both are valid approaches. They serve different needs.

Semantic names travel. color.text.primary can be consumed by a button label, a card heading, a form input — any element that needs primary text color. Component names don't travel: color.button.label is only legible in a button context. Using it in a card feels wrong, so engineers reach for raw hex instead.

We recommend semantics for the mid-layer (between primitives and components) and component names only for genuine exceptions — cases where a specific component has a color that is truly not reusable. In our experience, these genuine exceptions account for less than 10% of tokens. The other 90% are semantic.

The disappearing name

The best token name is the one you never have to think about.

When a naming system is working, engineers stop thinking about token names as decisions. They reach for color.surface.elevated the way they reach for a scalpel — it's in the right place, it's the right thing, there is no deliberation. The name disappears into the action.

This state is hard to achieve and easy to lose. It requires that every token in the catalog follows the same naming convention, without exceptions. One outlier — one colorBrandPrimary in camelCase among hundreds of dot-separated names — breaks the muscle memory. The engineer has to think again. The name is no longer invisible.

A naming starter

UISqueezy ships a default naming convention that follows a category.variant.modifier pattern. It is not the only correct convention — but it is internally consistent, and consistency is more important than perfection.

  • color.{scale}.{stop} → primitives (color.portica.500)
  • color.{role}.{variant} → semantics (color.surface.elevated)
  • space.{step} → primitives (space.4, space.8)
  • space.{role}.{size} → semantics (space.gap.md)
  • radius.{component} → component tokens (radius.card, radius.button)
  • type.{ramp}.{step} → typography (type.display.xl, type.body.md)

Start here. Deviate deliberately. Document every deviation. The goal is not to follow our convention — it's to have a convention that everyone on your team can apply without asking.

NAMING CONVENTION · full pattern color.{scale}.{stop}color.portica.500color.{role}.{variant}color.surface.elevatedspace.{step}space.8radius.{component}radius.cardtype.{ramp}.{step}type.display.xlz.{step}z.400
Fig. 02Naming convention cheat sheet — the full UISqueezy pattern at a glance.
OP
Onur Pamuk
Co-founder & head of design at UISqueezy. Has renamed the same token four times and is not proud of it.