# Design System Theme System Guide

**Version:** 1.0.0
**Last Updated:** December 7, 2025

Complete guide to theming and customizing the design system.

---

## Table of Contents

1. [Theme Overview](#theme-overview)
2. [Light Mode (Default)](#light-mode-default)
3. [Dark Mode](#dark-mode)
4. [Custom Themes](#custom-themes)
5. [Theme Switching](#theme-switching)
6. [CSS Variable Customization](#css-variable-customization)
7. [Component Theming](#component-theming)
8. [Best Practices](#best-practices)

---

## Theme Overview

The design system includes:
- ✅ Light mode (default)
- ✅ Dark mode (CSS class-based)
- ✅ Full customization via CSS variables
- ✅ Per-component theme support
- ✅ Automatic contrast checking

### How Theming Works

Themes are implemented using CSS custom properties (variables) that automatically apply based on a class on the root element:

```html
<!-- Light mode (default) -->
<html>
  <body>...</body>
</html>

<!-- Dark mode -->
<html class="dark">
  <body>...</body>
</html>
```

---

## Light Mode (Default)

Light mode is the default theme with clean, bright colors optimized for daytime viewing.

### Color Palette (Light Mode)

| Token | Color | HEX | Usage |
|-------|-------|-----|-------|
| `--primary` | Blue | `#3b82f6` | Primary actions, focus |
| `--secondary` | Indigo | `#6366f1` | Secondary elements |
| `--success` | Green | `#10b981` | Success feedback |
| `--warning` | Amber | `#f59e0b` | Warning messages |
| `--destructive` | Red | `#ef4444` | Error/delete actions |
| `--info` | Cyan | `#0ea5e9` | Information |
| `--foreground` | Slate-900 | `#0f172a` | Primary text |
| `--muted-foreground` | Slate-600 | `#64748b` | Secondary text |
| `--background` | White | `#ffffff` | Page background |
| `--card` | Slate-50 | `#f8fafc` | Card backgrounds |
| `--card-foreground` | Slate-900 | `#1e293b` | Card text |
| `--border` | Slate-200 | `#e2e8f0` | Borders |
| `--input` | White | `#ffffff` | Input backgrounds |
| `--ring` | Blue | `#3b82f6` | Focus rings |

### Light Mode Appearance

- Clear distinction between elements
- High contrast text (4.5:1+)
- Subtle shadows for depth
- Neutral backgrounds
- Vibrant accent colors

### CSS

```css
:root {
  /* Light mode variables are set by default */
  --primary: #3b82f6;
  --secondary: #6366f1;
  --success: #10b981;
  --warning: #f59e0b;
  --destructive: #ef4444;
  --info: #0ea5e9;
  --foreground: #0f172a;
  --muted-foreground: #64748b;
  --background: #ffffff;
  --card: #f8fafc;
  --card-foreground: #1e293b;
  --border: #e2e8f0;
  --input: #ffffff;
  --ring: #3b82f6;
}
```

---

## Dark Mode

Dark mode provides eye-friendly colors for low-light environments.

### Enabling Dark Mode

```javascript
// Add dark class to enable dark mode
document.documentElement.classList.add('dark');
```

### Color Palette (Dark Mode)

| Token | Color | HEX | Usage |
|-------|-------|-----|-------|
| `--primary` | Light Blue | `#60a5fa` | Primary actions |
| `--secondary` | Light Indigo | `#818cf8` | Secondary elements |
| `--success` | Light Green | `#34d399` | Success feedback |
| `--warning` | Light Amber | `#fbbf24` | Warning messages |
| `--destructive` | Light Red | `#f87171` | Error/delete actions |
| `--info` | Light Cyan | `#38bdf8` | Information |
| `--foreground` | Slate-50 | `#f1f5f9` | Primary text |
| `--muted-foreground` | Slate-400 | `#cbd5e1` | Secondary text |
| `--background` | Slate-950 | `#0f172a` | Page background |
| `--card` | Slate-900 | `#1e293b` | Card backgrounds |
| `--card-foreground` | Slate-50 | `#e2e8f0` | Card text |
| `--border` | Slate-800 | `#334155` | Borders |
| `--input` | Slate-900 | `#1f2937` | Input backgrounds |
| `--ring` | Light Blue | `#60a5fa` | Focus rings |

### Dark Mode Appearance

- Dark backgrounds reduce eye strain
- Brighter text for readability
- Adjusted accent colors for clarity
- Softer shadows
- Maintained contrast ratios

### CSS

```css
:root.dark {
  --primary: #60a5fa;
  --secondary: #818cf8;
  --success: #34d399;
  --warning: #fbbf24;
  --destructive: #f87171;
  --info: #38bdf8;
  --foreground: #f1f5f9;
  --muted-foreground: #cbd5e1;
  --background: #0f172a;
  --card: #1e293b;
  --card-foreground: #e2e8f0;
  --border: #334155;
  --input: #1f2937;
  --ring: #60a5fa;
}
```

### Component Support

All 9 components support dark mode:

- ✅ DsButton - All variants themed
- ✅ DsInput - Form fields themed
- ✅ DsCard - Background and text adjusted
- ✅ DsBadge - Color variants adjusted
- ✅ DsToast - Backgrounds and text adjusted
- ✅ DsWorkflow - Step colors adjusted
- ✅ DsNotificationCenter - Scrollbar styled
- ✅ DsActionBar - Background themed
- ✅ DsToastProvider - Inherits from toasts

---

## Custom Themes

Create custom themes by overriding CSS variables.

### Creating a Custom Theme

```css
/* custom-theme.css */
:root.custom-theme {
  /* Custom brand colors */
  --primary: #6d28d9;        /* Deep purple */
  --secondary: #d946ef;      /* Magenta */
  --success: #22c55e;        /* Bright green */
  --warning: #eab308;        /* Bright yellow */
  --destructive: #dc2626;    /* Bright red */

  /* Custom backgrounds */
  --background: #f9f5ff;     /* Lavender white */
  --card: #f3e8ff;           /* Light purple */
  --card-foreground: #3f0f63; /* Dark purple text */

  /* Custom text colors */
  --foreground: #1f1337;     /* Dark purple */
  --muted-foreground: #6b5280; /* Muted purple */

  /* Adjust other tokens as needed */
  --border: #e9d5ff;         /* Light purple border */
  --input: #fafaf9;          /* Warm white */
}
```

### Applying Custom Theme

```html
<html class="custom-theme">
  <body>...</body>
</html>
```

```javascript
// Switch to custom theme
document.documentElement.classList.add('custom-theme');

// Remove other themes
document.documentElement.classList.remove('dark', 'light');
```

### Brand-Specific Theme Example

```css
/* tech-brand-theme.css - Modern tech company theme */
:root.tech-brand {
  --primary: #0066ff;        /* Vibrant blue */
  --secondary: #00d4ff;      /* Cyan */
  --success: #00ff88;        /* Neon green */
  --warning: #ffaa00;        /* Bright orange */
  --destructive: #ff3366;    /* Hot pink */

  --foreground: #1a1a2e;     /* Dark blue */
  --background: #0f1419;     /* Almost black */
  --card: #161b22;           /* Slightly lighter black */
  --card-foreground: #ffffff; /* Pure white text */
  --border: #30363d;         /* Dark gray borders */
}

:root.tech-brand.dark {
  /* Dark mode would be even more dark/vibrant */
  --primary: #00d4ff;        /* Swap primary/secondary in dark */
  --secondary: #0066ff;
  --success: #00ff88;
}
```

### Corporate Theme Example

```css
/* corporate-theme.css - Professional corporate theme */
:root.corporate {
  --primary: #003366;        /* Navy blue */
  --secondary: #666666;      /* Gray */
  --success: #006600;        /* Dark green */
  --warning: #cc6600;        /* Brown-orange */
  --destructive: #990000;    /* Dark red */

  --foreground: #000000;     /* Pure black */
  --background: #ffffff;     /* Pure white */
  --card: #f5f5f5;           /* Light gray */
  --card-foreground: #333333; /* Dark gray text */
  --border: #cccccc;         /* Medium gray borders */
}
```

---

## Theme Switching

### Simple Theme Toggle

```html
<button id="theme-toggle">Toggle Dark Mode</button>

<script>
  const button = document.getElementById('theme-toggle');

  button.addEventListener('click', () => {
    document.documentElement.classList.toggle('dark');
  });
</script>
```

### Theme Switcher with Dropdown

```html
<select id="theme-selector">
  <option value="">Light</option>
  <option value="dark">Dark</option>
  <option value="custom-theme">Custom Brand</option>
  <option value="corporate">Corporate</option>
</select>

<script>
  const selector = document.getElementById('theme-selector');

  selector.addEventListener('change', (e) => {
    const theme = e.target.value;

    // Remove all theme classes
    document.documentElement.classList.remove('dark', 'custom-theme', 'corporate');

    // Add selected theme
    if (theme) {
      document.documentElement.classList.add(theme);
    }

    // Save preference
    localStorage.setItem('preferred-theme', theme);
  });

  // Load saved preference
  const saved = localStorage.getItem('preferred-theme');
  if (saved) {
    document.documentElement.classList.add(saved);
    selector.value = saved;
  }
</script>
```

### System Preference Detection

```javascript
// Detect system dark mode preference
function getSystemTheme() {
  if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
    return 'dark';
  }
  return 'light';
}

// Apply system theme on page load
function applySystemTheme() {
  const saved = localStorage.getItem('preferred-theme');
  const theme = saved || getSystemTheme();

  if (theme === 'dark') {
    document.documentElement.classList.add('dark');
  } else {
    document.documentElement.classList.remove('dark');
  }
}

applySystemTheme();

// Listen for system theme changes
window.matchMedia('(prefers-color-scheme: dark)')
  .addEventListener('change', (e) => {
    if (!localStorage.getItem('preferred-theme')) {
      // Only change if user hasn't set preference
      if (e.matches) {
        document.documentElement.classList.add('dark');
      } else {
        document.documentElement.classList.remove('dark');
      }
    }
  });
```

### Theme Switcher Component

```html
<div class="theme-switcher">
  <button id="light-theme" aria-label="Light theme">☀️</button>
  <button id="dark-theme" aria-label="Dark theme">🌙</button>
  <button id="auto-theme" aria-label="Auto theme">🔄</button>
</div>

<script>
  const lightBtn = document.getElementById('light-theme');
  const darkBtn = document.getElementById('dark-theme');
  const autoBtn = document.getElementById('auto-theme');

  lightBtn.addEventListener('click', () => {
    document.documentElement.classList.remove('dark');
    localStorage.setItem('preferred-theme', 'light');
  });

  darkBtn.addEventListener('click', () => {
    document.documentElement.classList.add('dark');
    localStorage.setItem('preferred-theme', 'dark');
  });

  autoBtn.addEventListener('click', () => {
    localStorage.removeItem('preferred-theme');
    applySystemTheme();
  });

  // Highlight current theme
  function updateButtons() {
    const isDark = document.documentElement.classList.contains('dark');
    lightBtn.classList.toggle('active', !isDark);
    darkBtn.classList.toggle('active', isDark);
  }

  updateButtons();
  document.addEventListener('theme-change', updateButtons);
</script>
```

---

## CSS Variable Customization

### Override Global Variables

```css
/* Override for entire page */
:root {
  --primary: #your-color;
  --space-4: 1.25rem;
  --duration-normal: 0.3s;
}
```

### Override for Specific Components

```css
/* Custom styling for one component */
.my-special-button {
  --primary: #ff6b6b;  /* Use different color */
  background: var(--primary);
}

/* Custom styling for theme */
:root.my-theme {
  --primary: #667eea;
  --secondary: #764ba2;
}
```

### Using Variables in JavaScript

```javascript
// Get variable value
const primaryColor = getComputedStyle(document.documentElement)
  .getPropertyValue('--primary')
  .trim();

// Set variable value
document.documentElement.style.setProperty('--primary', '#ff0000');

// In component
class CustomComponent extends HTMLElement {
  getPrimaryColor() {
    return getComputedStyle(this).getPropertyValue('--primary').trim();
  }

  setPrimaryColor(color) {
    this.style.setProperty('--primary', color);
  }
}
```

---

## Component Theming

### Button Theming

```css
/* Light mode button colors */
.ds-btn[data-variant="primary"] {
  background: var(--primary);
  color: white;
}

.ds-btn[data-variant="success"] {
  background: var(--success);
  color: white;
}

/* Dark mode adjustments (automatic via tokens) */
:root.dark .ds-btn[data-variant="primary"] {
  background: var(--primary);  /* Already adjusted in tokens */
  color: white;
}
```

### Input Theming

```css
/* Light mode input */
.ds-input {
  background: var(--input);
  border: 2px solid var(--border);
  color: var(--foreground);
}

/* Dark mode input (automatic) */
:root.dark .ds-input {
  background: var(--input);     /* Dark background */
  border-color: var(--border);  /* Lighter border */
  color: var(--foreground);     /* Light text */
}

/* Focus state (works in both themes) */
.ds-input:focus {
  border-color: var(--ring);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--ring) 20%, transparent);
}
```

### Card Theming

```css
/* Light mode card */
.ds-card {
  background: var(--card);
  color: var(--card-foreground);
  border: 1px solid var(--border);
}

/* Dark mode card (automatic) */
:root.dark .ds-card {
  background: var(--card);       /* Dark background */
  color: var(--card-foreground); /* Light text */
  border-color: var(--border);   /* Darker border */
}
```

### Toast Theming

```css
/* Light mode toast */
.ds-toast[data-type="success"] {
  border-left: 4px solid var(--success);
  background: linear-gradient(135deg,
    color-mix(in oklch, var(--success) 5%, var(--card)) 0%,
    var(--card) 100%);
}

/* Dark mode toast (automatic) */
:root.dark .ds-toast[data-type="success"] {
  /* Uses dark theme tokens automatically */
  border-left-color: var(--success);
  background: linear-gradient(135deg,
    color-mix(in oklch, var(--success) 5%, var(--card)) 0%,
    var(--card) 100%);
}
```

---

## Best Practices

### 1. Always Use Tokens

```css
/* ✅ Good */
.my-button {
  background: var(--primary);
  color: var(--foreground);
  padding: var(--space-4);
}

/* ❌ Bad */
.my-button {
  background: #3b82f6;
  color: #0f172a;
  padding: 16px;
}
```

### 2. Test in Both Themes

```javascript
// Test dark mode
document.documentElement.classList.add('dark');
// Check colors, contrast, visibility

// Test light mode
document.documentElement.classList.remove('dark');
// Check colors, contrast, visibility
```

### 3. Maintain Contrast

Ensure all text meets WCAG 2.1 AA minimum (4.5:1 contrast ratio):

```javascript
// Validate contrast
function checkContrast(foreground, background) {
  const fgLum = getRelativeLuminance(foreground);
  const bgLum = getRelativeLuminance(background);
  const ratio = (Math.max(fgLum, bgLum) + 0.05) / (Math.min(fgLum, bgLum) + 0.05);
  return ratio >= 4.5; // WCAG AA
}
```

### 4. Respect User Preferences

```javascript
// Always check prefers-color-scheme
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
  // Apply dark mode
} else {
  // Apply light mode
}

// Listen for changes
window.matchMedia('(prefers-color-scheme: dark)')
  .addEventListener('change', (e) => {
    // Update theme
  });
```

### 5. Announce Theme Changes

```javascript
// Emit custom event when theme changes
const event = new CustomEvent('theme-change', {
  detail: { theme: isDark ? 'dark' : 'light' }
});
document.dispatchEvent(event);

// Listen for theme changes
document.addEventListener('theme-change', (e) => {
  console.log('Theme changed to:', e.detail.theme);
});
```

### 6. Handle Transitions Smoothly

```css
/* Smooth color transitions when switching themes */
* {
  transition: background-color 0.2s ease, color 0.2s ease;
}

/* But avoid transitions on initial load */
*:not(:root):not(body) {
  transition: none;
}

:root.theme-changing * {
  transition: background-color 0.2s ease, color 0.2s ease;
}
```

### 7. Document Custom Themes

```markdown
# Custom Theme: TechBrand

## Colors
- Primary: #0066ff (Vibrant Blue)
- Secondary: #00d4ff (Cyan)
- Success: #00ff88 (Neon Green)

## Usage
```html
<html class="tech-brand">
  <!-- Content -->
</html>
```

## Dark Mode
Automatically supports dark theme with enhanced contrast.
```

---

## Troubleshooting

### Issue: Theme not applying
**Solution:** Make sure CSS is loaded before HTML:
```javascript
// Load in this order:
import '@company/design-system/css/variants.css';
import '@company/design-system/css/components.css';
```

### Issue: Custom colors not working
**Solution:** Use CSS custom properties, not hardcoded values:
```css
/* ✅ Works */
--primary: #your-color;

/* ❌ Doesn't work */
background: #your-color;
```

### Issue: Dark mode colors don't match
**Solution:** Adjust tokens in dark mode CSS:
```css
:root.dark {
  --primary: #lighter-color; /* Use lighter shade in dark mode */
}
```

### Issue: Contrast is too low
**Solution:** Check WCAG ratios and adjust colors:
```javascript
// Aim for 4.5:1 minimum (WCAG AA)
// 7:1+ for best accessibility (WCAG AAA)
```

---

## Summary

The design system theming system provides:

✅ **Light & Dark modes** - Out of the box
✅ **42 CSS variables** - Full customization
✅ **Automatic component support** - All 9 components themed
✅ **High contrast** - WCAG 2.1 AA compliant
✅ **System preference detection** - Respects OS preference
✅ **Persistence** - Save user theme preference
✅ **Custom themes** - Create brand-specific themes
✅ **Smooth transitions** - Animate theme changes

---

**For more help:** design-system@company.com
