@trishchuk/coolors-mcp 1.0.0 → 1.1.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/.github/ISSUE_TEMPLATE/bug_report.md +20 -8
- package/.github/ISSUE_TEMPLATE/feature_request.md +22 -8
- package/.github/pull_request_template.md +33 -8
- package/.github/workflows/ci.yml +107 -104
- package/.github/workflows/deploy-docs.yml +14 -11
- package/.github/workflows/release.yml +25 -23
- package/README.md +149 -15
- package/dist/bin/server.js +997 -256
- package/dist/bin/server.js.map +1 -1
- package/dist/{chunk-P3ARRKLS.js → chunk-HOMDMKUY.js} +3 -1
- package/dist/{chunk-P3ARRKLS.js.map → chunk-HOMDMKUY.js.map} +1 -1
- package/dist/{chunk-IQ7NN26V.js → chunk-LHW2ZTOU.js} +14 -2
- package/dist/chunk-LHW2ZTOU.js.map +1 -0
- package/dist/color/index.js +1 -1
- package/dist/coolors-mcp.d.ts +4 -4
- package/dist/coolors-mcp.js +1 -1
- package/docs/.vitepress/components/ClientGrid.vue +9 -3
- package/docs/.vitepress/components/CodeBlock.vue +51 -44
- package/docs/.vitepress/components/ConfigModal.vue +151 -67
- package/docs/.vitepress/components/DiagramModal.vue +186 -154
- package/docs/.vitepress/components/TroubleshootingModal.vue +101 -96
- package/docs/.vitepress/config.js +171 -141
- package/docs/.vitepress/theme/FundingLayout.vue +65 -54
- package/docs/.vitepress/theme/Layout.vue +21 -21
- package/docs/.vitepress/theme/components/AdBanner.vue +73 -52
- package/docs/.vitepress/theme/components/AdPlaceholder.vue +3 -3
- package/docs/.vitepress/theme/components/FundingEffects.vue +77 -53
- package/docs/.vitepress/theme/components/FundingHero.vue +78 -63
- package/docs/.vitepress/theme/components/SupportSection.vue +106 -89
- package/docs/.vitepress/theme/custom-app.css +19 -12
- package/docs/.vitepress/theme/custom.css +33 -25
- package/docs/.vitepress/theme/index.js +19 -16
- package/docs/concepts/accessibility.md +59 -47
- package/docs/concepts/color-spaces.md +28 -6
- package/docs/concepts/distance-metrics.md +45 -30
- package/docs/concepts/hct.md +30 -27
- package/docs/concepts/image-analysis.md +52 -21
- package/docs/concepts/material-design.md +43 -17
- package/docs/concepts/theme-matching.md +64 -40
- package/docs/examples/basic-colors.md +92 -108
- package/docs/examples/creating-themes.md +104 -108
- package/docs/examples/css-refactoring.md +33 -29
- package/docs/examples/image-extraction.md +145 -138
- package/docs/getting-started.md +45 -34
- package/docs/index.md +5 -1
- package/docs/installation.md +15 -1
- package/docs/tools/accessibility.md +74 -68
- package/docs/tools/image-extraction.md +62 -54
- package/docs/tools/theme-matching.md +45 -42
- package/eslint.config.ts +13 -0
- package/jsr.json +1 -1
- package/package.json +17 -13
- package/src/bin/server.ts +13 -1
- package/src/color/__tests__/extract-colors.test.ts +20 -30
- package/src/color/apca.ts +105 -0
- package/src/color/color-blindness.ts +109 -0
- package/src/coolors-mcp.ts +1 -1
- package/src/session.ts +10 -2
- package/src/theme/matcher.ts +1 -1
- package/src/theme/refactor.ts +1 -1
- package/src/theme/types.ts +3 -0
- package/src/tools/__tests__/cohesion.test.ts +97 -0
- package/src/tools/__tests__/color-blindness.test.ts +45 -0
- package/src/tools/__tests__/color-conversion.test.ts +38 -0
- package/src/tools/__tests__/contrast-checker.test.ts +56 -0
- package/src/tools/__tests__/palette-export.test.ts +54 -0
- package/src/tools/adjust-color.tool.ts +80 -0
- package/src/tools/cohesion.tools.ts +380 -0
- package/src/tools/color-blindness.tool.ts +168 -0
- package/src/tools/color-conversion.tool.ts +1 -1
- package/src/tools/contrast-checker.tool.ts +53 -14
- package/src/tools/dislike-analyzer.tool.ts +41 -54
- package/src/tools/image-extraction.tools.ts +62 -115
- package/src/tools/index.ts +15 -2
- package/src/tools/palette-export.tool.ts +174 -0
- package/src/tools/palette-with-locks.tool.ts +8 -6
- package/src/types.ts +2 -3
- package/tsconfig.json +12 -2
- package/vitest.config.js +1 -3
- package/.claude/settings.local.json +0 -39
- package/.env +0 -2
- package/.mcp.json +0 -12
- package/CLAUDE.md +0 -201
- package/DOCUMENTATION.md +0 -274
- package/GEMINI.md +0 -54
- package/demo/content_based_color.png +0 -0
- package/demo/music-player.html +0 -621
- package/demo/podcast-player.html +0 -903
- package/dist/chunk-IQ7NN26V.js.map +0 -1
- package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js +0 -93
- package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js.map +0 -7
- package/docs/.vitepress/cache/deps/_metadata.json +0 -127
- package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js +0 -9
- package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js.map +0 -7
- package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js +0 -12683
- package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js.map +0 -7
- package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js +0 -9719
- package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js.map +0 -7
- package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js +0 -4710
- package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js.map +0 -7
- package/docs/.vitepress/cache/deps/cytoscape.js +0 -30278
- package/docs/.vitepress/cache/deps/cytoscape.js.map +0 -7
- package/docs/.vitepress/cache/deps/dayjs.js +0 -285
- package/docs/.vitepress/cache/deps/dayjs.js.map +0 -7
- package/docs/.vitepress/cache/deps/debug.js +0 -468
- package/docs/.vitepress/cache/deps/debug.js.map +0 -7
- package/docs/.vitepress/cache/deps/package.json +0 -3
- package/docs/.vitepress/cache/deps/prismjs.js +0 -1466
- package/docs/.vitepress/cache/deps/prismjs.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js +0 -228
- package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js +0 -142
- package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js +0 -27
- package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js +0 -65
- package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js +0 -53
- package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js.map +0 -7
- package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js +0 -73
- package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -4507
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -584
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +0 -1146
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +0 -1667
- package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +0 -7
- package/docs/.vitepress/cache/deps/vitepress___minisearch.js +0 -1814
- package/docs/.vitepress/cache/deps/vitepress___minisearch.js.map +0 -7
- package/docs/.vitepress/cache/deps/vue.js +0 -344
- package/docs/.vitepress/cache/deps/vue.js.map +0 -7
- package/examples/theme-matching.md +0 -113
- package/mcp-config.json +0 -8
- package/note.md +0 -35
- package/research_results.md +0 -53
- package/src/tools/colors.ts +0 -31
- package/src/tools/registry.ts +0 -142
- package/src/tools/simple-tools.ts +0 -37
|
@@ -37,7 +37,7 @@ Intuitive color model for human understanding.
|
|
|
37
37
|
}
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
## LAB (CIE L*a*b
|
|
40
|
+
## LAB (CIE L*a*b\*)
|
|
41
41
|
|
|
42
42
|
Perceptually uniform color space based on human vision.
|
|
43
43
|
|
|
@@ -104,33 +104,38 @@ HSL ↔ RGB ↔ HEX
|
|
|
104
104
|
const hex = "#6366F1";
|
|
105
105
|
|
|
106
106
|
// To RGB
|
|
107
|
-
"rgb(99, 102, 241)"
|
|
107
|
+
("rgb(99, 102, 241)");
|
|
108
108
|
|
|
109
109
|
// To HSL
|
|
110
|
-
"hsl(239, 84%, 67%)"
|
|
110
|
+
("hsl(239, 84%, 67%)");
|
|
111
111
|
|
|
112
112
|
// To LAB
|
|
113
|
-
"lab(47.9, 35.2, -65.7)"
|
|
113
|
+
("lab(47.9, 35.2, -65.7)");
|
|
114
114
|
|
|
115
115
|
// To HCT
|
|
116
|
-
"hct(265.8, 87.2, 47.9)"
|
|
116
|
+
("hct(265.8, 87.2, 47.9)");
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
## Choosing the Right Color Space
|
|
120
120
|
|
|
121
121
|
### For Color Picking
|
|
122
|
+
|
|
122
123
|
Use **HSL** - intuitive for users to understand and manipulate.
|
|
123
124
|
|
|
124
125
|
### For Color Matching
|
|
126
|
+
|
|
125
127
|
Use **LAB** or **HCT** - perceptually uniform for accurate comparisons.
|
|
126
128
|
|
|
127
129
|
### For UI Themes
|
|
130
|
+
|
|
128
131
|
Use **HCT** - designed for interface design with predictable contrast.
|
|
129
132
|
|
|
130
133
|
### For Web/Digital
|
|
134
|
+
|
|
131
135
|
Use **RGB/Hex** - native format for browsers and displays.
|
|
132
136
|
|
|
133
137
|
### For Print
|
|
138
|
+
|
|
134
139
|
Use **LAB** - device-independent and accurate for print reproduction.
|
|
135
140
|
|
|
136
141
|
## Perceptual Distance Metrics
|
|
@@ -138,42 +143,53 @@ Use **LAB** - device-independent and accurate for print reproduction.
|
|
|
138
143
|
Different color spaces affect distance calculations:
|
|
139
144
|
|
|
140
145
|
### RGB Distance (Euclidean)
|
|
146
|
+
|
|
141
147
|
Simple but perceptually inaccurate:
|
|
148
|
+
|
|
142
149
|
```
|
|
143
150
|
distance = √((r₂-r₁)² + (g₂-g₁)² + (b₂-b₁)²)
|
|
144
151
|
```
|
|
145
152
|
|
|
146
153
|
### Delta E (LAB-based)
|
|
154
|
+
|
|
147
155
|
Industry standard for color difference:
|
|
156
|
+
|
|
148
157
|
- **Delta E 76**: Original formula
|
|
149
158
|
- **Delta E 94**: Improved for textiles
|
|
150
159
|
- **Delta E 2000**: Most accurate, accounts for human perception
|
|
151
160
|
|
|
152
161
|
### HCT Distance
|
|
162
|
+
|
|
153
163
|
Weighted for UI applications:
|
|
164
|
+
|
|
154
165
|
```
|
|
155
166
|
distance = √((h₂-h₁)² + (c₂-c₁)² + 2×(t₂-t₁)²)
|
|
156
167
|
```
|
|
168
|
+
|
|
157
169
|
Tone is weighted 2x because lightness differences are more noticeable in UI.
|
|
158
170
|
|
|
159
171
|
## Color Space Limitations
|
|
160
172
|
|
|
161
173
|
### RGB Limitations
|
|
174
|
+
|
|
162
175
|
- Not perceptually uniform
|
|
163
176
|
- Difficult for humans to predict color changes
|
|
164
177
|
- Poor for color difference calculations
|
|
165
178
|
|
|
166
179
|
### HSL Limitations
|
|
180
|
+
|
|
167
181
|
- Saturation and lightness are not perceptually uniform
|
|
168
182
|
- Colors with same L value may appear different brightness
|
|
169
183
|
- Not suitable for accessibility calculations
|
|
170
184
|
|
|
171
185
|
### LAB Limitations
|
|
186
|
+
|
|
172
187
|
- Can represent impossible colors
|
|
173
188
|
- Less intuitive for designers
|
|
174
189
|
- Blue region has known inaccuracies
|
|
175
190
|
|
|
176
191
|
### HCT Advantages
|
|
192
|
+
|
|
177
193
|
- Specifically designed for UI/UX
|
|
178
194
|
- Predictable contrast ratios
|
|
179
195
|
- Perceptually uniform
|
|
@@ -182,7 +198,9 @@ Tone is weighted 2x because lightness differences are more noticeable in UI.
|
|
|
182
198
|
## Practical Applications
|
|
183
199
|
|
|
184
200
|
### Theme Generation
|
|
201
|
+
|
|
185
202
|
HCT enables predictable theme generation:
|
|
203
|
+
|
|
186
204
|
```javascript
|
|
187
205
|
// Generate accessible color variations
|
|
188
206
|
const baseHCT = { h: 265, c: 50, t: 50 };
|
|
@@ -195,13 +213,17 @@ const dark = { ...baseHCT, t: 20 };
|
|
|
195
213
|
```
|
|
196
214
|
|
|
197
215
|
### Color Harmonies
|
|
216
|
+
|
|
198
217
|
Different spaces excel at different harmonies:
|
|
218
|
+
|
|
199
219
|
- **HSL**: Best for analogous colors (rotate hue)
|
|
200
220
|
- **HCT**: Best for tonal variations (adjust tone)
|
|
201
221
|
- **LAB**: Best for perceptual interpolation
|
|
202
222
|
|
|
203
223
|
### Gradient Generation
|
|
224
|
+
|
|
204
225
|
Color space affects gradient smoothness:
|
|
226
|
+
|
|
205
227
|
- **RGB**: Can produce muddy colors in middle
|
|
206
228
|
- **HSL**: Can produce unnatural brightness shifts
|
|
207
229
|
- **LAB/HCT**: Smooth perceptual transitions
|
|
@@ -219,4 +241,4 @@ Color space affects gradient smoothness:
|
|
|
219
241
|
- [HCT Color System](./hct.md) - Deep dive into HCT
|
|
220
242
|
- [Material Design](./material-design.md) - Using HCT in practice
|
|
221
243
|
- [Accessibility](./accessibility.md) - Color contrast and WCAG
|
|
222
|
-
- [Theme Matching](./theme-matching.md) - Algorithm details
|
|
244
|
+
- [Theme Matching](./theme-matching.md) - Algorithm details
|
|
@@ -17,16 +17,19 @@ distance = √((r₂-r₁)² + (g₂-g₁)² + (b₂-b₁)²)
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
**Pros:**
|
|
20
|
+
|
|
20
21
|
- Fast to compute
|
|
21
22
|
- Simple to understand
|
|
22
23
|
- Good for rough comparisons
|
|
23
24
|
|
|
24
25
|
**Cons:**
|
|
26
|
+
|
|
25
27
|
- Not perceptually uniform
|
|
26
28
|
- Poor for subtle color differences
|
|
27
29
|
- Doesn't match human vision
|
|
28
30
|
|
|
29
31
|
**When to use:**
|
|
32
|
+
|
|
30
33
|
- Quick filtering
|
|
31
34
|
- Performance-critical applications
|
|
32
35
|
- When accuracy isn't crucial
|
|
@@ -40,11 +43,13 @@ The original perceptual color difference formula using LAB color space:
|
|
|
40
43
|
```
|
|
41
44
|
|
|
42
45
|
**Characteristics:**
|
|
46
|
+
|
|
43
47
|
- First attempt at perceptual uniformity
|
|
44
48
|
- Simple LAB distance calculation
|
|
45
49
|
- Threshold: ΔE < 2.3 is barely perceptible
|
|
46
50
|
|
|
47
51
|
**When to use:**
|
|
52
|
+
|
|
48
53
|
- Basic perceptual matching
|
|
49
54
|
- Legacy systems
|
|
50
55
|
- When computation speed matters
|
|
@@ -58,11 +63,13 @@ Improved formula with weighting factors for different color attributes:
|
|
|
58
63
|
```
|
|
59
64
|
|
|
60
65
|
**Improvements:**
|
|
66
|
+
|
|
61
67
|
- Separate weights for lightness, chroma, hue
|
|
62
68
|
- Better for textiles and graphics
|
|
63
69
|
- More accurate than CIE76
|
|
64
70
|
|
|
65
71
|
**When to use:**
|
|
72
|
+
|
|
66
73
|
- Textile industry
|
|
67
74
|
- Graphic arts
|
|
68
75
|
- Better accuracy than CIE76
|
|
@@ -77,12 +84,14 @@ The most accurate standard for color difference, addressing perceptual non-unifo
|
|
|
77
84
|
```
|
|
78
85
|
|
|
79
86
|
**Features:**
|
|
87
|
+
|
|
80
88
|
- Rotation term for blue region
|
|
81
89
|
- Lightness, chroma, hue corrections
|
|
82
90
|
- Most accurate for human perception
|
|
83
91
|
- Industry standard
|
|
84
92
|
|
|
85
93
|
**When to use:**
|
|
94
|
+
|
|
86
95
|
- Color matching applications
|
|
87
96
|
- Quality control
|
|
88
97
|
- When accuracy is paramount
|
|
@@ -98,11 +107,13 @@ distance = √((Δh × wₕ)² + (Δc × wᴄ)² + (Δt × wᴛ)²)
|
|
|
98
107
|
```
|
|
99
108
|
|
|
100
109
|
**Advantages:**
|
|
110
|
+
|
|
101
111
|
- Optimized for UI colors
|
|
102
112
|
- Tone component predicts contrast
|
|
103
113
|
- Better for Material Design
|
|
104
114
|
|
|
105
115
|
**When to use:**
|
|
116
|
+
|
|
106
117
|
- UI/UX design
|
|
107
118
|
- Material Design systems
|
|
108
119
|
- Theme matching
|
|
@@ -112,14 +123,14 @@ distance = √((Δh × wₕ)² + (Δc × wᴄ)² + (Δt × wᴛ)²)
|
|
|
112
123
|
|
|
113
124
|
Different ΔE values represent different levels of color difference:
|
|
114
125
|
|
|
115
|
-
| ΔE Value | Perception
|
|
116
|
-
|
|
117
|
-
| 0-1
|
|
118
|
-
| 1-2
|
|
119
|
-
| 2-3.5
|
|
120
|
-
| 3.5-5
|
|
121
|
-
| 5-10
|
|
122
|
-
| >10
|
|
126
|
+
| ΔE Value | Perception | Use Case |
|
|
127
|
+
| -------- | ---------------------- | ------------------ |
|
|
128
|
+
| 0-1 | Not perceptible | Exact matches |
|
|
129
|
+
| 1-2 | Barely perceptible | Very close matches |
|
|
130
|
+
| 2-3.5 | Perceptible by experts | Close matches |
|
|
131
|
+
| 3.5-5 | Noticeable difference | Acceptable matches |
|
|
132
|
+
| 5-10 | Clear difference | Related colors |
|
|
133
|
+
| >10 | Different colors | Distinct colors |
|
|
123
134
|
|
|
124
135
|
## Metric Comparison
|
|
125
136
|
|
|
@@ -211,14 +222,14 @@ Is performance critical?
|
|
|
211
222
|
|
|
212
223
|
### Use Case Guidelines
|
|
213
224
|
|
|
214
|
-
| Use Case
|
|
215
|
-
|
|
216
|
-
| CSS color matching
|
|
217
|
-
| Real-time filtering
|
|
218
|
-
| Theme generation
|
|
219
|
-
| Print color matching | Delta E 2000
|
|
220
|
-
| Palette creation
|
|
221
|
-
| Image quantization
|
|
225
|
+
| Use Case | Recommended Metric | Reason |
|
|
226
|
+
| -------------------- | ------------------ | --------------------- |
|
|
227
|
+
| CSS color matching | Delta E 2000 | Accuracy |
|
|
228
|
+
| Real-time filtering | Euclidean | Speed |
|
|
229
|
+
| Theme generation | HCT | UI optimization |
|
|
230
|
+
| Print color matching | Delta E 2000 | Industry standard |
|
|
231
|
+
| Palette creation | HCT | Perceptual uniformity |
|
|
232
|
+
| Image quantization | Delta E 76 | Balance |
|
|
222
233
|
|
|
223
234
|
## Implementation Examples
|
|
224
235
|
|
|
@@ -226,14 +237,14 @@ Is performance critical?
|
|
|
226
237
|
|
|
227
238
|
```javascript
|
|
228
239
|
function findSimilarColors(targetColor, palette, threshold = 5) {
|
|
229
|
-
return palette.filter(color => {
|
|
230
|
-
const distance = colorDistance(targetColor, color,
|
|
240
|
+
return palette.filter((color) => {
|
|
241
|
+
const distance = colorDistance(targetColor, color, "deltaE2000");
|
|
231
242
|
return distance < threshold;
|
|
232
243
|
});
|
|
233
244
|
}
|
|
234
245
|
|
|
235
246
|
// Usage
|
|
236
|
-
const similar = findSimilarColors(
|
|
247
|
+
const similar = findSimilarColors("#6366f1", myPalette, 10);
|
|
237
248
|
// Returns colors within ΔE 10 of target
|
|
238
249
|
```
|
|
239
250
|
|
|
@@ -243,11 +254,11 @@ const similar = findSimilarColors('#6366f1', myPalette, 10);
|
|
|
243
254
|
function clusterColors(colors, maxDistance = 5) {
|
|
244
255
|
const clusters = [];
|
|
245
256
|
|
|
246
|
-
colors.forEach(color => {
|
|
257
|
+
colors.forEach((color) => {
|
|
247
258
|
let added = false;
|
|
248
259
|
|
|
249
260
|
for (const cluster of clusters) {
|
|
250
|
-
const distance = colorDistance(color, cluster.center,
|
|
261
|
+
const distance = colorDistance(color, cluster.center, "deltaE2000");
|
|
251
262
|
if (distance < maxDistance) {
|
|
252
263
|
cluster.colors.push(color);
|
|
253
264
|
added = true;
|
|
@@ -258,7 +269,7 @@ function clusterColors(colors, maxDistance = 5) {
|
|
|
258
269
|
if (!added) {
|
|
259
270
|
clusters.push({
|
|
260
271
|
center: color,
|
|
261
|
-
colors: [color]
|
|
272
|
+
colors: [color],
|
|
262
273
|
});
|
|
263
274
|
}
|
|
264
275
|
});
|
|
@@ -281,7 +292,7 @@ function interpolatePerceptual(color1, color2, steps) {
|
|
|
281
292
|
const lab = {
|
|
282
293
|
l: lab1.l + (lab2.l - lab1.l) * t,
|
|
283
294
|
a: lab1.a + (lab2.a - lab1.a) * t,
|
|
284
|
-
b: lab1.b + (lab2.b - lab1.b) * t
|
|
295
|
+
b: lab1.b + (lab2.b - lab1.b) * t,
|
|
285
296
|
};
|
|
286
297
|
colors.push(labToRgb(lab));
|
|
287
298
|
}
|
|
@@ -313,16 +324,16 @@ Distance perception changes based on viewing conditions:
|
|
|
313
324
|
|
|
314
325
|
```javascript
|
|
315
326
|
function contextualDistance(color1, color2, context) {
|
|
316
|
-
switch(context) {
|
|
317
|
-
case
|
|
327
|
+
switch (context) {
|
|
328
|
+
case "small-text":
|
|
318
329
|
// Need larger differences for readability
|
|
319
330
|
return colorDistance(color1, color2) * 1.5;
|
|
320
331
|
|
|
321
|
-
case
|
|
332
|
+
case "large-area":
|
|
322
333
|
// Subtle differences more noticeable
|
|
323
334
|
return colorDistance(color1, color2) * 0.8;
|
|
324
335
|
|
|
325
|
-
case
|
|
336
|
+
case "dark-mode":
|
|
326
337
|
// Adjust for dark backgrounds
|
|
327
338
|
return adjustedDarkModeDistance(color1, color2);
|
|
328
339
|
|
|
@@ -343,8 +354,8 @@ function multiFactorDistance(color1, color2) {
|
|
|
343
354
|
const semantic = getSemanticDistance(color1, color2);
|
|
344
355
|
|
|
345
356
|
return {
|
|
346
|
-
overall:
|
|
347
|
-
components: { perceptual, contrast, semantic }
|
|
357
|
+
overall: perceptual * 0.6 + contrast * 0.3 + semantic * 0.1,
|
|
358
|
+
components: { perceptual, contrast, semantic },
|
|
348
359
|
};
|
|
349
360
|
}
|
|
350
361
|
```
|
|
@@ -352,18 +363,22 @@ function multiFactorDistance(color1, color2) {
|
|
|
352
363
|
## Common Pitfalls
|
|
353
364
|
|
|
354
365
|
### RGB Distance Misuse
|
|
366
|
+
|
|
355
367
|
❌ Don't use RGB distance for perceptual matching
|
|
356
368
|
✅ Use Delta E or HCT distance instead
|
|
357
369
|
|
|
358
370
|
### Ignoring Context
|
|
371
|
+
|
|
359
372
|
❌ Don't use the same threshold for all use cases
|
|
360
373
|
✅ Adjust thresholds based on application
|
|
361
374
|
|
|
362
375
|
### Over-Engineering
|
|
376
|
+
|
|
363
377
|
❌ Don't always use the most complex metric
|
|
364
378
|
✅ Choose based on actual requirements
|
|
365
379
|
|
|
366
380
|
### Wrong Color Space
|
|
381
|
+
|
|
367
382
|
❌ Don't interpolate in RGB for gradients
|
|
368
383
|
✅ Use LAB or HCT for smooth transitions
|
|
369
384
|
|
|
@@ -381,4 +396,4 @@ function multiFactorDistance(color1, color2) {
|
|
|
381
396
|
- [Color Spaces](./color-spaces.md) - Understanding different color models
|
|
382
397
|
- [HCT System](./hct.md) - Google's perceptual color space
|
|
383
398
|
- [Theme Matching](./theme-matching.md) - Using distance for matching
|
|
384
|
-
- [Accessibility](./accessibility.md) - Contrast and perception
|
|
399
|
+
- [Accessibility](./accessibility.md) - Contrast and perception
|
package/docs/concepts/hct.md
CHANGED
|
@@ -50,7 +50,7 @@ Tone Difference | Approximate Contrast Ratio
|
|
|
50
50
|
const primary = { h: 265, c: 50, t: 50 };
|
|
51
51
|
|
|
52
52
|
// Guaranteed accessible combinations
|
|
53
|
-
const onPrimary = { h: 265, c: 50, t: 100 };
|
|
53
|
+
const onPrimary = { h: 265, c: 50, t: 100 }; // t: 50 → 100 = 50 diff = 4.5:1
|
|
54
54
|
const primaryContainer = { h: 265, c: 25, t: 90 }; // Lower chroma, high tone
|
|
55
55
|
const onPrimaryContainer = { h: 265, c: 50, t: 10 }; // t: 90 → 10 = 80 diff = 7:1+
|
|
56
56
|
```
|
|
@@ -62,11 +62,13 @@ HCT is the foundation of Material Design 3's color system:
|
|
|
62
62
|
### Tonal Palettes
|
|
63
63
|
|
|
64
64
|
Material Design uses 13 standard tones:
|
|
65
|
+
|
|
65
66
|
```
|
|
66
67
|
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99, 100]
|
|
67
68
|
```
|
|
68
69
|
|
|
69
70
|
Each tone has specific use cases:
|
|
71
|
+
|
|
70
72
|
- **0-10**: On-colors for light surfaces
|
|
71
73
|
- **20-40**: Accent and emphasis colors
|
|
72
74
|
- **50**: Medium, often primary color
|
|
@@ -79,16 +81,16 @@ HCT enables semantic color roles with guaranteed contrast:
|
|
|
79
81
|
|
|
80
82
|
```javascript
|
|
81
83
|
// Primary color family
|
|
82
|
-
primary: tone(40)
|
|
83
|
-
onPrimary: tone(100)
|
|
84
|
-
primaryContainer: tone(90)
|
|
85
|
-
onPrimaryContainer: tone(10) // Text on container
|
|
84
|
+
primary: tone(40); // Main brand color
|
|
85
|
+
onPrimary: tone(100); // Text on primary
|
|
86
|
+
primaryContainer: tone(90); // Light container
|
|
87
|
+
onPrimaryContainer: tone(10); // Text on container
|
|
86
88
|
|
|
87
89
|
// Surface colors
|
|
88
|
-
surface: tone(99)
|
|
89
|
-
onSurface: tone(10)
|
|
90
|
-
surfaceVariant: tone(95)
|
|
91
|
-
onSurfaceVariant: tone(30) // Secondary text
|
|
90
|
+
surface: tone(99); // Main background
|
|
91
|
+
onSurface: tone(10); // Text on surface
|
|
92
|
+
surfaceVariant: tone(95); // Secondary background
|
|
93
|
+
onSurfaceVariant: tone(30); // Secondary text
|
|
92
94
|
```
|
|
93
95
|
|
|
94
96
|
## Chroma Behavior
|
|
@@ -106,6 +108,7 @@ Chroma in HCT represents color intensity, but unlike saturation in HSL, it maint
|
|
|
106
108
|
### Chroma and Tone Interaction
|
|
107
109
|
|
|
108
110
|
Maximum achievable chroma varies by tone:
|
|
111
|
+
|
|
109
112
|
```
|
|
110
113
|
Tone 0-10: Low max chroma (dark colors can't be very colorful)
|
|
111
114
|
Tone 40-60: Highest max chroma (mid-tones most colorful)
|
|
@@ -128,7 +131,7 @@ function generateTheme(sourceColor) {
|
|
|
128
131
|
tertiary: { h: hct.h + 120, c: hct.c * 0.7, t: 40 },
|
|
129
132
|
error: { h: 25, c: 84, t: 40 },
|
|
130
133
|
neutral: { h: hct.h, c: 4, t: 50 },
|
|
131
|
-
neutralVariant: { h: hct.h, c: 8, t: 50 }
|
|
134
|
+
neutralVariant: { h: hct.h, c: 8, t: 50 },
|
|
132
135
|
};
|
|
133
136
|
}
|
|
134
137
|
```
|
|
@@ -139,8 +142,7 @@ Create accessible color variations:
|
|
|
139
142
|
|
|
140
143
|
```javascript
|
|
141
144
|
function createAccessiblePair(baseHct, contrastRatio = 4.5) {
|
|
142
|
-
const toneDiff = contrastRatio >= 7 ? 70 :
|
|
143
|
-
contrastRatio >= 4.5 ? 50 : 40;
|
|
145
|
+
const toneDiff = contrastRatio >= 7 ? 70 : contrastRatio >= 4.5 ? 50 : 40;
|
|
144
146
|
|
|
145
147
|
const lighter = { ...baseHct, t: Math.min(100, baseHct.t + toneDiff) };
|
|
146
148
|
const darker = { ...baseHct, t: Math.max(0, baseHct.t - toneDiff) };
|
|
@@ -172,21 +174,21 @@ function harmonize(color1Hct, color2Hct) {
|
|
|
172
174
|
|
|
173
175
|
### HCT vs LAB
|
|
174
176
|
|
|
175
|
-
| Aspect
|
|
176
|
-
|
|
177
|
-
| Perceptual Uniformity | ✅ Optimized for UI
|
|
178
|
-
| Contrast Prediction
|
|
179
|
-
| UI Optimization
|
|
180
|
-
| Impossible Colors
|
|
177
|
+
| Aspect | HCT | LAB |
|
|
178
|
+
| --------------------- | ----------------------- | ------------------------- |
|
|
179
|
+
| Perceptual Uniformity | ✅ Optimized for UI | ✅ General purpose |
|
|
180
|
+
| Contrast Prediction | ✅ Direct tone mapping | ❌ Requires calculation |
|
|
181
|
+
| UI Optimization | ✅ Designed for screens | ❌ Designed for all media |
|
|
182
|
+
| Impossible Colors | ❌ None | ✅ Can represent |
|
|
181
183
|
|
|
182
184
|
### HCT vs HSL
|
|
183
185
|
|
|
184
|
-
| Aspect
|
|
185
|
-
|
|
186
|
-
| Perceptual Uniformity | ✅ Yes
|
|
187
|
-
| Lightness Accuracy
|
|
188
|
-
| Contrast Prediction
|
|
189
|
-
| Designer Familiarity
|
|
186
|
+
| Aspect | HCT | HSL |
|
|
187
|
+
| --------------------- | ----------------- | ----------------------- |
|
|
188
|
+
| Perceptual Uniformity | ✅ Yes | ❌ No |
|
|
189
|
+
| Lightness Accuracy | ✅ Perceptual | ❌ Mathematical |
|
|
190
|
+
| Contrast Prediction | ✅ Built-in | ❌ Requires calculation |
|
|
191
|
+
| Designer Familiarity | 🔶 Learning curve | ✅ Well known |
|
|
190
192
|
|
|
191
193
|
## Advanced Concepts
|
|
192
194
|
|
|
@@ -197,6 +199,7 @@ HCT is built on the CAM16 color appearance model, which models how humans percei
|
|
|
197
199
|
### Viewing Conditions
|
|
198
200
|
|
|
199
201
|
HCT assumes standard viewing conditions:
|
|
202
|
+
|
|
200
203
|
- Average surround
|
|
201
204
|
- Adapting luminance of 200 cd/m²
|
|
202
205
|
- 20% background luminance
|
|
@@ -238,9 +241,9 @@ const darkSurface = { h: 265, c: 0, t: 10 };
|
|
|
238
241
|
|
|
239
242
|
```javascript
|
|
240
243
|
// Standard error colors in HCT
|
|
241
|
-
const error = { h: 25, c: 84, t: 40 };
|
|
244
|
+
const error = { h: 25, c: 84, t: 40 }; // Red-orange, high chroma
|
|
242
245
|
const errorContainer = { h: 25, c: 30, t: 90 }; // Muted, light
|
|
243
|
-
const onError = { h: 25, c: 0, t: 100 };
|
|
246
|
+
const onError = { h: 25, c: 0, t: 100 }; // White
|
|
244
247
|
const onErrorContainer = { h: 25, c: 84, t: 10 }; // Dark red
|
|
245
248
|
```
|
|
246
249
|
|
|
@@ -258,4 +261,4 @@ Coolors MCP implements HCT using Google's Material Color Utilities algorithms:
|
|
|
258
261
|
- [Color Spaces](./color-spaces.md) - Comparison with other color models
|
|
259
262
|
- [Material Design](./material-design.md) - HCT in Material Design 3
|
|
260
263
|
- [Accessibility](./accessibility.md) - Using tone for contrast
|
|
261
|
-
- [Theme Matching](./theme-matching.md) - HCT-based matching algorithm
|
|
264
|
+
- [Theme Matching](./theme-matching.md) - HCT-based matching algorithm
|