Design Token Naming: 7 Systems Compared

How Polaris, Carbon, Primer, Material Design, Lightning, Spectrum, and Fluent name their tokens. Side-by-side comparison with patterns, examples, and what to steal for your system.

Before you start
  • Basic understanding of design tokens
Naming philosophy triangle
Naming system Token Name how you encode meaning
  • Pattern 01 Option Property-first color.background.primary
  • Pattern 02 Option Role-first primary.background.color
  • Pattern 03 Option Semantic action.default, surface.raised

Every design system names tokens differently. There is no universal standard. But after studying how the top systems do it, clear patterns emerge.

This guide compares 7 major design systems and gives you a framework to pick the right approach for your team.

For hands-on naming tools, see namedesigntokens.guide

The 7 systems at a glance

Seven naming systems compared
Criterion Polaris Shopify Carbon IBM Primer GitHub Material 3 Google Lightning Salesforce Spectrum Adobe Fluent 2 Microsoft
Token count 300+ 500+ 200+ 100+ 400+ 600+ 300+
Prefix --p- $ / --cds- --color- / --primer- --md-sys- --slds-g- --spectrum- none
Format kebab-case kebab + Sass kebab-case kebab-case kebab-case kebab-case camelCase
Pattern property-first property-first semantic system-spec numeric scale property-first role-first
Spacing scale 100–800 01–13 named 8px grid 1–9 100–600 S/M/L

Naming patterns side by side

Color tokens

SystemBackgroundTextBorder
Polaris--p-color-bg-fill-brand--p-color-text-brand--p-color-border-brand
Carbon$background-brand$text-primary$border-strong-01
Primer--color-accent-subtle--color-accent-fg--color-accent-emphasis
Material--md-sys-color-primary-container--md-sys-color-on-primary--md-sys-color-outline
Lightning--slds-g-color-brand-base-50--slds-g-color-neutral-base-100--slds-g-color-border-base-1
Spectrum--spectrum-accent-background-color-default--spectrum-neutral-content-color-default--spectrum-gray-border-color-default
FluentcolorBrandBackgroundcolorNeutralForeground1colorNeutralStroke1

Spacing tokens

SystemSmallMediumLarge
Polaris--p-space-200 (8px)--p-space-400 (16px)--p-space-800 (32px)
Carbon$spacing-03 (8px)$spacing-05 (16px)$spacing-07 (32px)
Primer--primer-spacing-normal--primer-spacing-spacious-
MaterialHardcoded 8px grid--
Lightning--slds-g-spacing-3--slds-g-spacing-5--slds-g-spacing-7
Spectrum--spectrum-spacing-200--spectrum-spacing-400--spectrum-spacing-600
FluentspacingHorizontalSspacingHorizontalMspacingHorizontalL

Three naming philosophies

1. Property-first (Polaris, Spectrum)

--{prefix}-{category}-{property}-{variant}
--p-color-bg-fill-brand
--spectrum-accent-background-color-default

The token name describes what it does. Background, text, border. Then what kind. Brand, subtle, emphasis.

Pros: Self-documenting. Easy to find what you need. Cons: Long names. Category boundaries can blur.

2. Role-first (Carbon, Lightning)

--{prefix}-{role}-{modifier}
$background-brand
--slds-g-color-brand-base-50

The token name describes its role in the system. Background, primary, brand. Numbers indicate scale position.

Pros: Clean, short names. Clear hierarchy. Cons: Requires knowing the system’s role definitions.

3. Semantic-abstract (Material, Fluent)

--md-sys-color-{semantic-role}
colorBrandBackground

The token name is an abstraction. “Primary” means nothing about color. It means “the most important thing.” The system decides what color that maps to.

Pros: Theme-agnostic. Easy to swap entire palettes. Cons: Harder to debug. “What color is primary again?”

Token layers compared

Every mature system has at least 3 layers:

Primitive          →  Semantic         →  Component
blue-500              color-bg-brand       button-bg-primary
SystemPrimitivesSemanticComponent
PolarisNot exposed--p-color-bg-fill-*Not exposed
Carbon$blue-60$background-brand$button-primary
Primer--base-color-scale-blue-5--color-accent-fgLimited
Material--md-ref-palette-primary40--md-sys-color-primary--md-comp-filled-button-container-color
Lightning--slds-g-color-blue-50--slds-g-color-brand-base-50Not exposed
Spectrum--spectrum-blue-900--spectrum-accent-background-color-default--spectrum-actionbutton-background-color-default
FluentcolorPaletteBlue600colorBrandBackgroundComponent-level in code

What to steal for your system

If you’re starting fresh

Use the Polaris pattern: --{prefix}-{category}-{property}-{variant}. It’s verbose but unambiguous. New team members can read the name and know exactly what it does.

If you have an existing system

Map your tokens to the 3-layer model (primitive > semantic > component). Most systems that struggle have tokens that skip the semantic layer and go straight from primitive to component.

If you support multiple brands

Follow Material Design’s approach: separate ref (reference/primitive) tokens from sys (system/semantic) tokens. Each brand overrides the sys layer, primitives stay shared.

Universal rules (every system agrees on these)

  1. Use a prefix. --p-, --cds-, --slds-. Avoids conflicts with other libraries.
  2. Separate concerns. Color tokens name the role (background, text, border), not the color (blue, red).
  3. Scale numerically for primitives. blue-500, spacing-400. Not blue-medium.
  4. Use semantic names for consumption. Components reference color-bg-brand, never blue-500.
  5. Document the “why.” Every token needs a description explaining when to use it.

Naming decision tree

Is it a raw value (hex, px, rem)?
  → Primitive token: {color}-{scale} or {category}-{step}

Does it describe a purpose?
  → Semantic token: {category}-{property}-{variant}

Is it tied to a specific component?
  → Component token: {component}-{property}-{state}

Interactive naming tool

namedesigntokens.guide is a free tool that generates consistent token names based on the patterns above. It has three surfaces depending on where you are in your naming process.

Start here

namedesigntokens.guide landing page with a hero that introduces the tool and four entry points into the Learn page, the Wizard, the Builder, and examples from real design systems.
Landing page, pick the path that matches where you are: learning, wizarding through your first system, or building directly.

Wizard, for a first design system

If you’re naming tokens for the first time, the Wizard walks you through category, property, and variant decisions and outputs a full set that follows the industry patterns in this guide.

Name Design Tokens Wizard in step two of the flow, asking which separator to use, with dot, slash, and dash options shown next to example token strings.
Wizard, answer five questions, get a consistent starting token set.

Builder, for when you know what you want

If you already have a naming convention in mind, the Builder lets you configure separators, casing, and token tiers directly and preview the output.

Name Design Tokens Builder showing the Primitive Token Preview with an example token 'background-500' and a list of 11 generated tokens grouped by component.
Builder, generate names like background-500 using industry conventions.

Learn, for the theory behind it

If you want to understand why certain patterns win, the Learn page breaks down the trade-offs between dot vs slash, kebab vs camel, and property-first vs role-first naming.

Name Design Tokens Learn page with side-by-side comparisons of naming patterns across major design systems and short explanations of when each one wins.
Learn, the theory behind the patterns, with real examples from Polaris, Carbon, Material, and Lightning.
Exercise

Name a real token set with AI, then automate it

45 min
  1. Try it in Claude (the chat window)

    Open Claude in the browser. Paste the prompt. Read the output carefully and answer the follow-up question about overlapping tokens. This is your baseline: one good prompt, one good result.

    • Every hex has a semantic name like color.background.primary or color.feedback.danger, not color.red.500
    • Claude flagged at least one ambiguous value and asked you to clarify (usually the accent color, because it could be brand or action)
    • The output is copy-pasteable as-is into a token file
    I have raw color values that need semantic token names.
    
    Palette:
    - #FBFBFA (main background)
    - #111111 (main text)
    - #DFFF82 (brand accent)
    - #E8E5D4 (subtle surface)
    - #B4B0A8 (muted text)
    - #DC2626 (error)
    - #059669 (success)
    
    Conventions I want to follow:
    - Structure: category.intent.modifier (e.g. color.background.primary)
    - Intent names the role, never the hex
    - Use "danger" and "success", never "red" and "green"
    
    Output: one token per line, no explanations. After the list, flag any value that could serve two different intents and ask me which to keep.
  2. Turn it into a Claude Code skill

    Now make it reusable. In your project, create the file:

    .claude/skills/name-tokens/SKILL.md

    Paste the prompt from Step 1 as the skill body, but replace the hardcoded palette with an instruction: “Read the raw color values from tokens/primitives.json in the current project. For each one, output a semantic name following the conventions below.”

    Add a skill frontmatter block at the top so Claude Code knows when to trigger it:

    ---
    name: name-tokens
    description: Generate semantic token names from raw values in tokens/primitives.json. Use when the user mentions naming tokens, semantic layer, or runs /name-tokens.
    ---
    • .claude/skills/name-tokens/SKILL.md exists in your repo
    • Running /name-tokens in Claude Code triggers the skill instead of a generic response
    • The skill reads from your actual tokens/primitives.json (not a pasted palette)
  3. Hook it up to real token files and run it

    Point the skill at real values. If you do not have a token file yet, create a minimal one:

    {
      "color": {
        "bone": "#FBFBFA",
        "ink": "#111111",
        "lime": "#DFFF82",
        "sand": "#E8E5D4"
      }
    }

    In Claude Code, run /name-tokens. Compare the output to what you got in Step 1. Then: change one primitive value in the JSON (e.g., swap #DFFF82 for #B8DFFF) and run it again. The semantic names should stay the same, because they describe role, not color.

    • The skill named every token in your JSON file without being asked for each one
    • Changing the hex value did not change the semantic name (color.brand.primary stays color.brand.primary whether it is lime or blue)
    • You can now regenerate the semantic layer any time primitives change, in one command
    • If it hallucinated a token that is not in your JSON, the skill prompt needs a stricter “only name values that exist in the file” instruction

Finished this lesson?

Mark it complete to track your progress through "Design System Automation".

Lesson
1 / 12
Progress
8%