Components

Component tokens go under the components key as named objects. Each object holds up to eight typed sub-token fields. Variants for interaction states (hover, active, disabled, etc.) are defined as sibling keys with a state suffix. References that point to undefined tokens produce a broken-ref error visible in the tool's diagnostics panel.

Token shape#

Each component is a key mapped to an object. The key is a free-form component name (e.g., button-primary, card, input). The value is an object whose keys are sub-token names:

components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    typography: "{typography.label-md}"
    rounded: "{rounded.md}"
    padding: 12px
  card:
    backgroundColor: "{colors.surface}"
    rounded: "{rounded.lg}"
    padding: "{spacing.md}"

Sub-token fields reference#

FieldTypeDescription
backgroundColorColorBackground fill. Accepts a hex color string or a {colors.token} reference.
textColorColorForeground text color. The linter checks the backgroundColor / textColor pair for WCAG AA contrast (4.5:1 minimum).
typographyTypographyReferences a full typography token using {typography.token-name}. This is the one place where a reference to a composite value (an object) is permitted.
roundedDimensionBorder-radius. Accepts a literal dimension (e.g., 8px) or a {rounded.token} reference.
paddingDimensionInternal padding. Accepts a literal dimension or a {spacing.token} reference.
sizeDimensionGeneral size (often used for icon containers, avatars, or fixed-size elements).
heightDimensionExplicit height constraint.
widthDimensionExplicit width constraint.

All sub-token fields are optional. A component with only backgroundColor and textColor is valid.

Unknown sub-token field names (e.g., borderColor) are accepted by the parser and reported as a warning-severity finding by the broken-ref linter rule (message: "'borderColor' is not a recognized component sub-token"). The file remains parseable; only confirmed sub-token fields are typed and validated.

Variant sibling keys#

A component can have variants for interaction states. A variant is defined as a sibling key in components whose name is the base component name plus a hyphen-separated state suffix:

components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    rounded: "{rounded.md}"
    padding: 12px
  button-primary-hover:
    backgroundColor: "{colors.primary-dark}"
  button-primary-disabled:
    backgroundColor: "{colors.neutral}"
    textColor: "{colors.on-primary}"

The engine recognizes these state suffixes: hover, active, pressed, disabled, focus, selected, checked.

For a sibling to be treated as a variant, two conditions must both hold:

  1. The suffix is one of the recognized state words above.
  2. The base name (everything before the last hyphen) is also defined as its own component entry.

If the base component does not exist, the key is treated as a standalone component, not a variant. For example, button-primary-hover is a variant only if button-primary is also defined.

Variant components carry only the properties that differ from the base state. Agents are expected to merge the base and variant tokens, with the variant's values taking precedence.

Token references and broken-ref errors#

Component sub-token values can reference any previously defined token:

  • {colors.token-name} for Color fields
  • {typography.token-name} for the typography field
  • {rounded.token-name} for the rounded field
  • {spacing.token-name} for the padding, size, height, or width fields

If a reference points to a token that does not exist, the engine records it as an unresolved reference. In this tool, each unresolved reference appears as a broken-ref warning in the diagnostics panel and as a warning on the component's row in the parsed output.

Example: if {rounded.md} is used but the rounded map has no md key, the engine logs:

unresolved {rounded.md}

The file remains parseable; the broken reference does not prevent other tokens from loading. Fix broken references by adding the missing token or correcting the reference path.

Full DESIGN.md example: Components section#

---
name: System Design
colors:
  primary: "#0D47A1"
  on-primary: "#FFFFFF"
  surface: "#FAFAFA"
  on-surface: "#1A1A1A"
  neutral: "#E0E0E0"
  muted: "#9E9E9E"
typography:
  label-md:
    fontFamily: Inter
    fontSize: 14px
    fontWeight: 500
    lineHeight: 1.0
    letterSpacing: "0.01em"
rounded:
  sm: 4px
  md: 8px
  full: 9999px
spacing:
  sm: 8px
  md: 16px
components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    typography: "{typography.label-md}"
    rounded: "{rounded.md}"
    padding: "{spacing.md}"
  button-primary-hover:
    backgroundColor: "#1565C0"
  button-primary-disabled:
    backgroundColor: "{colors.neutral}"
    textColor: "{colors.muted}"
  input:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.on-surface}"
    rounded: "{rounded.sm}"
    padding: "{spacing.sm}"
---

## Components

Two primary interactive atoms: a filled button and a text input.

- **button-primary**: Filled with the primary blue; white label text.
  Hover state deepens the fill by one step. Disabled state uses neutral
  grey with muted text to communicate non-interactivity.
- **input**: Neutral surface background with a subtle 4px radius. Padding
  follows the `sm` spacing step to remain compact in dense forms.

Try it in the tool

Was this page helpful?