Colors

The palettes, the role vocabulary every hue shares, and where each is meant to be used.

The palettes#

Ten hues plus brand, each with eleven steps from 50 (near white) to 950 (near black). These are the primitives — the only real color values in the system; everything else is a pointer to one of these.

gray
red
orange
yellow
green
teal
blue
cyan
purple
pink

brand is special: by default it aliases the gold palette, but it's the one palette that can be replaced at runtime — pass tokens={{ brandColor }} to the provider and all ten brand steps are recomputed from your color (see Theming).

Roles — how components actually pick colors#

Components rarely touch a raw step like blue-600. Every palette exposes the same eight roles, and those are what variant styles are written against:

RoleJobExample use
solidThe strong fillSolid button background
contrastText on top of solidSolid button label
labelTinted text on neutral backgroundsLink text, subtle-button label
subtleFaint tinted backgroundBadge background, hover wash
mutedA step stronger than subtleSubtle-button hover
emphasizedStrongest tinted backgroundActive/pressed states
strokeTinted borderOutline button border
ringFocus ringAny focused control

Two things make this vocabulary powerful:

  • Light and dark values differ per role. In light mode blue-subtle points at blue-100; in dark mode it re-points at a deep step. Write against roles and dark mode is automatic.
  • Every hue answers the same questions. Because all palettes share the vocabulary, one set of component styles can be recolored to any hue — that's what makes colorScheme possible.

The accent channel#

accent-* is a ninth, virtual palette. It has the same eight roles but no colors of its own — it forwards to whichever real palette the nearest colorScheme chose (brand by default). Components are written once against accent-* and recolor through it. The full mechanism is explained on the Theming page.

Neutral semantic tokens#

For everyday UI structure — page backgrounds, text, borders — use the neutral roles instead of any palette:

FamilyTokensJob
Surfacebase · subtle · muted · emphasized · panel · invertedBackgrounds, in rising strength; panel for cards/overlays
Labelbase · muted · subtle · invertedText, from primary to faintest
Strokebase · subtle · muted · emphasized · invertedBorders and separators

Plus a status set (warning, error, success, info) across all three families — the same tokens Alert, Toast and form validation use.

Using colors in your own code#

Style props accept all three tiers:

<Box bg="subtle" />            {/* neutral semantic role */}
<Box bg="blue-subtle" />       {/* palette role */}
<Box bg="blue-100" />          {/* raw primitive — last resort */}
<Text color="muted" />         {/* neutral label role */}

Prefer the highest tier that says what you mean: semantic roles adapt to both themes on their own, palette roles adapt within their hue, and raw steps don't adapt at all. In custom CSS, the same values are available as variables — var(--astralis-color-blue-subtle), exactly like the swatch grid demo above does.