picasso-skill 1.5.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/picasso.md +14 -2
- package/checklists/pre-ship.md +83 -0
- package/commands/backlog.md +34 -0
- package/commands/variants.md +18 -0
- package/package.json +3 -1
- package/references/accessibility-wcag.md +245 -0
- package/references/anti-patterns.md +184 -0
- package/references/color-and-contrast.md +477 -0
- package/references/component-patterns.md +113 -0
- package/references/conversion-design.md +193 -0
- package/references/data-visualization.md +226 -0
- package/references/depth-and-elevation.md +211 -0
- package/references/design-system.md +176 -0
- package/references/generative-art.md +648 -0
- package/references/interaction-design.md +162 -0
- package/references/modern-css-performance.md +361 -0
- package/references/motion-and-animation.md +267 -0
- package/references/performance-optimization.md +746 -0
- package/references/react-patterns.md +318 -0
- package/references/responsive-design.md +452 -0
- package/references/sensory-design.md +369 -0
- package/references/spatial-design.md +176 -0
- package/references/style-presets.md +502 -0
- package/references/tools-catalog.md +103 -0
- package/references/typography.md +415 -0
- package/references/ux-psychology.md +235 -0
- package/references/ux-writing.md +513 -0
- package/skills/picasso/SKILL.md +58 -2
- package/skills/picasso/references/animation-performance.md +244 -0
- package/skills/picasso/references/brand-and-identity.md +136 -0
- package/skills/picasso/references/code-typography.md +222 -0
- package/skills/picasso/references/color-and-contrast.md +56 -2
- package/skills/picasso/references/dark-mode.md +199 -0
- package/skills/picasso/references/depth-and-elevation.md +211 -0
- package/skills/picasso/references/i18n-visual-patterns.md +177 -0
- package/skills/picasso/references/images-and-media.md +222 -0
- package/skills/picasso/references/loading-and-states.md +258 -0
- package/skills/picasso/references/micro-interactions.md +291 -0
- package/skills/picasso/references/motion-and-animation.md +9 -2
- package/skills/picasso/references/navigation-patterns.md +247 -0
- package/skills/picasso/references/style-presets.md +1 -1
- package/skills/picasso/references/tables-and-forms.md +227 -0
- package/skills/picasso/references/tools-catalog.md +103 -0
- package/skills/picasso/references/typography.md +45 -2
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
# Color and Contrast Reference
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
1. Color Space and Manipulation
|
|
5
|
+
2. Palette Construction
|
|
6
|
+
3. Tinted Neutrals
|
|
7
|
+
4. Dark Mode
|
|
8
|
+
5. Accessibility
|
|
9
|
+
6. CSS Variables Pattern
|
|
10
|
+
7. Curated Color Palettes
|
|
11
|
+
8. Wide Gamut Colors (P3)
|
|
12
|
+
9. `light-dark()` CSS Function
|
|
13
|
+
10. `color-mix()` for Runtime Blending
|
|
14
|
+
11. Common Mistakes
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. Color Space and Manipulation
|
|
19
|
+
|
|
20
|
+
Use OKLCH for perceptually uniform color. Unlike HSL, OKLCH ensures that colors at the same lightness value actually appear equally bright to the human eye.
|
|
21
|
+
|
|
22
|
+
```css
|
|
23
|
+
/* OKLCH: lightness (0-1), chroma (0-0.4), hue (0-360) */
|
|
24
|
+
--accent: oklch(0.65 0.25 25); /* vibrant red-orange */
|
|
25
|
+
--accent-hover: oklch(0.60 0.28 25); /* darker, more saturated */
|
|
26
|
+
--accent-muted: oklch(0.75 0.08 25); /* same hue, much less chroma */
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For programmatic palette generation, adjust lightness for tints/shades, chroma for saturation, and hue for variation. OKLCH makes this predictable.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2. Palette Construction
|
|
34
|
+
|
|
35
|
+
### The 60-30-10 Rule
|
|
36
|
+
- 60% dominant (surface/background)
|
|
37
|
+
- 30% secondary (cards, sections, supporting elements)
|
|
38
|
+
- 10% accent (CTAs, active states, highlights)
|
|
39
|
+
|
|
40
|
+
### Building a Palette
|
|
41
|
+
1. Start with the accent color (the brand or action color)
|
|
42
|
+
2. Derive a surface color: very low chroma version of the accent hue
|
|
43
|
+
3. Build neutral scale: tinted toward the accent hue (never pure gray)
|
|
44
|
+
4. Add a semantic layer: success (green family), warning (amber), error (red), info (blue)
|
|
45
|
+
5. Generate dark mode variants by inverting the lightness scale, not the colors
|
|
46
|
+
|
|
47
|
+
### Token Structure
|
|
48
|
+
```css
|
|
49
|
+
:root {
|
|
50
|
+
/* Surfaces */
|
|
51
|
+
--surface-0: oklch(0.99 0.005 80); /* page background */
|
|
52
|
+
--surface-1: oklch(0.97 0.008 80); /* card background */
|
|
53
|
+
--surface-2: oklch(0.94 0.01 80); /* elevated/hover surface */
|
|
54
|
+
--surface-3: oklch(0.90 0.012 80); /* active/selected surface */
|
|
55
|
+
|
|
56
|
+
/* Text */
|
|
57
|
+
--text-primary: oklch(0.15 0.02 80);
|
|
58
|
+
--text-secondary: oklch(0.40 0.02 80);
|
|
59
|
+
--text-tertiary: oklch(0.55 0.015 80);
|
|
60
|
+
|
|
61
|
+
/* Accent */
|
|
62
|
+
--accent: oklch(0.55 0.25 30);
|
|
63
|
+
--accent-hover: oklch(0.50 0.28 30);
|
|
64
|
+
--accent-subtle: oklch(0.92 0.04 30);
|
|
65
|
+
|
|
66
|
+
/* Borders */
|
|
67
|
+
--border: oklch(0.88 0.01 80);
|
|
68
|
+
--border-strong: oklch(0.78 0.015 80);
|
|
69
|
+
|
|
70
|
+
/* Semantic */
|
|
71
|
+
--success: oklch(0.55 0.18 145);
|
|
72
|
+
--warning: oklch(0.65 0.18 70);
|
|
73
|
+
--error: oklch(0.55 0.22 25);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 3. Tinted Neutrals
|
|
80
|
+
|
|
81
|
+
Never use pure gray (#808080, rgb(128,128,128), etc.). Always tint neutrals toward the dominant hue of the palette. This creates warmth and cohesion.
|
|
82
|
+
|
|
83
|
+
**Warm neutrals** (tinted toward amber/brown): suited for editorial, luxury, organic brands
|
|
84
|
+
**Cool neutrals** (tinted toward blue/slate): suited for tech, data, professional tools
|
|
85
|
+
**Neutral neutrals** (tinted toward the accent hue at very low chroma): the most versatile approach
|
|
86
|
+
|
|
87
|
+
```css
|
|
88
|
+
/* Instead of #333333 */
|
|
89
|
+
--text-primary: oklch(0.25 0.015 260); /* cool-tinted dark */
|
|
90
|
+
|
|
91
|
+
/* Instead of #f5f5f5 */
|
|
92
|
+
--surface-bg: oklch(0.97 0.005 260); /* cool-tinted light */
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 4. Dark Mode
|
|
98
|
+
|
|
99
|
+
Dark mode is not "invert everything." Follow these rules:
|
|
100
|
+
|
|
101
|
+
1. Surface colors get darker but retain their hue tint
|
|
102
|
+
2. Text colors flip but never become pure white (use oklch lightness 0.93-0.97)
|
|
103
|
+
3. Accent colors often need a lightness bump (+0.05 to +0.10) to maintain contrast
|
|
104
|
+
4. Shadows become less visible on dark surfaces; use subtle inner glows or border effects instead
|
|
105
|
+
5. Elevation in dark mode goes lighter (higher surfaces are lighter), opposite of light mode
|
|
106
|
+
6. Images and illustrations may need reduced brightness/contrast (`filter: brightness(0.9)`)
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
[data-theme="dark"] {
|
|
110
|
+
--surface-0: oklch(0.13 0.01 260);
|
|
111
|
+
--surface-1: oklch(0.17 0.012 260);
|
|
112
|
+
--surface-2: oklch(0.21 0.015 260);
|
|
113
|
+
--text-primary: oklch(0.93 0.01 260);
|
|
114
|
+
--text-secondary: oklch(0.70 0.01 260);
|
|
115
|
+
--border: oklch(0.25 0.01 260);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 5. Accessibility
|
|
122
|
+
|
|
123
|
+
### Contrast Requirements (WCAG 2.2)
|
|
124
|
+
- Normal text (<24px or <18.66px bold): 4.5:1 minimum
|
|
125
|
+
- Large text (>=24px or >=18.66px bold): 3:1 minimum
|
|
126
|
+
- UI components and graphical objects: 3:1 minimum
|
|
127
|
+
- Focus indicators: 3:1 against adjacent colors
|
|
128
|
+
|
|
129
|
+
### Testing
|
|
130
|
+
Use OKLCH lightness difference as a quick heuristic: a difference of 0.40+ between text and background lightness values usually passes AA. For precise checking, use the APCA (Advanced Perceptual Contrast Algorithm) when possible, as it better represents human perception than WCAG 2.x contrast ratios.
|
|
131
|
+
|
|
132
|
+
### Color Blindness
|
|
133
|
+
Never use color as the only way to convey information. Pair color with icons, patterns, or text labels. Test palettes with a deuteranopia/protanopia simulator.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 6. CSS Variables Pattern
|
|
138
|
+
|
|
139
|
+
Define all colors as CSS custom properties. Group by function, not by color name.
|
|
140
|
+
|
|
141
|
+
```css
|
|
142
|
+
/* Good: semantic naming */
|
|
143
|
+
--color-surface: ...;
|
|
144
|
+
--color-text: ...;
|
|
145
|
+
--color-accent: ...;
|
|
146
|
+
--color-border: ...;
|
|
147
|
+
|
|
148
|
+
/* Bad: literal naming */
|
|
149
|
+
--blue: ...;
|
|
150
|
+
--dark-gray: ...;
|
|
151
|
+
--light-blue: ...;
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
For component-level overrides:
|
|
155
|
+
```css
|
|
156
|
+
.card {
|
|
157
|
+
--card-bg: var(--surface-1);
|
|
158
|
+
--card-border: var(--border);
|
|
159
|
+
background: var(--card-bg);
|
|
160
|
+
border: 1px solid var(--card-border);
|
|
161
|
+
}
|
|
162
|
+
.card.highlighted {
|
|
163
|
+
--card-bg: var(--accent-subtle);
|
|
164
|
+
--card-border: var(--accent);
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 7. Curated Color Palettes
|
|
171
|
+
|
|
172
|
+
Ten tested OKLCH palettes ready to drop into any project. Each includes a complete token set. Copy the one that fits your domain, then adjust chroma and hue to taste.
|
|
173
|
+
|
|
174
|
+
### 7.1 Warm Terracotta
|
|
175
|
+
**Vibe**: Earthy, grounded, artisanal. Good for lifestyle brands, wellness, real estate, organic products.
|
|
176
|
+
```css
|
|
177
|
+
:root {
|
|
178
|
+
--surface-0: oklch(0.98 0.008 55);
|
|
179
|
+
--surface-1: oklch(0.95 0.012 55);
|
|
180
|
+
--text-primary: oklch(0.18 0.025 55);
|
|
181
|
+
--text-secondary: oklch(0.42 0.02 55);
|
|
182
|
+
--accent: oklch(0.58 0.16 45);
|
|
183
|
+
--accent-hover: oklch(0.52 0.18 45);
|
|
184
|
+
--accent-subtle: oklch(0.93 0.04 45);
|
|
185
|
+
--border: oklch(0.87 0.015 55);
|
|
186
|
+
--success: oklch(0.55 0.16 155);
|
|
187
|
+
--warning: oklch(0.68 0.16 75);
|
|
188
|
+
--error: oklch(0.55 0.20 25);
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 7.2 Forest Green
|
|
193
|
+
**Vibe**: Natural, sustainable, trustworthy. Good for fintech, health, environmental, agriculture.
|
|
194
|
+
```css
|
|
195
|
+
:root {
|
|
196
|
+
--surface-0: oklch(0.98 0.006 145);
|
|
197
|
+
--surface-1: oklch(0.96 0.01 145);
|
|
198
|
+
--text-primary: oklch(0.17 0.03 150);
|
|
199
|
+
--text-secondary: oklch(0.40 0.02 150);
|
|
200
|
+
--accent: oklch(0.52 0.14 155);
|
|
201
|
+
--accent-hover: oklch(0.46 0.16 155);
|
|
202
|
+
--accent-subtle: oklch(0.93 0.04 155);
|
|
203
|
+
--border: oklch(0.88 0.012 145);
|
|
204
|
+
--success: oklch(0.55 0.16 145);
|
|
205
|
+
--warning: oklch(0.66 0.16 80);
|
|
206
|
+
--error: oklch(0.55 0.20 25);
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### 7.3 Amber Gold
|
|
211
|
+
**Vibe**: Premium, confident, optimistic. Good for finance, luxury SaaS, productivity tools.
|
|
212
|
+
```css
|
|
213
|
+
:root {
|
|
214
|
+
--surface-0: oklch(0.99 0.005 85);
|
|
215
|
+
--surface-1: oklch(0.96 0.01 85);
|
|
216
|
+
--text-primary: oklch(0.16 0.02 85);
|
|
217
|
+
--text-secondary: oklch(0.40 0.018 85);
|
|
218
|
+
--accent: oklch(0.68 0.18 75);
|
|
219
|
+
--accent-hover: oklch(0.62 0.20 75);
|
|
220
|
+
--accent-subtle: oklch(0.94 0.04 75);
|
|
221
|
+
--border: oklch(0.88 0.012 85);
|
|
222
|
+
--success: oklch(0.55 0.16 150);
|
|
223
|
+
--warning: oklch(0.68 0.18 75);
|
|
224
|
+
--error: oklch(0.55 0.20 28);
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 7.4 Coral Salmon
|
|
229
|
+
**Vibe**: Warm, energetic, approachable. Good for social apps, creative tools, food and hospitality.
|
|
230
|
+
```css
|
|
231
|
+
:root {
|
|
232
|
+
--surface-0: oklch(0.98 0.006 30);
|
|
233
|
+
--surface-1: oklch(0.96 0.01 30);
|
|
234
|
+
--text-primary: oklch(0.18 0.02 30);
|
|
235
|
+
--text-secondary: oklch(0.42 0.018 30);
|
|
236
|
+
--accent: oklch(0.65 0.20 25);
|
|
237
|
+
--accent-hover: oklch(0.58 0.22 25);
|
|
238
|
+
--accent-subtle: oklch(0.94 0.04 25);
|
|
239
|
+
--border: oklch(0.88 0.012 30);
|
|
240
|
+
--success: oklch(0.55 0.16 150);
|
|
241
|
+
--warning: oklch(0.66 0.16 75);
|
|
242
|
+
--error: oklch(0.52 0.22 20);
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### 7.5 Deep Teal
|
|
247
|
+
**Vibe**: Calm, medical, authoritative. Good for health tech, enterprise SaaS, data platforms, legal.
|
|
248
|
+
```css
|
|
249
|
+
:root {
|
|
250
|
+
--surface-0: oklch(0.98 0.005 195);
|
|
251
|
+
--surface-1: oklch(0.96 0.008 195);
|
|
252
|
+
--text-primary: oklch(0.16 0.025 200);
|
|
253
|
+
--text-secondary: oklch(0.40 0.02 200);
|
|
254
|
+
--accent: oklch(0.52 0.12 195);
|
|
255
|
+
--accent-hover: oklch(0.46 0.14 195);
|
|
256
|
+
--accent-subtle: oklch(0.93 0.03 195);
|
|
257
|
+
--border: oklch(0.88 0.01 195);
|
|
258
|
+
--success: oklch(0.55 0.14 155);
|
|
259
|
+
--warning: oklch(0.66 0.16 75);
|
|
260
|
+
--error: oklch(0.55 0.20 25);
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 7.6 Slate Blue
|
|
265
|
+
**Vibe**: Professional, systematic, dependable. Good for project management, B2B SaaS, documentation.
|
|
266
|
+
```css
|
|
267
|
+
:root {
|
|
268
|
+
--surface-0: oklch(0.98 0.005 250);
|
|
269
|
+
--surface-1: oklch(0.96 0.008 250);
|
|
270
|
+
--text-primary: oklch(0.17 0.02 250);
|
|
271
|
+
--text-secondary: oklch(0.42 0.018 250);
|
|
272
|
+
--accent: oklch(0.55 0.14 250);
|
|
273
|
+
--accent-hover: oklch(0.49 0.16 250);
|
|
274
|
+
--accent-subtle: oklch(0.93 0.03 250);
|
|
275
|
+
--border: oklch(0.88 0.01 250);
|
|
276
|
+
--success: oklch(0.55 0.16 150);
|
|
277
|
+
--warning: oklch(0.66 0.16 75);
|
|
278
|
+
--error: oklch(0.55 0.20 25);
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### 7.7 Burgundy
|
|
283
|
+
**Vibe**: Sophisticated, editorial, rich. Good for wine/food, publishing, luxury, fashion.
|
|
284
|
+
```css
|
|
285
|
+
:root {
|
|
286
|
+
--surface-0: oklch(0.98 0.006 10);
|
|
287
|
+
--surface-1: oklch(0.96 0.01 10);
|
|
288
|
+
--text-primary: oklch(0.16 0.025 10);
|
|
289
|
+
--text-secondary: oklch(0.40 0.02 10);
|
|
290
|
+
--accent: oklch(0.42 0.16 15);
|
|
291
|
+
--accent-hover: oklch(0.36 0.18 15);
|
|
292
|
+
--accent-subtle: oklch(0.93 0.04 15);
|
|
293
|
+
--border: oklch(0.87 0.012 10);
|
|
294
|
+
--success: oklch(0.55 0.16 150);
|
|
295
|
+
--warning: oklch(0.66 0.16 75);
|
|
296
|
+
--error: oklch(0.50 0.20 25);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 7.8 Sage
|
|
301
|
+
**Vibe**: Soft, organic, restorative. Good for wellness, meditation, journaling, therapy platforms.
|
|
302
|
+
```css
|
|
303
|
+
:root {
|
|
304
|
+
--surface-0: oklch(0.98 0.006 130);
|
|
305
|
+
--surface-1: oklch(0.95 0.012 130);
|
|
306
|
+
--text-primary: oklch(0.20 0.02 130);
|
|
307
|
+
--text-secondary: oklch(0.42 0.018 130);
|
|
308
|
+
--accent: oklch(0.58 0.10 130);
|
|
309
|
+
--accent-hover: oklch(0.52 0.12 130);
|
|
310
|
+
--accent-subtle: oklch(0.93 0.03 130);
|
|
311
|
+
--border: oklch(0.88 0.01 130);
|
|
312
|
+
--success: oklch(0.55 0.14 150);
|
|
313
|
+
--warning: oklch(0.66 0.15 75);
|
|
314
|
+
--error: oklch(0.55 0.18 25);
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### 7.9 Charcoal with Orange Accent
|
|
319
|
+
**Vibe**: Bold, industrial, high-contrast. Good for dev tools, gaming, analytics, creative coding.
|
|
320
|
+
```css
|
|
321
|
+
:root {
|
|
322
|
+
--surface-0: oklch(0.97 0.003 60);
|
|
323
|
+
--surface-1: oklch(0.94 0.005 60);
|
|
324
|
+
--text-primary: oklch(0.15 0.01 60);
|
|
325
|
+
--text-secondary: oklch(0.40 0.01 60);
|
|
326
|
+
--accent: oklch(0.65 0.22 55);
|
|
327
|
+
--accent-hover: oklch(0.58 0.24 55);
|
|
328
|
+
--accent-subtle: oklch(0.94 0.04 55);
|
|
329
|
+
--border: oklch(0.86 0.008 60);
|
|
330
|
+
--success: oklch(0.55 0.16 150);
|
|
331
|
+
--warning: oklch(0.66 0.18 70);
|
|
332
|
+
--error: oklch(0.55 0.22 25);
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### 7.10 Monochrome Black and White
|
|
337
|
+
**Vibe**: Stark, typographic, gallery-like. Good for portfolios, photography, editorial, minimal SaaS.
|
|
338
|
+
```css
|
|
339
|
+
:root {
|
|
340
|
+
--surface-0: oklch(0.99 0.000 0);
|
|
341
|
+
--surface-1: oklch(0.96 0.000 0);
|
|
342
|
+
--text-primary: oklch(0.13 0.000 0);
|
|
343
|
+
--text-secondary: oklch(0.45 0.000 0);
|
|
344
|
+
--accent: oklch(0.15 0.000 0);
|
|
345
|
+
--accent-hover: oklch(0.25 0.000 0);
|
|
346
|
+
--accent-subtle: oklch(0.93 0.000 0);
|
|
347
|
+
--border: oklch(0.85 0.000 0);
|
|
348
|
+
--success: oklch(0.50 0.14 150);
|
|
349
|
+
--warning: oklch(0.62 0.14 75);
|
|
350
|
+
--error: oklch(0.50 0.18 25);
|
|
351
|
+
}
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
For the monochrome palette, the accent is near-black. CTAs rely on fill weight (solid black buttons with white text) rather than color. Semantic colors (success, warning, error) break the monochrome intentionally so they remain functional.
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## 8. Wide Gamut Colors (P3)
|
|
359
|
+
|
|
360
|
+
### What is Display P3?
|
|
361
|
+
Display P3 is a color space that covers roughly 25% more visible colors than sRGB. Modern Apple devices, most OLED screens, and recent monitors support it. Colors outside the sRGB gamut appear more vivid without being oversaturated.
|
|
362
|
+
|
|
363
|
+
### CSS Syntax
|
|
364
|
+
```css
|
|
365
|
+
/* Display P3 via color() function */
|
|
366
|
+
--accent: color(display-p3 0.92 0.34 0.15); /* vivid orange impossible in sRGB */
|
|
367
|
+
--success: color(display-p3 0.18 0.75 0.35); /* richer green */
|
|
368
|
+
--highlight: color(display-p3 1 0.85 0); /* pure P3 yellow */
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### Feature Detection
|
|
372
|
+
```css
|
|
373
|
+
@media (color-gamut: p3) {
|
|
374
|
+
:root {
|
|
375
|
+
--accent: color(display-p3 0.92 0.34 0.15);
|
|
376
|
+
--success: color(display-p3 0.18 0.75 0.35);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Progressive Enhancement Pattern
|
|
382
|
+
Always define an sRGB fallback first, then override for wide gamut displays. This ensures every screen gets a reasonable color.
|
|
383
|
+
|
|
384
|
+
```css
|
|
385
|
+
:root {
|
|
386
|
+
/* sRGB fallback (works everywhere) */
|
|
387
|
+
--accent: oklch(0.65 0.22 35);
|
|
388
|
+
--success: oklch(0.55 0.18 150);
|
|
389
|
+
--highlight: oklch(0.82 0.18 90);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
@media (color-gamut: p3) {
|
|
393
|
+
:root {
|
|
394
|
+
/* P3 override (wider gamut screens) */
|
|
395
|
+
--accent: oklch(0.65 0.27 35); /* push chroma beyond sRGB limit */
|
|
396
|
+
--success: oklch(0.55 0.22 150);
|
|
397
|
+
--highlight: oklch(0.82 0.22 90);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Note: OKLCH values automatically map to the widest gamut the browser and display support. Increasing chroma beyond ~0.15-0.20 (depending on hue) often pushes into P3 territory. This makes OKLCH the ideal space for progressive enhancement because you write one value and the browser resolves it to the best available gamut.
|
|
403
|
+
|
|
404
|
+
### When to Use P3
|
|
405
|
+
- Hero gradients and accent splashes where vibrancy matters
|
|
406
|
+
- Success/error states that need to "pop" on capable screens
|
|
407
|
+
- Brand colors that were designed in P3 (increasingly common)
|
|
408
|
+
- Image overlays and tinted surfaces that blend with wide-gamut photography
|
|
409
|
+
|
|
410
|
+
### When NOT to Use P3
|
|
411
|
+
- Body text colors (perceptual difference is negligible)
|
|
412
|
+
- Border and surface tokens (subtle differences, not worth the complexity)
|
|
413
|
+
- Any context where the sRGB version already looks correct
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## 9. `light-dark()` CSS Function
|
|
418
|
+
|
|
419
|
+
The `light-dark()` function returns one of two values depending on the current `color-scheme`. This eliminates the need for duplicate variable declarations in many cases:
|
|
420
|
+
|
|
421
|
+
```css
|
|
422
|
+
:root {
|
|
423
|
+
color-scheme: light dark;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.surface {
|
|
427
|
+
background: light-dark(oklch(0.97 0.005 260), oklch(0.17 0.012 260));
|
|
428
|
+
}
|
|
429
|
+
.text {
|
|
430
|
+
color: light-dark(oklch(0.20 0.015 260), oklch(0.93 0.01 260));
|
|
431
|
+
}
|
|
432
|
+
.border {
|
|
433
|
+
border-color: light-dark(oklch(0.88 0.01 260), oklch(0.25 0.01 260));
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
Use `light-dark()` for simple color flips (surfaces, text, borders). For complex theme differences (shadow systems, accent adjustments, chroma changes), continue using `[data-theme="dark"]` selectors or CSS custom properties for full control.
|
|
438
|
+
|
|
439
|
+
Browser support: baseline since March 2024 (Chrome 123, Firefox 120, Safari 17.5).
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## 10. `color-mix()` for Runtime Blending
|
|
444
|
+
|
|
445
|
+
`color-mix()` blends two colors at runtime without defining intermediate tokens. Useful for hover states, tinted surfaces, and dynamic theming:
|
|
446
|
+
|
|
447
|
+
```css
|
|
448
|
+
/* Hover: darken accent by mixing with black */
|
|
449
|
+
.btn:hover {
|
|
450
|
+
background: color-mix(in oklch, var(--accent), black 15%);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/* Subtle tint: mix accent into white */
|
|
454
|
+
.surface-tinted {
|
|
455
|
+
background: color-mix(in oklch, var(--accent), white 92%);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/* Disabled: reduce opacity feel by mixing with the surface */
|
|
459
|
+
.btn:disabled {
|
|
460
|
+
background: color-mix(in oklch, var(--accent), var(--surface-0) 60%);
|
|
461
|
+
}
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Always specify `in oklch` for perceptually uniform blending. Mixing `in srgb` produces muddier results, especially across hues.
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
## 11. Common Mistakes
|
|
469
|
+
|
|
470
|
+
- Using pure black (#000) for text (use tinted near-black instead)
|
|
471
|
+
- Using gray text on colored backgrounds (low contrast, hard to read)
|
|
472
|
+
- Applying opacity to achieve lighter colors (makes elements look washed out; use chroma reduction instead)
|
|
473
|
+
- Using too many accent colors (one primary accent, one secondary maximum)
|
|
474
|
+
- Forgetting to test dark mode after building light mode
|
|
475
|
+
- Using brand colors at full saturation for large surfaces (they vibrate and cause eye strain; reserve full chroma for small accents)
|
|
476
|
+
- Not providing hover/focus states with visible color change
|
|
477
|
+
- Using `color-mix(in srgb, ...)` instead of `color-mix(in oklch, ...)` (sRGB blending produces muddier, less predictable results)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Component Patterns Reference
|
|
2
|
+
|
|
3
|
+
Standard component taxonomy, naming conventions, and state patterns drawn from 90+ real-world design systems and 2,500+ implementations (sourced from component.gallery).
|
|
4
|
+
|
|
5
|
+
## Standard Component Names
|
|
6
|
+
|
|
7
|
+
Use these names consistently. When building a component, check this list first. Do not invent new names for solved patterns.
|
|
8
|
+
|
|
9
|
+
### Navigation
|
|
10
|
+
- **Navbar / Navigation Bar**: Top-level site navigation. Contains logo, links, actions.
|
|
11
|
+
- **Sidebar / Side Navigation**: Vertical navigation panel, typically on the left.
|
|
12
|
+
- **Breadcrumb**: Shows the user's location in a hierarchy. e.g., Home > Products > Shoes.
|
|
13
|
+
- **Tabs**: Horizontal set of toggles for switching between views within a section.
|
|
14
|
+
- **Pagination**: Controls for navigating between pages of content.
|
|
15
|
+
- **Bottom Navigation / Tab Bar**: Mobile-only bottom navigation with 3-5 icon+label items.
|
|
16
|
+
- **Menu / Dropdown Menu**: A list of options revealed on click, typically from a button.
|
|
17
|
+
- **Command Palette / Command Menu**: Keyboard-driven search-and-action overlay (Cmd+K pattern).
|
|
18
|
+
|
|
19
|
+
### Content
|
|
20
|
+
- **Card**: A bounded container for a unit of content (image, title, description, action).
|
|
21
|
+
- **Accordion / Disclosure**: Expandable/collapsible sections in a vertical stack.
|
|
22
|
+
- **Carousel / Slider**: Multiple slides navigated via swipe, scroll, or buttons.
|
|
23
|
+
- **Table / Data Table**: Structured rows and columns for tabular data.
|
|
24
|
+
- **List / List Item**: Ordered or unordered vertical sequence of items.
|
|
25
|
+
- **Tree View**: Nested hierarchical content (file explorer, category browser).
|
|
26
|
+
- **Timeline**: Chronological sequence of events.
|
|
27
|
+
- **Empty State**: Placeholder shown when a section has no content yet.
|
|
28
|
+
|
|
29
|
+
### Input
|
|
30
|
+
- **Text Input / Text Field**: Single-line text entry.
|
|
31
|
+
- **Textarea**: Multi-line text entry.
|
|
32
|
+
- **Select / Dropdown**: Choose one option from a list.
|
|
33
|
+
- **Combobox / Autocomplete**: Text input with filtered dropdown suggestions.
|
|
34
|
+
- **Checkbox**: Binary on/off selection (multiple selections allowed).
|
|
35
|
+
- **Radio / Radio Group**: Select exactly one option from a set.
|
|
36
|
+
- **Toggle / Switch**: Binary on/off with immediate effect (no form submission needed).
|
|
37
|
+
- **Slider / Range**: Select a value within a numeric range by dragging.
|
|
38
|
+
- **Date Picker**: Calendar-based date selection.
|
|
39
|
+
- **File Upload**: Interface for selecting and uploading files.
|
|
40
|
+
- **Search Input**: Text input with search semantics (clear button, submit on enter).
|
|
41
|
+
|
|
42
|
+
### Feedback
|
|
43
|
+
- **Alert / Banner**: Non-interactive message at the top of a page or section.
|
|
44
|
+
- **Toast / Snackbar**: Temporary notification that auto-dismisses. Bottom of screen.
|
|
45
|
+
- **Modal / Dialog**: Overlay requiring user attention before returning to the page.
|
|
46
|
+
- **Popover**: Small overlay anchored to a trigger element, often for contextual info.
|
|
47
|
+
- **Tooltip**: Brief label shown on hover/focus, never interactive.
|
|
48
|
+
- **Progress Bar**: Linear indicator of completion (determinate or indeterminate).
|
|
49
|
+
- **Spinner / Loading Indicator**: Circular animation indicating a pending operation.
|
|
50
|
+
- **Skeleton / Placeholder**: Gray shapes matching expected content layout during load.
|
|
51
|
+
- **Badge / Tag / Chip**: Small label for status, category, or count.
|
|
52
|
+
|
|
53
|
+
### Actions
|
|
54
|
+
- **Button**: Primary interactive element for triggering actions.
|
|
55
|
+
- **Icon Button**: Button with only an icon (must have aria-label).
|
|
56
|
+
- **Button Group**: Set of related buttons displayed together.
|
|
57
|
+
- **Floating Action Button (FAB)**: Prominent circular button for the primary action (mobile).
|
|
58
|
+
- **Link / Anchor**: Navigation to another page or resource.
|
|
59
|
+
|
|
60
|
+
### Layout
|
|
61
|
+
- **Container**: Max-width wrapper centering content on the page.
|
|
62
|
+
- **Divider / Separator**: Visual line separating content sections.
|
|
63
|
+
- **Grid**: Multi-column layout system.
|
|
64
|
+
- **Stack**: Vertical or horizontal arrangement with consistent spacing.
|
|
65
|
+
- **Aspect Ratio**: Container maintaining a fixed width:height ratio.
|
|
66
|
+
|
|
67
|
+
## Component State Matrix
|
|
68
|
+
|
|
69
|
+
Every interactive component needs these states defined:
|
|
70
|
+
|
|
71
|
+
| State | Visual Treatment |
|
|
72
|
+
|---|---|
|
|
73
|
+
| Default | Base appearance |
|
|
74
|
+
| Hover | Subtle change: background lightens/darkens, cursor changes |
|
|
75
|
+
| Focus | High-contrast outline (2px accent, 2px offset) |
|
|
76
|
+
| Active / Pressed | Slight scale-down (0.97-0.98), darkened background |
|
|
77
|
+
| Disabled | 50% opacity, cursor: not-allowed, no hover/focus effects |
|
|
78
|
+
| Loading | Spinner or skeleton replacing content, pointer-events: none |
|
|
79
|
+
| Error | Error-colored border, inline error message |
|
|
80
|
+
| Selected / Active | Accent background or border, checkmark indicator |
|
|
81
|
+
| Dragging | Elevated shadow, slight rotation, reduced opacity on source |
|
|
82
|
+
|
|
83
|
+
## Compound Component Pattern
|
|
84
|
+
|
|
85
|
+
For components with multiple sub-parts, use the dot notation compound pattern:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
<Dialog>
|
|
89
|
+
<Dialog.Trigger>Open</Dialog.Trigger>
|
|
90
|
+
<Dialog.Content>
|
|
91
|
+
<Dialog.Title>Confirm</Dialog.Title>
|
|
92
|
+
<Dialog.Description>Are you sure?</Dialog.Description>
|
|
93
|
+
<Dialog.Footer>
|
|
94
|
+
<Dialog.Close>Cancel</Dialog.Close>
|
|
95
|
+
<Button>Confirm</Button>
|
|
96
|
+
</Dialog.Footer>
|
|
97
|
+
</Dialog.Content>
|
|
98
|
+
</Dialog>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
This pattern appears in: Radix UI, shadcn/ui, Headless UI, Reach UI, Ark UI.
|
|
102
|
+
|
|
103
|
+
## Component Sizing Convention
|
|
104
|
+
|
|
105
|
+
Use a consistent sizing scale across all components:
|
|
106
|
+
|
|
107
|
+
| Size | Height | Font Size | Padding | Use Case |
|
|
108
|
+
|---|---|---|---|---|
|
|
109
|
+
| xs | 28px | 12px | 4px 8px | Dense UIs, inline tags |
|
|
110
|
+
| sm | 32px | 13px | 6px 12px | Secondary actions, compact forms |
|
|
111
|
+
| md | 40px | 14px | 8px 16px | Default for most components |
|
|
112
|
+
| lg | 48px | 16px | 12px 24px | Primary actions, hero sections |
|
|
113
|
+
| xl | 56px | 18px | 16px 32px | Landing page CTAs |
|