next-shell

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

TokenUtilityPurpose
--backgroundbg-backgroundPage background
--foregroundtext-foregroundDefault text
--card / --card-foregroundbg-card, text-card-foregroundCard surfaces
--primary / --primary-foregroundbg-primary, text-primary-foregroundBrand accent
--secondary / --secondary-foregroundbg-secondary, text-secondary-foregroundNeutral accent
--muted / --muted-foregroundbg-muted, text-muted-foregroundSubdued content
--accent / --accent-foregroundbg-accent, text-accent-foregroundHover / focus states
--destructive / --destructive-foregroundbg-destructive, text-destructive-foregroundError / danger
--success / --success-foregroundbg-success, text-success-foregroundPositive feedback
--warning / --warning-foregroundbg-warning, text-warning-foregroundCaution
--info / --info-foregroundbg-info, text-info-foregroundInformational
--borderborder-borderDefault borders
--inputborder-inputForm input borders
--ringring-ringFocus rings

Radius tokens

--radius: 0.625rem; /* base — all variants derived from this */
UtilityValue
rounded-smcalc(var(--radius) - 4px)
rounded-mdcalc(var(--radius) - 2px)
rounded-lgvar(--radius)
rounded-xlcalc(var(--radius) + 4px)

Motion tokens

UtilityTokenValue
duration-fast--duration-fast150ms
duration-normal--duration-normal250ms
duration-slow--duration-slow400ms
ease-standard--ease-standardcubic-bezier(0.2, 0, 0, 1)
ease-emphasized--ease-emphasizedcubic-bezier(0.2, 0, 0, 1)
ease-decelerate--ease-deceleratecubic-bezier(0, 0, 0.2, 1)
ease-accelerate--ease-acceleratecubic-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.

On this page