Skip to content

Theme Registry

THEME_REGISTRY in src/tokens/themes/registry.ts is the single source of truth for all themes in Stratum. Unistyles, ThemeProvider, and TypeScript types all auto-derive from this registry — you never need to update them manually.

src/tokens/themes/registry.ts
export const THEME_REGISTRY: ThemeEntry[] = [
{ name: 'slate', label: 'Slate', light: slateLight, dark: slateDark },
{ name: 'obsidian', label: 'Obsidian', light: obsidianLight, dark: obsidianDark },
{ name: 'quartz', label: 'Quartz', light: quartzLight, dark: quartzDark },
];
SystemWhat it gets
src/providers/unistyles.tsRegisters all themes with Unistyles so useStyles() works
ThemeProviderKnows which theme names are valid for initialTheme
ThemeName typeUnion type 'slate' | 'obsidian' | 'quartz' — inferred, not hand-written
useThemeToggle()setTheme() accepts only registered names
HIG ThemeBarRenders a button for each registered theme
  1. Create your theme file (use createTheme() or implement AppTheme directly):
src/tokens/themes/brand.ts
import { createTheme } from './createTheme';
import { slateThemeLight, slateThemeDark } from './slate';
export const brandLight = createTheme(slateThemeLight, { colors: { accent: '#E11D48' } });
export const brandDark = createTheme(slateThemeDark, { colors: { accent: '#FB7185' } });
  1. Add one entry to the registry:
import { brandLight, brandDark } from './brand';
export const THEME_REGISTRY: ThemeEntry[] = [
{ name: 'slate', label: 'Slate', light: slateLight, dark: slateDark },
{ name: 'obsidian', label: 'Obsidian', light: obsidianLight, dark: obsidianDark },
{ name: 'quartz', label: 'Quartz', light: quartzLight, dark: quartzDark },
{ name: 'brand', label: 'Brand', light: brandLight, dark: brandDark },
];

That’s the entire change. Everything else updates automatically.

interface ThemeEntry {
name: string; // used in setTheme() and initialTheme prop
label: string; // displayed in UI (ThemeBar, pickers)
light: AppTheme; // light variant
dark: AppTheme; // dark variant
}