Theming
Stash colors come in three buckets. Use them in this order.
Token buckets
- Semantic tokens — role names like
primary,surface,text,success. Use these for almost everything. When a product color changes, it changes here once and every screen follows. - Primitives — the raw ramp (
--stash-color-blue-500and the rest), shown on the Colors page. Use a primitive only when no role fits — a brand gradient, a decorative fill, a one-off. - Data-visualization palette —
--stash-color-viz-1throughviz-8, a categorical sequence for charts. A chart series is not a UI role, so this bucket is exempt from the "prefer semantic" guidance.
Using semantic tokens
With Tailwind, write the semantic utility instead of a raw family utility: bg-primary, not bg-blue-500; text-muted-foreground, not text-ice-700. The content roles use shadcn-style utility names so the default text utility is not text-text.
| Role | Tailwind utility | CSS variable |
|---|---|---|
| Page background | bg-surface | --stash-color-surface |
| Card / panel | bg-surface-raised | --stash-color-surface-raised |
| Body text | text-foreground | --stash-color-text |
| Secondary text | text-muted-foreground | --stash-color-text-muted |
| Default border | border-border | --stash-color-border |
| Faint border | border-border-subtle | --stash-color-border-subtle |
| Primary action | bg-primary text-primary-foreground | --stash-color-primary |
| Tinted primary | bg-primary-subtle text-primary-subtle-foreground | --stash-color-primary-subtle |
| Link | text-link | --stash-color-link |
| Success / warning / error / info | bg-{role}, bg-{role}-subtle, text-{role}-subtle-foreground, border-{role}-border | --stash-color-{role}* |
Without Tailwind, read the CSS variables directly: color: var(--stash-color-text).
Dark mode
Add the .dark class to a root element (usually <html>); remove it for light. The :root values are light; a .dark block overrides them. Because a utility like bg-surface compiles to background-color: var(--color-surface) (which resolves to --stash-color-surface), it picks up the dark value on its own — no dark: variant needed. Apps that never add .dark render exactly as before.
To author an explicit dark: override for a one-off, add this once at the top level of your Tailwind entry (not inside a layer()-wrapped import):
@custom-variant dark (&:where(.dark, .dark *));Live examples
Toggle this site's light/dark switch and watch these flip.
Mapping to other frameworks
Semantic tokens are plain CSS variables, so any framework that themes through CSS variables can point its own names at ours. Do this in the consuming app, not in Stash.
shadcn/ui
Each shadcn variable maps to one Stash token. Set them in the app's global stylesheet:
:root {
--background: var(--stash-color-surface);
--foreground: var(--stash-color-text);
--card: var(--stash-color-surface-raised);
--card-foreground: var(--stash-color-text);
--popover: var(--stash-color-surface-overlay);
--popover-foreground: var(--stash-color-text);
--primary: var(--stash-color-primary);
--primary-foreground: var(--stash-color-primary-foreground);
--secondary: var(--stash-color-surface-sunken);
--secondary-foreground: var(--stash-color-text);
--muted: var(--stash-color-surface-sunken);
--muted-foreground: var(--stash-color-text-muted);
--accent: var(--stash-color-primary-subtle);
--accent-foreground: var(--stash-color-primary-subtle-foreground);
--destructive: var(--stash-color-error);
--destructive-foreground: var(--stash-color-error-foreground);
--border: var(--stash-color-border);
--input: var(--stash-color-border-strong);
--ring: var(--stash-color-focus-ring);
}Bootstrap (--bs-*)
Bootstrap 5.3 and later theme through CSS variables and support [data-bs-theme] for dark mode. Point the --bs-* variables at Stash tokens:
:root {
--bs-body-bg: var(--stash-color-surface);
--bs-body-color: var(--stash-color-text);
--bs-border-color: var(--stash-color-border);
--bs-primary: var(--stash-color-primary);
--bs-success: var(--stash-color-success);
--bs-warning: var(--stash-color-warning);
--bs-danger: var(--stash-color-error);
--bs-info: var(--stash-color-info);
}Bootstrap before 5.3 themes through Sass variables ($primary), so an older app needs a Sass bridge or has to override compiled values. Confirm the version first.
Angular Material (--mat-sys-*)
Angular Material 3 (Angular v17 and later) exposes system CSS variables. Point them at Stash tokens:
:root {
--mat-sys-surface: var(--stash-color-surface);
--mat-sys-on-surface: var(--stash-color-text);
--mat-sys-primary: var(--stash-color-primary);
--mat-sys-on-primary: var(--stash-color-primary-foreground);
--mat-sys-error: var(--stash-color-error);
--mat-sys-outline: var(--stash-color-border);
}Material 2 themes through Sass (define-palette), so the same version caveat applies.