Colors

Color tokens go under the colors key in YAML frontmatter as name-to-hex pairs. Values must be # followed by six hex digits (sRGB). Components reference colors with the {colors.token-name} syntax. The linter checks every backgroundColor/textColor component pair for WCAG AA contrast (minimum 4.5:1).

Token shape#

Each color token is a key-value pair. The key is a free-form name; the value is a hex color string.

colors:
  primary: "#1A1C1E"
  secondary: "#6C7278"
  tertiary: "#B8422E"
  neutral: "#F7F5F2"

Value format. The value must be a # followed by exactly six hexadecimal digits (sRGB, case-insensitive). The linter rejects values that do not match this pattern.

Key names. Any string key is accepted. Unknown token names do not produce errors. The spec recommends a core set of names (see below) to maximize interoperability with agents and exporters.

The spec-config in @google/design.md 0.3.0 lists these recommended names:

NameTypical role
primaryMain brand color; headlines, key UI surfaces
secondarySupporting color; borders, metadata, captions
tertiaryAccent; CTAs, interactive highlights
neutralBackground foundation
surfaceCard and panel backgrounds
on-surfaceText/icon color when placed on surface
errorDestructive actions, validation failures

Missing a primary token when colors are otherwise defined triggers a missing-primary warning: the linter flags that agents will auto-generate a primary.

Example palette#

primary#1A1C1E secondary#6C7278 tertiary#B8422E neutral#F7F5F2
colors:
  primary: "#1A1C1E"
  secondary: "#6C7278"
  tertiary: "#B8422E"
  neutral: "#F7F5F2"

Token references#

Components and other token values can reference a color with the {colors.token-name} syntax:

components:
  button-primary:
    backgroundColor: "{colors.tertiary}"
    textColor: "#ffffff"
    rounded: "{rounded.md}"
    padding: 12px

The reference path is {colors.<key>} where <key> matches a key defined under colors. A reference that points to a key that does not exist triggers a broken-ref error (severity: error, meaning the file is rejected).

Nesting limit. The parser supports up to 10 levels of reference depth and 20 levels of token nesting. Cycles or references beyond that limit are flagged as broken.

Contrast-ratio lint (WCAG AA)#

The linter includes a contrast-ratio rule that checks every component definition that has both a backgroundColor and a textColor. It computes the relative luminance of each color and verifies the contrast ratio meets the WCAG AA minimum of 4.5:1.

A component that fails produces a contrast-ratio warning (severity: warning). Example finding from the linter:

{
  "severity": "warning",
  "path": "components.button-secondary",
  "message": "textColor (#6C7278) on backgroundColor (#F7F5F2) has contrast ratio 3.20:1, below WCAG AA minimum of 4.5:1."
}

Note. The rule fires only for components with explicit backgroundColor and textColor values (or resolved token references). Components with only one of the two properties are skipped.

Orphaned tokens#

The orphaned-tokens rule (severity: warning) flags any color token defined in colors that is never referenced by any component's backgroundColor or textColor. Orphaned tokens indicate either a forgotten cleanup or a palette defined ahead of component usage. They do not prevent the file from being valid.

Full DESIGN.md example: colors section#

---
name: Mono Studio
colors:
  primary: "#111111"
  on-primary: "#FFFFFF"
  surface: "#F5F5F5"
  on-surface: "#111111"
  accent: "#4A6FFF"
  error: "#CC2929"
components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    rounded: 6px
    padding: 12px
---

## Colors

A near-black primary on a light surface, with an electric-blue accent
for interactive elements. The palette passes WCAG AA for all component pairs.

- **Primary (#111111):** Near-black for all primary UI chrome.
- **Surface (#F5F5F5):** Off-white to reduce eye strain on large canvases.
- **Accent (#4A6FFF):** Electric blue for links, focus rings, and CTAs.

Try it in the tool

Was this page helpful?