NDPRThemeProvider

Typed React Context wrapper that injects --ndpr-* CSS custom properties from a JavaScript theme object. Pair it with the toolkit stylesheet to brand every component in one place.

Overview

NDPRThemeProvideris a thin wrapper around the toolkit's existing CSS-variable theming model. It renders a single<div> with--ndpr-* custom properties set inline, so every nested toolkit component picks them up automatically.

The provider is syntactic sugar — it is not a runtime requirement. Unset fields cascade from the stylesheet defaults at @tantainnovative/ndpr-toolkit/styles, so you can set just the few tokens you care about (brand colour, radius) and leave the rest alone.

Quickstart

import { NDPRThemeProvider, type NDPRTheme } from '@tantainnovative/ndpr-toolkit';
import '@tantainnovative/ndpr-toolkit/styles';

const theme: NDPRTheme = {
  colors: {
    primary: '22 163 74',          // RGB triplet — green-600
    primaryHover: '21 128 61',     // green-700
  },
  radius: { base: '0.75rem' },
  font: { sans: '"Inter", system-ui, sans-serif' },
};

export default function App() {
  return (
    <NDPRThemeProvider theme={theme}>
      <YourApp />
    </NDPRThemeProvider>
  );
}

Colour values are RGB triplets

Every colour token takes the format 'R G B' — three space-separated channels, no rgb() wrapper. The stylesheet wraps them internally as rgb(var(--ndpr-primary)), which lets the same token power solid backgrounds and transparent tints like rgb(var(--ndpr-primary) / 0.12).

// If your design system stores hex, add a one-liner converter:
const hexToRgbTriplet = (hex: string) => {
  const n = parseInt(hex.replace('#', ''), 16);
  return `${(n >> 16) & 255} ${(n >> 8) & 255} ${n & 255}`;
};

const theme: NDPRTheme = {
  colors: { primary: hexToRgbTriplet('#16a34a') },
};

Props

PropTypeDescription
themeNDPRThemeOptional partial theme. Only set fields produce CSS variables; unset fields cascade from the stylesheet.
classNamestringOptional class on the wrapping <div>. Useful for Tailwind utilities (e.g. "min-h-screen bg-background").
childrenReact.ReactNodeApp tree. Anything below the provider inherits the theme.

NDPRTheme shape

Every field is optional. The full type:

interface NDPRTheme {
  mode?: 'light' | 'dark';
  colors?: {
    primary?: string;              // --ndpr-primary
    primaryHover?: string;         // --ndpr-primary-hover
    primaryForeground?: string;    // --ndpr-primary-foreground
    background?: string;           // --ndpr-background
    surface?: string;              // --ndpr-surface
    foreground?: string;           // --ndpr-foreground
    muted?: string;                // --ndpr-muted
    mutedForeground?: string;      // --ndpr-muted-foreground
    border?: string;               // --ndpr-border
    input?: string;                // --ndpr-input
    ring?: string;                 // --ndpr-ring
    success?: string;              // --ndpr-success
    destructive?: string;          // --ndpr-destructive
    warning?: string;              // --ndpr-warning
  };
  radius?: { sm?: string; base?: string; lg?: string; full?: string };
  spacing?: { 1?: string; 2?: string; 3?: string; 4?: string; 5?: string; 6?: string; 8?: string };
  shadow?: { sm?: string; base?: string; lg?: string };
  font?: {
    sans?: string;
    sizeXs?: string; sizeSm?: string; sizeBase?: string;
    sizeLg?: string; sizeXl?: string;
    lineHeight?: string; lineHeightTight?: string;
  };
  transition?: { base?: string; slow?: string };
  z?: { banner?: number | string; modal?: number | string };
}

Dark mode

Setting mode: 'dark' stamps data-theme="dark" on the wrapper, which activates the dark-mode block in the stylesheet. The toolkit also auto-switches via prefers-color-scheme, so most apps don't need to set mode explicitly.

const [mode, setMode] = useState<'light' | 'dark'>('light');

<NDPRThemeProvider theme={{ mode }}>
  <button onClick={() => setMode(m => m === 'dark' ? 'light' : 'dark')}>
    Toggle theme
  </button>
  <App />
</NDPRThemeProvider>

When NOT to use the provider

  • You manage design tokens in CSS — write :root { --ndpr-primary: 22 163 74; } directly.
  • You need to scope tokens to a subtree without an extra DOM node — apply --ndpr-* overrides on your existing ancestor.
  • You're bringing your own design system — use the /unstyled entry and skip CSS variables entirely.