167 lines
4.7 KiB
Plaintext
167 lines
4.7 KiB
Plaintext
---
|
|
alwaysApply: true
|
|
description: CSS Variables theme system best practices
|
|
---
|
|
|
|
# CSS Variables Theme System
|
|
|
|
## Core Principle: Pure CSS Variables for Theming
|
|
|
|
This project uses **CSS Variables exclusively** for theming. No Tailwind `dark:` classes or conditional CSS classes.
|
|
|
|
## ✅ Architecture Pattern
|
|
|
|
### CSS Structure
|
|
```css
|
|
:root {
|
|
/* Light theme (default values) */
|
|
--background: #f1f5f9;
|
|
--foreground: #0f172a;
|
|
--primary: #0891b2;
|
|
--success: #059669;
|
|
--destructive: #dc2626;
|
|
--accent: #d97706;
|
|
--purple: #8b5cf6;
|
|
--yellow: #eab308;
|
|
--green: #059669;
|
|
--blue: #2563eb;
|
|
--gray: #6b7280;
|
|
--gray-light: #e5e7eb;
|
|
}
|
|
|
|
.dark {
|
|
/* Dark theme (override values) */
|
|
--background: #1e293b;
|
|
--foreground: #f1f5f9;
|
|
--primary: #06b6d4;
|
|
--success: #10b981;
|
|
--destructive: #ef4444;
|
|
--accent: #f59e0b;
|
|
--purple: #8b5cf6;
|
|
--yellow: #eab308;
|
|
--green: #10b981;
|
|
--blue: #3b82f6;
|
|
--gray: #9ca3af;
|
|
--gray-light: #374151;
|
|
}
|
|
```
|
|
|
|
### Theme Application
|
|
- **Single source of truth**: [ThemeContext.tsx](mdc:src/contexts/ThemeContext.tsx) applies theme class to `document.documentElement`
|
|
- **No duplication**: Theme is applied only once, not in multiple places
|
|
- **SSR safe**: Initial theme from server-side preferences
|
|
|
|
## ✅ Component Usage Patterns
|
|
|
|
### Correct: Using CSS Variables
|
|
```tsx
|
|
// ✅ GOOD: CSS Variables in className
|
|
<div className="bg-[var(--card)] text-[var(--foreground)] border-[var(--border)]">
|
|
|
|
// ✅ GOOD: CSS Variables in style prop
|
|
<div style={{ color: 'var(--primary)', backgroundColor: 'var(--card)' }}>
|
|
|
|
// ✅ GOOD: CSS Variables with color-mix for transparency
|
|
<div style={{
|
|
backgroundColor: 'color-mix(in srgb, var(--primary) 10%, transparent)',
|
|
borderColor: 'color-mix(in srgb, var(--primary) 20%, var(--border))'
|
|
}}>
|
|
```
|
|
|
|
### ❌ Forbidden: Tailwind Dark Mode Classes
|
|
```tsx
|
|
// ❌ BAD: Tailwind dark: classes
|
|
<div className="bg-white dark:bg-gray-800 text-black dark:text-white">
|
|
|
|
// ❌ BAD: Conditional classes
|
|
<div className={theme === 'dark' ? 'bg-gray-800' : 'bg-white'}>
|
|
|
|
// ❌ BAD: Hardcoded colors
|
|
<div className="bg-red-500 text-blue-600">
|
|
```
|
|
|
|
## ✅ Color System
|
|
|
|
### Semantic Color Tokens
|
|
- `--background`: Main background color
|
|
- `--foreground`: Main text color
|
|
- `--card`: Card/panel background
|
|
- `--card-hover`: Card hover state
|
|
- `--card-column`: Column background (darker than cards)
|
|
- `--border`: Border color
|
|
- `--input`: Input field background
|
|
- `--primary`: Primary brand color
|
|
- `--primary-foreground`: Text on primary background
|
|
- `--muted`: Muted text color
|
|
- `--muted-foreground`: Secondary text color
|
|
- `--accent`: Accent color (orange/amber)
|
|
- `--destructive`: Error/danger color (red)
|
|
- `--success`: Success color (green)
|
|
- `--purple`: Purple accent
|
|
- `--yellow`: Yellow accent
|
|
- `--green`: Green accent
|
|
- `--blue`: Blue accent
|
|
- `--gray`: Gray color
|
|
- `--gray-light`: Light gray background
|
|
|
|
### Color Mixing Patterns
|
|
```css
|
|
/* Background with transparency */
|
|
background-color: color-mix(in srgb, var(--primary) 10%, transparent);
|
|
|
|
/* Border with transparency */
|
|
border-color: color-mix(in srgb, var(--primary) 20%, var(--border));
|
|
|
|
/* Text with opacity */
|
|
color: color-mix(in srgb, var(--destructive) 80%, transparent);
|
|
```
|
|
|
|
## ✅ Theme Context Usage
|
|
|
|
### ThemeProvider Setup
|
|
```tsx
|
|
// In layout.tsx
|
|
<ThemeProvider initialTheme={initialPreferences.viewPreferences.theme}>
|
|
{children}
|
|
</ThemeProvider>
|
|
```
|
|
|
|
### Component Usage
|
|
```tsx
|
|
import { useTheme } from '@/contexts/ThemeContext';
|
|
|
|
function MyComponent() {
|
|
const { theme, toggleTheme, setTheme } = useTheme();
|
|
|
|
return (
|
|
<button onClick={toggleTheme}>
|
|
Switch to {theme === 'dark' ? 'light' : 'dark'} theme
|
|
</button>
|
|
);
|
|
}
|
|
```
|
|
|
|
## ✅ Future Extensibility
|
|
|
|
This system is designed to support:
|
|
- **Custom color themes**: Easy to add new color variables
|
|
- **User preferences**: Colors can be dynamically changed
|
|
- **Theme presets**: Multiple predefined themes
|
|
- **Accessibility**: High contrast modes
|
|
|
|
## 🚨 Anti-patterns to Avoid
|
|
|
|
1. **Don't mix approaches**: Never use both CSS variables and Tailwind dark: classes
|
|
2. **Don't duplicate theme application**: Theme should be applied only in ThemeContext
|
|
3. **Don't hardcode colors**: Always use semantic color tokens
|
|
4. **Don't use conditional classes**: Use CSS variables instead
|
|
5. **Don't forget transparency**: Use `color-mix()` for semi-transparent colors
|
|
|
|
## 📁 Key Files
|
|
|
|
- [globals.css](mdc:src/app/globals.css) - CSS Variables definitions
|
|
- [ThemeContext.tsx](mdc:src/contexts/ThemeContext.tsx) - Theme management
|
|
- [UserPreferencesContext.tsx](mdc:src/contexts/UserPreferencesContext.tsx) - Preferences sync
|
|
- [layout.tsx](mdc:src/app/layout.tsx) - Theme provider setup
|
|
|
|
Remember: **CSS Variables are the single source of truth for theming. Keep it pure and consistent.** |