Color & variants
Manti UI separates fixed color ramps from the semantic roles components use.
Primitive ramps
Six OKLCH ramps run from 1 (lightest) to 12 (darkest):
| Ramp | Purpose | Use it for |
|---|---|---|
gray | Neutral UI | Surfaces, borders, text, and secondary controls |
orange | Primary | Main actions, selected states, and the product accent |
green | Success | Positive feedback, completed states, and confirmations |
blue | Information | Informational feedback, notices, and helpful context |
amber | Warning | Caution, attention, and states that need review |
red | Danger | Errors, destructive actions, and critical feedback |
gray
orange
green
amber
red
blue
Each stop is available as --manti-{ramp}-{step}. Component CSS should use
semantic tokens or variants instead of choosing a stop directly.
Primitive scale contract
This mapping comes directly from colorScaleRoles in @manti-ui/tokens. Every
color ramp uses the same contract:
| Stop | Source role | Exact purpose |
|---|---|---|
1 | appBackground[0] | Lighter page or panel background position |
2 | appBackground[1] | Next page or panel background position |
3 | componentBackground.rest | Resting component background |
4 | componentBackground.hover | Hovered component background |
5 | componentBackground.active | Active, pressed, or selected component background |
6 | border.subtle | Subtle borders and separators |
7 | border.interactive | Interactive borders |
8 | border.strong | Strong borders and focus chrome |
9 | solid.rest | Resting solid fill |
10 | solid.hover | Hovered solid fill |
11 | text.lowContrast | Supporting or lower-contrast text |
12 | text.highContrast | Primary or highest-contrast text |
This is the palette's intended role contract, not a promise that every component
reads the primitive stop literally. Components consume semantic tokens or
--variant-* roles, and tokens.css adapts them for theme and contrast.
The current --variant-solid* mappings are:
| Variant | Rest | Hover | Active |
|---|---|---|---|
primary | orange-7 | theme-aware color-mix() | theme-aware color-mix() |
success, info, and danger | matching hue at step 8 | theme-aware color-mix() | theme-aware color-mix() |
secondary | gray-11 / gray-3 | gray-10 / gray-4 | gray-9 / gray-5 |
tertiary and outline | semantic neutral value | semantic neutral value | semantic neutral value |
Values separated by / mean light theme / dark theme. These mappings deliberately
depart from the nominal 9 → 10 solid pair when contrast requires it.
Input-like controls are the main exception to the colored-border progression. They use the neutral border at rest and hover, then introduce the variant color at focus or open.
Built-in variants
Manti ships seven variant palettes:
primary— orange, highest emphasis;secondary— neutral soft surface;success— green feedback;info— blue feedback;tertiary— neutral ghost;danger— red feedback;outline— neutral bordered treatment.
Individual components may expose a subset. Alert supports primary,
secondary, success, info, and danger. Badge omits tertiary. Button also
adds link.
Every variant defines the same roles:
--variant-solid
--variant-solid-hover
--variant-solid-active
--variant-on-solid
--variant-soft-bg
--variant-soft-bg-hover
--variant-soft-bg-active
--variant-soft-text
--variant-border
--variant-text
--variant-ringCustom variant
Components typed with MantiVariant accept custom strings:
[data-variant='brand'] {
--variant-solid: var(--manti-blue-9);
--variant-solid-hover: var(--manti-blue-10);
--variant-solid-active: color-mix(in oklab, var(--manti-blue-10) 88%, black);
--variant-on-solid: var(--manti-text-on-accent);
--variant-soft-bg: var(--manti-blue-2);
--variant-soft-bg-hover: var(--manti-blue-3);
--variant-soft-bg-active: var(--manti-blue-4);
--variant-soft-text: var(--manti-blue-9);
--variant-border: var(--manti-blue-7);
--variant-text: var(--manti-blue-9);
--variant-ring: var(--manti-blue-8);
}<Button variant="brand">Save</Button>Contributor checks
Use semantic roles in component CSS, keep foregrounds explicit, and verify both themes:
pnpm check:color-scale
pnpm --filter @manti-ui/styles check:contrast
pnpm --filter @manti-ui/styles buildLast updated