|
| 1 | +# Palette guidance |
| 2 | + |
| 3 | +## Hue reference (for step 1) |
| 4 | + |
| 5 | +| Color | Hue Range | Tailwind Gray | |
| 6 | +|-------|-----------|---------------| |
| 7 | +| Red/Coral | 0-30 | neutral | |
| 8 | +| Orange/Amber | 30-60 | stone | |
| 9 | +| Yellow/Gold | 60-90 | stone | |
| 10 | +| Green/Lime/Avocado | 90-150 | stone | |
| 11 | +| Teal/Cyan | 150-200 | zinc | |
| 12 | +| Blue/Azure | 200-260 | slate | |
| 13 | +| Violet/Purple | 260-300 | zinc | |
| 14 | +| Magenta/Pink/Rose | 300-360 | neutral | |
| 15 | + |
| 16 | +## Mood and palette guidance |
| 17 | + |
| 18 | +### Color psychology reference |
| 19 | + |
| 20 | +| Mood | Primary Hues | Neutral Family | Characteristics | |
| 21 | +|------|--------------|----------------|-----------------| |
| 22 | +| Professional | Blue, Slate, Indigo | gray, slate | Clean, trustworthy, corporate | |
| 23 | +| Creative | Purple, Pink, Orange | neutral | Innovative, artistic, expressive | |
| 24 | +| Natural | Green, Teal, Brown | stone | Organic, sustainable, calm | |
| 25 | +| Energetic | Orange, Yellow, Red | neutral | Bold, active, attention-grabbing | |
| 26 | +| Luxurious | Gold, Purple, Black | zinc | Premium, elegant, sophisticated | |
| 27 | +| Playful | Pink, Cyan, Yellow | neutral | Fun, youthful, approachable | |
| 28 | +| Tech/Cyber | Cyan, Green, Purple | slate, zinc | Modern, digital, futuristic | |
| 29 | +| Warm | Orange, Amber, Brown | stone | Cozy, inviting, comfortable | |
| 30 | +| Cool | Blue, Teal, Slate | gray, slate | Calm, refreshing, serene | |
| 31 | +| Minimal | Gray, White, Black | gray | Simple, focused, uncluttered | |
| 32 | + |
| 33 | +### Building cohesive palettes |
| 34 | + |
| 35 | +1. Pick a primary: the hero color for buttons, links, CTAs |
| 36 | +2. Choose matching neutrals: warm primaries -> stone/neutral; cool primaries -> gray/slate |
| 37 | +3. Define contrast: bold brands -> high contrast; soft aesthetics -> low contrast |
| 38 | +4. Consider dark mode: primary often shifts lighter; neutrals shift to darker family |
| 39 | + |
| 40 | +### Accessibility and contrast guidelines (WCAG) |
| 41 | + |
| 42 | +Ensure themes meet WCAG 2.1 AA contrast requirements: |
| 43 | + |
| 44 | +| Element | Minimum Ratio | OKLCH Rule of Thumb | |
| 45 | +|---------|---------------|---------------------| |
| 46 | +| Body text on background | 4.5:1 | Lightness difference >= 50% | |
| 47 | +| Large text (18pt+) | 3:1 | Lightness difference >= 40% | |
| 48 | +| UI components (buttons, inputs) | 3:1 | Lightness difference >= 40% | |
| 49 | +| Focus indicators | 3:1 | Use distinct color + lightness | |
| 50 | + |
| 51 | +OKLCH lightness thresholds: |
| 52 | + |
| 53 | +| Context | Light Mode | Dark Mode | |
| 54 | +|---------|------------|-----------| |
| 55 | +| Background | L >= 95% | L <= 25% | |
| 56 | +| Text on light bg | L <= 45% | -- | |
| 57 | +| Text on dark bg | -- | L >= 85% | |
| 58 | +| Primary button text | Check against primary-500/600 | Check against primary-400 | |
| 59 | + |
| 60 | +Readable primary foreground: |
| 61 | +- Most hues (blue, purple, red, orange): use white (L: 100%) |
| 62 | +- Light hues (yellow 50-110 degrees, light cyan 160-195): use dark gray (L <= 20%) |
| 63 | + |
| 64 | +Quick check: If |L_text - L_background| >= 50%, contrast is likely sufficient for body text. |
| 65 | + |
| 66 | +## Palette types |
| 67 | + |
| 68 | +When generating custom themes, there are TWO distinct types of custom color palettes: |
| 69 | + |
| 70 | +| Palette Type | Example Variable | Purpose | Chroma Level | |
| 71 | +|--------------|------------------|---------|--------------| |
| 72 | +| Brand palette | `--color-<name>-*` | Primary/accent colors, buttons, links, CTAs | Vibrant (high chroma) by default | |
| 73 | +| Gray palette | `--color-<name>-gray-*` | Backgrounds, surfaces, borders, dark mode neutrals | Soft (low chroma 0.002-0.035) | |
| 74 | + |
| 75 | +### When to create each palette |
| 76 | + |
| 77 | +ALWAYS create TWO palettes in `@theme inline { }`: |
| 78 | +1. Brand palette (`--color-<name>-*`) for primary/accent colors |
| 79 | +2. Gray palette (`--color-<name>-gray-*`) for backgrounds, surfaces, borders |
| 80 | + |
| 81 | +Both palettes are used in light mode for a cohesive feel. |
| 82 | + |
| 83 | +Dark mode behavior depends on user request: |
| 84 | + |
| 85 | +| User Request | Light Mode Uses | Dark Mode Uses | |
| 86 | +|--------------|-----------------|----------------| |
| 87 | +| "soft rose theme" (default) | Custom gray (`--color-<name>-gray-*`) | Tailwind gray (`zinc`, `stone`, etc.) | |
| 88 | +| "soft rose theme with matching dark mode" | Custom gray (`--color-<name>-gray-*`) | Custom gray (`--color-<name>-gray-*`) | |
| 89 | + |
| 90 | +Trigger phrases for custom dark mode palette: |
| 91 | +- "matching dark mode" |
| 92 | +- "cohesive dark mode" |
| 93 | +- "consistent dark colors" |
| 94 | +- "unified light and dark" |
| 95 | +- "matching neutrals" |
| 96 | + |
| 97 | +If none of these phrases appear -> light mode uses custom gray, dark mode uses Tailwind grays. |
| 98 | + |
| 99 | +### Brand color style (vibrant vs soft) |
| 100 | + |
| 101 | +Brand palettes are vibrant by default (like Tailwind's blue, green, orange). Only reduce chroma if user explicitly requests: |
| 102 | + |
| 103 | +| User Says | Brand Palette Style | Chroma Level | |
| 104 | +|-----------|---------------------|--------------| |
| 105 | +| Default (no modifier) | Vibrant, follow Tailwind color saturation | 0.10-0.20+ | |
| 106 | +| "soft", "muted", "ash", "pastel", "dusty", "desaturated" | Soft, reduced chroma like lavender/khaki | 0.02-0.05 | |
| 107 | + |
| 108 | +Example comparison: |
| 109 | + |
| 110 | +```css |
| 111 | +/* Vibrant brand (default) */ |
| 112 | +--color-<name>-500: oklch(55% 0.14 <hue>); |
| 113 | + |
| 114 | +/* Soft/muted brand (if requested) */ |
| 115 | +--color-<name>-500: oklch(55% 0.04 <hue>); |
| 116 | +``` |
| 117 | + |
| 118 | +## Custom gray palettes (neutral matching) |
| 119 | + |
| 120 | +When a theme benefits from unique neutrals, generate a custom neutral palette that harmonizes with the primary color. These are NOT pure grays; they have subtle warmth or coolness. |
| 121 | + |
| 122 | +### Palette characteristics |
| 123 | + |
| 124 | +| Palette Type | Hue Range | Chroma Range | Use With | |
| 125 | +|--------------|-----------|--------------|----------| |
| 126 | +| Warm neutrals | 60-100 degrees (yellow/brown) | 0.002-0.035 | Orange, amber, brown, gold primaries | |
| 127 | +| Cool neutrals | 200-260 degrees (blue/slate) | 0.002-0.030 | Blue, cyan, teal, indigo primaries | |
| 128 | +| Rose neutrals | 330-360 degrees (pink) | 0.002-0.040 | Pink, rose, magenta primaries | |
| 129 | +| Green neutrals | 120-160 degrees (sage) | 0.002-0.030 | Green, emerald, teal primaries | |
| 130 | + |
| 131 | +### OKLCH pattern for gray palettes (bell curve chroma) |
| 132 | + |
| 133 | +Gray palettes use a bell curve chroma pattern: very low at extremes (light AND dark), peaking at mid-tones. This ensures: |
| 134 | +- Light mode backgrounds (50-200) look clean with subtle tint |
| 135 | +- Dark mode backgrounds (800-950) look sophisticated, not muddy |
| 136 | + |
| 137 | +```css |
| 138 | +--color-<name>-gray-50: oklch(98% 0.002 <hue>); /* Almost neutral */ |
| 139 | +--color-<name>-gray-100: oklch(95.5% 0.004 <hue>); |
| 140 | +--color-<name>-gray-200: oklch(89.7% 0.008 <hue>); |
| 141 | +--color-<name>-gray-300: oklch(82.7% 0.012 <hue>); /* Building up */ |
| 142 | +--color-<name>-gray-400: oklch(73% 0.018 <hue>); /* Approaching peak */ |
| 143 | +--color-<name>-gray-500: oklch(62.5% 0.020 <hue>); /* PEAK chroma */ |
| 144 | +--color-<name>-gray-600: oklch(52.8% 0.016 <hue>); /* Starting to fade */ |
| 145 | +--color-<name>-gray-700: oklch(41.4% 0.012 <hue>); /* Fading */ |
| 146 | +--color-<name>-gray-800: oklch(34.6% 0.008 <hue>); /* Very low */ |
| 147 | +--color-<name>-gray-900: oklch(30.6% 0.005 <hue>); /* Almost neutral */ |
| 148 | +--color-<name>-gray-950: oklch(20.1% 0.003 <hue>); /* Nearly pure dark */ |
| 149 | +``` |
| 150 | + |
| 151 | +Critical: Dark mode backgrounds (800-950) need very low chroma: |
| 152 | + |
| 153 | +| Shade | Chroma | Why | |
| 154 | +|-------|--------|-----| |
| 155 | +| 950 | 0.003 | Dark backgrounds must be nearly neutral | |
| 156 | +| 900 | 0.005 | Avoids muddy/colored appearance | |
| 157 | +| 800 | 0.008 | Just a hint of warmth/coolness | |
| 158 | +| 500 | 0.020 | Peak, midtones carry color identity | |
| 159 | +| 50 | 0.002 | Light backgrounds stay clean | |
| 160 | + |
| 161 | +Key principles: |
| 162 | +- Chroma peaks at mid-tones (400-600), very low at BOTH extremes |
| 163 | +- Dark end (800-950) must have lower chroma than light end for clean dark mode |
| 164 | +- Hue stays consistent across the scale (±5 degrees variation is acceptable) |
| 165 | +- Lightness follows standard 50-950 scale |
| 166 | + |
| 167 | +### Placement of custom palettes |
| 168 | + |
| 169 | +Custom color palettes MUST be defined in the `@theme theme-<name> inline { }` block: |
| 170 | + |
| 171 | +```css |
| 172 | +@theme theme-<name> inline { |
| 173 | + /* Custom neutral palette for this theme */ |
| 174 | + --color-<name>-50: oklch(98% 0.003 88); |
| 175 | + --color-<name>-100: oklch(95.5% 0.005 88); |
| 176 | + /* ... full 50-950 scale ... */ |
| 177 | +} |
| 178 | +``` |
| 179 | + |
| 180 | +Then reference these in the theme selector blocks using `var()`: |
| 181 | + |
| 182 | +```css |
| 183 | +[data-theme="theme-<name>"] { |
| 184 | + --background: var(--color-<name>-50); |
| 185 | + --background-1: var(--color-<name>-100); |
| 186 | + /* ... */ |
| 187 | +} |
| 188 | + |
| 189 | +[data-theme="theme-<name>"].dark { |
| 190 | + --background: var(--color-<name>-950); |
| 191 | + --background-1: var(--color-<name>-900); |
| 192 | + /* ... */ |
| 193 | +} |
| 194 | +``` |
| 195 | + |
| 196 | +### When to create custom palettes |
| 197 | + |
| 198 | +| Scenario | Action | |
| 199 | +|----------|--------| |
| 200 | +| Primary is warm (orange/amber/brown) | Create warm neutral palette OR use `stone` | |
| 201 | +| Primary is cool (blue/cyan/indigo) | Use `slate` or `gray` (usually sufficient) | |
| 202 | +| Primary is unique (gold, khaki, etc.) | Create matching custom neutral palette | |
| 203 | +| User explicitly requests | Always create to match their vision | |
| 204 | +| Theme needs distinctive personality | Create for cohesion | |
| 205 | + |
| 206 | +### Using custom palettes in both modes |
| 207 | + |
| 208 | +Soft gray palettes work seamlessly across light and dark modes: |
| 209 | +- Light mode: use 50-300 for backgrounds, 600-950 for text |
| 210 | +- Dark mode: use 800-950 for backgrounds, 50-300 for text |
| 211 | + |
| 212 | +This creates consistent warmth/coolness across modes while maintaining readability. |
0 commit comments