# Theming System Guide ## Overview This application uses a unified theming system where **all colors are defined in ONE place** and consumed everywhere else through semantic CSS variables and Tailwind utilities. ## Single Source of Truth All colors are defined in [`src/theme/tokens.ts`](./src/theme/tokens.ts): ```typescript // Change brand colors here and see them propagate throughout the app export const baseColors = { gold: { 500: '#d99e34', // Primary brand color // ... full scale }, warmGray: { /* ... */ }, purple: { /* ... */ }, }; export const lightTokens = { background: { primary: baseColors.pure.white, secondary: '#f8fafc', // ... semantic names only }, // ... }; ``` ## How It Works 1. **Tokens** → CSS Variables → Tailwind Classes → Components 2. No hardcoded hex values or color classes allowed anywhere 3. Theme switching handled automatically via CSS variables ## Changing Colors ### To rebrand the entire application: 1. Edit colors in `src/theme/tokens.ts` 2. Save the file - Vite HMR will update everything automatically 3. That's it! 🎉 ### Example: Change gold to blue: ```typescript // src/theme/tokens.ts export const baseColors = { gold: { 50: '#eff6ff', // was: '#fefcf0' 100: '#dbeafe', // was: '#fdf7dc' // ... continue with blue scale 500: '#3b82f6', // was: '#d99e34' - Primary brand color // ... rest of blue scale }, }; ``` ## Available Token Classes ### Background Colors - `bg-primary` - Main background - `bg-secondary` - Secondary background - `bg-tertiary` - Tertiary background - `bg-elevated` - Cards, modals - `bg-overlay` - Modal overlays ### Text Colors - `text-primary` - Primary text - `text-secondary` - Secondary text - `text-muted` - Muted text - `text-inverse` - Inverse text (white on dark backgrounds) - `text-disabled` - Disabled text ### Accent Colors - `accent-primary-{50-900}` - Warm gray scale - `accent-secondary-{50-900}` - Purple scale - `accent-gold-{50-900}` - Gold/brand scale - `accent-{color}-text` - Text color for each accent ### Semantic Colors - `success-{bg|border|text|accent}` - Success states - `warning-{bg|border|text|accent}` - Warning states - `error-{bg|border|text|accent}` - Error states - `info-{bg|border|text|accent}` - Info states ### Border Colors - `border` - Default border (mapped to `border-default`) - `border-muted` - Subtle borders - `border-strong` - Emphasized borders ### Glass Effects - `glass-bg` - Glass background - `glass-border` - Glass border - `glass-shadow` - Glass shadow ## Examples ### ✅ Correct Usage (Semantic tokens) ```tsx
``` ### ❌ Wrong Usage (Hardcoded colors) ```tsx
``` ## Component Patterns ### Button with token-based styling: ```tsx ``` ### Card with glass effect: ```tsx

Card Title

Card content

``` ## Theme Switching The system automatically handles light/dark theme switching: - Uses CSS variables that change based on `[data-theme="dark"]` or `.dark` classes - No JavaScript required for color changes - Blocking script in `index.html` prevents FOUC ## Validation & Linting The system includes validation to prevent hardcoded colors from sneaking back in: ```bash # Check for hardcoded colors npm run validate:theme # Lint will catch violations too npm run lint ``` ## Adding New Themes To add a third theme (e.g., "high-contrast"): 1. Add tokens to `src/theme/tokens.ts`: ```typescript export const highContrastTokens: ThemeTokens = { background: { primary: '#000000', // ... high contrast values }, // ... }; ``` 2. Update CSS generation in `src/theme/cssVariables.ts` 3. Update theme context to support new theme ## No-FOUC Implementation The theme is applied via a blocking script in `index.html` before React mounts: ```javascript // Sets theme class before any content renders document.documentElement.setAttribute('data-theme', theme); ``` ## Contrast & Accessibility All color combinations are validated for WCAG AA compliance using `src/utils/contrast.ts`. The utility now reads CSS variables directly, so contrast ratios are always accurate for the current theme. ## Migration from Hardcoded Colors Common replacements when migrating existing components: | Old (hardcoded) | New (semantic) | |----------------|----------------| | `text-slate-900` | `text-text-primary` | | `text-slate-600` | `text-text-secondary` | | `text-slate-400` | `text-text-muted` | | `bg-white` | `bg-bg-primary` | | `bg-slate-100` | `bg-bg-secondary` | | `border-slate-200` | `border-border` | | `text-white` | `text-text-inverse` | ## Benefits ✅ **Single source of truth** - Change colors in one file ✅ **Type safety** - TypeScript ensures valid tokens ✅ **No FOUC** - Theme applies before React renders ✅ **Automatic contrast** - WCAG compliance built-in ✅ **Lint protection** - Prevents hardcoded colors ✅ **Easy rebrand** - Update tokens, everything changes ✅ **Theme switching** - Seamless light/dark modes ## Architecture ``` src/theme/tokens.ts // Single source of truth ↓ src/theme/cssVariables.ts // Generate CSS variables ↓ src/styles/tokens.css // CSS variables output ↓ tailwind.config.js // Map to Tailwind classes ↓ Components // Use semantic classes ``` This architecture ensures that changing colors in `tokens.ts` propagates through the entire application automatically.