Design System
The semantic-token contract that powers every component in next-shell.
Every color, radius, shadow, and motion value in @jonmatum/next-shell reaches the DOM through semantic tokens — CSS custom properties declared in styles/tokens.css and mapped to Tailwind utilities via styles/preset.css.
The custom ESLint rule next-shell/no-raw-colors fails CI immediately on any regression.
Semantic color tokens
| Token | Utility | Purpose |
|---|---|---|
--background | bg-background | Page background |
--foreground | text-foreground | Default text |
--card / --card-foreground | bg-card, text-card-foreground | Card surfaces |
--primary / --primary-foreground | bg-primary, text-primary-foreground | Brand accent |
--secondary / --secondary-foreground | bg-secondary, text-secondary-foreground | Neutral accent |
--muted / --muted-foreground | bg-muted, text-muted-foreground | Subdued content |
--accent / --accent-foreground | bg-accent, text-accent-foreground | Hover / focus states |
--destructive / --destructive-foreground | bg-destructive, text-destructive-foreground | Error / danger |
--success / --success-foreground | bg-success, text-success-foreground | Positive feedback |
--warning / --warning-foreground | bg-warning, text-warning-foreground | Caution |
--info / --info-foreground | bg-info, text-info-foreground | Informational |
--border | border-border | Default borders |
--input | border-input | Form input borders |
--ring | ring-ring | Focus rings |
Radius tokens
--radius: 0.625rem; /* base — all variants derived from this */
| Utility | Value |
|---|---|
rounded-sm | calc(var(--radius) - 4px) |
rounded-md | calc(var(--radius) - 2px) |
rounded-lg | var(--radius) |
rounded-xl | calc(var(--radius) + 4px) |
Motion tokens
| Utility | Token | Value |
|---|---|---|
duration-fast | --duration-fast | 150ms |
duration-normal | --duration-normal | 250ms |
duration-slow | --duration-slow | 400ms |
ease-standard | --ease-standard | cubic-bezier(0.2, 0, 0, 1) |
ease-emphasized | --ease-emphasized | cubic-bezier(0.2, 0, 0, 1) |
ease-decelerate | --ease-decelerate | cubic-bezier(0, 0, 0.2, 1) |
ease-accelerate | --ease-accelerate | cubic-bezier(0.3, 0, 1, 1) |
Dark mode
Tokens are scoped to [data-theme="dark"]. next-themes writes data-theme on the <html> element — add suppressHydrationWarning to avoid React hydration warnings:
<html lang="en" suppressHydrationWarning>
Brand overrides
Override any token per-theme via the brand prop on ThemeProvider:
import type { BrandOverrides } from '@jonmatum/next-shell/tokens';
const brand: BrandOverrides = {
light: {
primary: 'oklch(0.6 0.2 258)',
'primary-foreground': 'oklch(1 0 0)',
},
dark: {
primary: 'oklch(0.75 0.15 258)',
},
radius: '0.5rem',
fontSans: 'Inter, sans-serif',
};
<ThemeProvider brand={brand}>{children}</ThemeProvider>;
Overrides are applied as inline CSS custom properties — zero JS re-render on theme switch.