@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
|
@@ -5,6 +5,7 @@ Coolors MCP provides advanced image color extraction using Google's Material Col
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
7
|
Image color extraction involves:
|
|
8
|
+
|
|
8
9
|
1. **Quantization** - Reducing colors to a representative set
|
|
9
10
|
2. **Scoring** - Evaluating colors for UI suitability
|
|
10
11
|
3. **Selection** - Choosing optimal source colors
|
|
@@ -17,7 +18,9 @@ Image color extraction involves:
|
|
|
17
18
|
Quantization is a lossy compression process that selects a limited number of colors that best represent the original image.
|
|
18
19
|
|
|
19
20
|
#### Celebi Algorithm
|
|
21
|
+
|
|
20
22
|
Coolors MCP uses the Celebi quantizer, which combines:
|
|
23
|
+
|
|
21
24
|
- **Wu's algorithm**: Fast color quantization
|
|
22
25
|
- **WSMeans**: Weighted spatial color clustering
|
|
23
26
|
|
|
@@ -27,6 +30,7 @@ const colors = quantize(pixels, 128);
|
|
|
27
30
|
```
|
|
28
31
|
|
|
29
32
|
#### How It Works
|
|
33
|
+
|
|
30
34
|
1. **Spatial clustering**: Groups similar colors that appear near each other
|
|
31
35
|
2. **Color frequency**: Weights colors by how often they appear
|
|
32
36
|
3. **Perceptual grouping**: Merges perceptually similar colors
|
|
@@ -40,24 +44,29 @@ Not all colors are suitable for UI themes. The scoring algorithm evaluates color
|
|
|
40
44
|
|
|
41
45
|
**Chroma Score**
|
|
42
46
|
Colors closer to the target chroma of 48 receive higher scores:
|
|
47
|
+
|
|
43
48
|
```javascript
|
|
44
49
|
chromaScore = 1 - Math.abs(chroma - 48) / 48;
|
|
45
50
|
```
|
|
46
51
|
|
|
47
52
|
**Population Score**
|
|
48
53
|
More frequent colors score higher:
|
|
54
|
+
|
|
49
55
|
```javascript
|
|
50
56
|
populationScore = pixelCount / totalPixels;
|
|
51
57
|
```
|
|
52
58
|
|
|
53
59
|
**Color Diversity**
|
|
54
60
|
Promotes visually distinct colors:
|
|
61
|
+
|
|
55
62
|
- Higher scores for well-represented hues (30° neighborhood)
|
|
56
63
|
- Penalizes colors too similar to already selected ones
|
|
57
64
|
- Ensures good distribution across color wheel
|
|
58
65
|
|
|
59
66
|
#### Filtering Criteria
|
|
67
|
+
|
|
60
68
|
Colors are filtered out if they:
|
|
69
|
+
|
|
61
70
|
- Have very low chroma (<15) - too close to grayscale
|
|
62
71
|
- Are extremely rare (<0.01% of pixels)
|
|
63
72
|
- Fall in the "dislike zone" (dark yellow-greens)
|
|
@@ -78,20 +87,26 @@ The system selects multiple source colors for theme options:
|
|
|
78
87
|
## Image Sources
|
|
79
88
|
|
|
80
89
|
### Wallpapers
|
|
90
|
+
|
|
81
91
|
User device wallpapers provide personalized color schemes:
|
|
92
|
+
|
|
82
93
|
- Analyzed on device for privacy
|
|
83
94
|
- Updates dynamically when wallpaper changes
|
|
84
95
|
- Creates cohesive system-wide theming
|
|
85
96
|
|
|
86
97
|
### App Content
|
|
98
|
+
|
|
87
99
|
Content-based colors adapt to current context:
|
|
100
|
+
|
|
88
101
|
- **Album art** → Music player theme
|
|
89
102
|
- **Product images** → E-commerce theme
|
|
90
103
|
- **Video thumbnails** → Media player theme
|
|
91
104
|
- **Logos** → Brand-consistent theme
|
|
92
105
|
|
|
93
106
|
### User Photos
|
|
107
|
+
|
|
94
108
|
Personal photos for custom themes:
|
|
109
|
+
|
|
95
110
|
- Profile pictures for personal spaces
|
|
96
111
|
- Gallery images for creative apps
|
|
97
112
|
- Artwork for design applications
|
|
@@ -147,12 +162,15 @@ Personal photos for custom themes:
|
|
|
147
162
|
The system automatically detects and adjusts universally disliked colors:
|
|
148
163
|
|
|
149
164
|
#### The "Bile Zone"
|
|
165
|
+
|
|
150
166
|
Dark yellow-greens (reminiscent of biological waste) are universally disliked:
|
|
167
|
+
|
|
151
168
|
- **Hue range**: 50-120° (yellow-green)
|
|
152
169
|
- **Chroma**: 20-50
|
|
153
170
|
- **Tone**: 20-50
|
|
154
171
|
|
|
155
172
|
#### Automatic Fixing
|
|
173
|
+
|
|
156
174
|
```javascript
|
|
157
175
|
if (isDisliked(color)) {
|
|
158
176
|
// Shift hue away from dislike zone
|
|
@@ -169,11 +187,11 @@ For complex images, analyze different regions:
|
|
|
169
187
|
```javascript
|
|
170
188
|
// Analyze specific image regions
|
|
171
189
|
const regions = [
|
|
172
|
-
{ x: 0, y: 0, width: 100, height: 100 },
|
|
173
|
-
{ x: 100, y: 100, width: 200, height: 200 } // Center
|
|
190
|
+
{ x: 0, y: 0, width: 100, height: 100 }, // Top-left
|
|
191
|
+
{ x: 100, y: 100, width: 200, height: 200 }, // Center
|
|
174
192
|
];
|
|
175
193
|
|
|
176
|
-
regions.forEach(region => {
|
|
194
|
+
regions.forEach((region) => {
|
|
177
195
|
const colors = extractFromRegion(image, region);
|
|
178
196
|
// Process regional colors
|
|
179
197
|
});
|
|
@@ -186,7 +204,7 @@ For video or animated content:
|
|
|
186
204
|
```javascript
|
|
187
205
|
// Extract colors from multiple frames
|
|
188
206
|
const frames = [0, 30, 60, 90, 120];
|
|
189
|
-
const frameColors = frames.map(f => extractFrame(video, f));
|
|
207
|
+
const frameColors = frames.map((f) => extractFrame(video, f));
|
|
190
208
|
|
|
191
209
|
// Find consistent colors across frames
|
|
192
210
|
const stableColors = findStableColors(frameColors);
|
|
@@ -196,12 +214,12 @@ const stableColors = findStableColors(frameColors);
|
|
|
196
214
|
|
|
197
215
|
### UI Suitability Factors
|
|
198
216
|
|
|
199
|
-
| Factor
|
|
200
|
-
|
|
201
|
-
| Chroma
|
|
202
|
-
| Population
|
|
203
|
-
| Diversity
|
|
204
|
-
| Accessibility | 10%
|
|
217
|
+
| Factor | Weight | Description |
|
|
218
|
+
| ------------- | ------ | ------------------------------------ |
|
|
219
|
+
| Chroma | 40% | Preference for moderate chroma (~48) |
|
|
220
|
+
| Population | 30% | How much of image uses this color |
|
|
221
|
+
| Diversity | 20% | Distinctness from other colors |
|
|
222
|
+
| Accessibility | 10% | Potential for good contrast |
|
|
205
223
|
|
|
206
224
|
### Scoring Algorithm
|
|
207
225
|
|
|
@@ -226,12 +244,14 @@ function scoreColor(color, population, existingColors) {
|
|
|
226
244
|
### Image Preparation
|
|
227
245
|
|
|
228
246
|
#### Optimal Images
|
|
247
|
+
|
|
229
248
|
- **Resolution**: 200-500px wide (resize larger images)
|
|
230
249
|
- **Format**: RGB/RGBA
|
|
231
250
|
- **Quality**: Avoid heavily compressed images
|
|
232
251
|
- **Content**: Clear subject with distinct colors
|
|
233
252
|
|
|
234
253
|
#### Pre-processing
|
|
254
|
+
|
|
235
255
|
```javascript
|
|
236
256
|
// Resize for performance
|
|
237
257
|
const resized = resizeImage(original, 300);
|
|
@@ -246,6 +266,7 @@ const colors = extractColors(enhanced);
|
|
|
246
266
|
### Performance Optimization
|
|
247
267
|
|
|
248
268
|
#### Sampling Strategies
|
|
269
|
+
|
|
249
270
|
```javascript
|
|
250
271
|
// Fast: Sample every 5th pixel
|
|
251
272
|
const fastColors = quantize(pixels, 128, { sampling: 5 });
|
|
@@ -258,6 +279,7 @@ const sampling = pixels.length > 100000 ? 5 : 1;
|
|
|
258
279
|
```
|
|
259
280
|
|
|
260
281
|
#### Caching
|
|
282
|
+
|
|
261
283
|
```javascript
|
|
262
284
|
// Cache extracted colors
|
|
263
285
|
const cache = new Map();
|
|
@@ -274,28 +296,34 @@ cache.set(hash, colors);
|
|
|
274
296
|
## Use Cases
|
|
275
297
|
|
|
276
298
|
### Dynamic Theming
|
|
299
|
+
|
|
277
300
|
Apps that adapt to content:
|
|
301
|
+
|
|
278
302
|
- Music players matching album art
|
|
279
303
|
- News readers matching article images
|
|
280
304
|
- Photo galleries with ambient themes
|
|
281
305
|
|
|
282
306
|
### Brand Extraction
|
|
307
|
+
|
|
283
308
|
Deriving brand colors from logos:
|
|
309
|
+
|
|
284
310
|
```javascript
|
|
285
|
-
const logo = loadImage(
|
|
311
|
+
const logo = loadImage("logo.png");
|
|
286
312
|
const brandColors = extractColors(logo, {
|
|
287
313
|
maxColors: 3,
|
|
288
|
-
minChroma: 30
|
|
314
|
+
minChroma: 30, // Ensure vibrant colors
|
|
289
315
|
});
|
|
290
316
|
```
|
|
291
317
|
|
|
292
318
|
### Palette Generation
|
|
319
|
+
|
|
293
320
|
Creating artist palettes from artwork:
|
|
321
|
+
|
|
294
322
|
```javascript
|
|
295
|
-
const artwork = loadImage(
|
|
323
|
+
const artwork = loadImage("painting.jpg");
|
|
296
324
|
const palette = extractColors(artwork, {
|
|
297
325
|
maxColors: 12,
|
|
298
|
-
includeNeutrals: true
|
|
326
|
+
includeNeutrals: true,
|
|
299
327
|
});
|
|
300
328
|
```
|
|
301
329
|
|
|
@@ -312,7 +340,7 @@ async function themeFromUpload(file) {
|
|
|
312
340
|
|
|
313
341
|
const response = await coolorsMCP.extractColors({
|
|
314
342
|
imageData: pixels,
|
|
315
|
-
maxColors: 5
|
|
343
|
+
maxColors: 5,
|
|
316
344
|
});
|
|
317
345
|
|
|
318
346
|
return response.colors[0]; // Use top color
|
|
@@ -330,9 +358,7 @@ function ImageThemeProvider({ imageUrl, children }) {
|
|
|
330
358
|
}, [imageUrl]);
|
|
331
359
|
|
|
332
360
|
return (
|
|
333
|
-
<ThemeContext.Provider value={theme}>
|
|
334
|
-
{children}
|
|
335
|
-
</ThemeContext.Provider>
|
|
361
|
+
<ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
|
|
336
362
|
);
|
|
337
363
|
}
|
|
338
364
|
```
|
|
@@ -340,7 +366,7 @@ function ImageThemeProvider({ imageUrl, children }) {
|
|
|
340
366
|
### Node.js Server
|
|
341
367
|
|
|
342
368
|
```javascript
|
|
343
|
-
const sharp = require(
|
|
369
|
+
const sharp = require("sharp");
|
|
344
370
|
|
|
345
371
|
async function extractFromBuffer(buffer) {
|
|
346
372
|
// Resize and convert to raw pixels
|
|
@@ -353,7 +379,7 @@ async function extractFromBuffer(buffer) {
|
|
|
353
379
|
const colors = await coolorsMCP.extractColors({
|
|
354
380
|
imageData: Array.from(data),
|
|
355
381
|
width: info.width,
|
|
356
|
-
height: info.height
|
|
382
|
+
height: info.height,
|
|
357
383
|
});
|
|
358
384
|
|
|
359
385
|
return colors;
|
|
@@ -363,11 +389,13 @@ async function extractFromBuffer(buffer) {
|
|
|
363
389
|
## Limitations
|
|
364
390
|
|
|
365
391
|
### Technical Constraints
|
|
392
|
+
|
|
366
393
|
- Maximum image size: ~5MB recommended
|
|
367
394
|
- Color count: 128 colors maximum per extraction
|
|
368
395
|
- Processing time: ~100-500ms for typical images
|
|
369
396
|
|
|
370
397
|
### Accuracy Considerations
|
|
398
|
+
|
|
371
399
|
- Compressed images may lose color fidelity
|
|
372
400
|
- Very dark/light images provide limited options
|
|
373
401
|
- Monochrome images need fallback strategies
|
|
@@ -377,14 +405,17 @@ async function extractFromBuffer(buffer) {
|
|
|
377
405
|
### Common Issues
|
|
378
406
|
|
|
379
407
|
#### No Suitable Colors Found
|
|
408
|
+
|
|
380
409
|
**Cause**: Image too monochrome or low contrast
|
|
381
410
|
**Solution**: Adjust scoring thresholds or provide fallback
|
|
382
411
|
|
|
383
412
|
#### Inconsistent Results
|
|
413
|
+
|
|
384
414
|
**Cause**: Image compression or resizing artifacts
|
|
385
415
|
**Solution**: Use higher quality source images
|
|
386
416
|
|
|
387
417
|
#### Performance Problems
|
|
418
|
+
|
|
388
419
|
**Cause**: Processing large images
|
|
389
420
|
**Solution**: Resize before extraction
|
|
390
421
|
|
|
@@ -393,4 +424,4 @@ async function extractFromBuffer(buffer) {
|
|
|
393
424
|
- [Material Design](./material-design.md) - Theme generation from colors
|
|
394
425
|
- [Color Spaces](./color-spaces.md) - Understanding color models
|
|
395
426
|
- [HCT System](./hct.md) - Perceptual color space
|
|
396
|
-
- [Accessibility](./accessibility.md) - Ensuring extracted colors are usable
|
|
427
|
+
- [Accessibility](./accessibility.md) - Ensuring extracted colors are usable
|
|
@@ -15,30 +15,35 @@ Dynamic color is the heart of Material Design 3, enabling personalized experienc
|
|
|
15
15
|
Material Design 3 defines semantic color roles that map to UI elements consistently:
|
|
16
16
|
|
|
17
17
|
### Primary Colors
|
|
18
|
+
|
|
18
19
|
- **primary**: Main brand or theme color (tone 40 in light, 80 in dark)
|
|
19
20
|
- **onPrimary**: Text/icons on primary color (tone 100 in light, 20 in dark)
|
|
20
21
|
- **primaryContainer**: Light container variant (tone 90 in light, 30 in dark)
|
|
21
22
|
- **onPrimaryContainer**: Text on primary container (tone 10 in light, 90 in dark)
|
|
22
23
|
|
|
23
24
|
### Secondary Colors
|
|
25
|
+
|
|
24
26
|
- **secondary**: Supporting brand color
|
|
25
27
|
- **onSecondary**: Text/icons on secondary
|
|
26
28
|
- **secondaryContainer**: Light container variant
|
|
27
29
|
- **onSecondaryContainer**: Text on secondary container
|
|
28
30
|
|
|
29
31
|
### Tertiary Colors
|
|
32
|
+
|
|
30
33
|
- **tertiary**: Accent for special emphasis
|
|
31
34
|
- **onTertiary**: Text/icons on tertiary
|
|
32
35
|
- **tertiaryContainer**: Light container variant
|
|
33
36
|
- **onTertiaryContainer**: Text on tertiary container
|
|
34
37
|
|
|
35
38
|
### Surface Colors
|
|
39
|
+
|
|
36
40
|
- **surface**: Main background color (tone 99 in light, 10 in dark)
|
|
37
41
|
- **onSurface**: Primary text color (tone 10 in light, 90 in dark)
|
|
38
42
|
- **surfaceVariant**: Secondary background (tone 95 in light, 30 in dark)
|
|
39
43
|
- **onSurfaceVariant**: Secondary text (tone 30 in light, 80 in dark)
|
|
40
44
|
|
|
41
45
|
### Additional Roles
|
|
46
|
+
|
|
42
47
|
- **error**: Error states (hue ~25, chroma 84)
|
|
43
48
|
- **outline**: Borders and dividers
|
|
44
49
|
- **shadow**: Shadow colors
|
|
@@ -57,13 +62,13 @@ Material Design 3 uses 13 standard tones for each color palette:
|
|
|
57
62
|
|
|
58
63
|
### Tone Usage Guidelines
|
|
59
64
|
|
|
60
|
-
| Tone Range | Light Theme Usage
|
|
61
|
-
|
|
62
|
-
| 0-10
|
|
63
|
-
| 20-40
|
|
64
|
-
| 50
|
|
65
|
-
| 60-80
|
|
66
|
-
| 90-100
|
|
65
|
+
| Tone Range | Light Theme Usage | Dark Theme Usage |
|
|
66
|
+
| ---------- | ----------------------------- | -------------------- |
|
|
67
|
+
| 0-10 | On-colors, high emphasis text | Surfaces, containers |
|
|
68
|
+
| 20-40 | Primary actions, emphasis | On-colors, text |
|
|
69
|
+
| 50 | Neutral midpoint | Neutral midpoint |
|
|
70
|
+
| 60-80 | Containers, surfaces | Primary actions |
|
|
71
|
+
| 90-100 | Backgrounds, surfaces | On-colors, text |
|
|
67
72
|
|
|
68
73
|
## Key Colors
|
|
69
74
|
|
|
@@ -80,31 +85,37 @@ From a single source color, Material Design generates five key colors:
|
|
|
80
85
|
Material Design 3 offers multiple scheme variants for different moods:
|
|
81
86
|
|
|
82
87
|
### Tonal Spot (Default)
|
|
88
|
+
|
|
83
89
|
- Balanced use of primary color
|
|
84
90
|
- Secondary and tertiary are complementary
|
|
85
91
|
- Most versatile for general use
|
|
86
92
|
|
|
87
93
|
### Fidelity
|
|
94
|
+
|
|
88
95
|
- Preserves source color's exact appearance
|
|
89
96
|
- Adjusts tones to maintain chroma
|
|
90
97
|
- Best for brand-critical applications
|
|
91
98
|
|
|
92
99
|
### Vibrant
|
|
100
|
+
|
|
93
101
|
- Higher chroma across all colors
|
|
94
102
|
- More colorful, energetic appearance
|
|
95
103
|
- Good for creative, playful apps
|
|
96
104
|
|
|
97
105
|
### Expressive
|
|
106
|
+
|
|
98
107
|
- Unexpected color combinations
|
|
99
108
|
- Creative hue rotations
|
|
100
109
|
- For bold, artistic interfaces
|
|
101
110
|
|
|
102
111
|
### Neutral
|
|
112
|
+
|
|
103
113
|
- Minimal color, maximum elegance
|
|
104
114
|
- Reduced chroma values
|
|
105
115
|
- Professional, understated look
|
|
106
116
|
|
|
107
117
|
### Monochrome
|
|
118
|
+
|
|
108
119
|
- Single hue, varying tones
|
|
109
120
|
- Ultimate minimalism
|
|
110
121
|
- Focus on content over color
|
|
@@ -114,16 +125,19 @@ Material Design 3 offers multiple scheme variants for different moods:
|
|
|
114
125
|
Material Design 3 supports three contrast levels:
|
|
115
126
|
|
|
116
127
|
### Default (0.0)
|
|
128
|
+
|
|
117
129
|
- WCAG AA compliant
|
|
118
130
|
- 4.5:1 for normal text
|
|
119
131
|
- 3:1 for large text
|
|
120
132
|
|
|
121
133
|
### Medium (+0.5)
|
|
134
|
+
|
|
122
135
|
- Enhanced readability
|
|
123
136
|
- ~6:1 for normal text
|
|
124
137
|
- Better for outdoor/bright conditions
|
|
125
138
|
|
|
126
139
|
### High (+1.0)
|
|
140
|
+
|
|
127
141
|
- WCAG AAA compliant
|
|
128
142
|
- 7:1 for normal text
|
|
129
143
|
- Maximum accessibility
|
|
@@ -173,12 +187,14 @@ Material Design 3 supports three contrast levels:
|
|
|
173
187
|
Material Design uses harmonization to ensure colors work together:
|
|
174
188
|
|
|
175
189
|
### Harmonization Algorithm
|
|
190
|
+
|
|
176
191
|
1. Analyze hue relationships
|
|
177
192
|
2. Adjust hues toward harmony angles (0°, 60°, 120°, 180°, 240°, 300°)
|
|
178
193
|
3. Maintain original chroma and tone
|
|
179
194
|
4. Blend based on harmonization strength
|
|
180
195
|
|
|
181
196
|
### Example
|
|
197
|
+
|
|
182
198
|
```javascript
|
|
183
199
|
{
|
|
184
200
|
"name": "harmonize_colors",
|
|
@@ -194,11 +210,12 @@ Material Design uses harmonization to ensure colors work together:
|
|
|
194
210
|
Material Design 3 uses design tokens for consistent application:
|
|
195
211
|
|
|
196
212
|
### Token Structure
|
|
213
|
+
|
|
197
214
|
```css
|
|
198
215
|
/* Color tokens */
|
|
199
|
-
--md-sys-color-primary: #
|
|
200
|
-
--md-sys-color-on-primary: #
|
|
201
|
-
--md-sys-color-primary-container: #
|
|
216
|
+
--md-sys-color-primary: #6366f1;
|
|
217
|
+
--md-sys-color-on-primary: #ffffff;
|
|
218
|
+
--md-sys-color-primary-container: #e0e2ff;
|
|
202
219
|
--md-sys-color-on-primary-container: #000747;
|
|
203
220
|
|
|
204
221
|
/* Elevation tokens */
|
|
@@ -236,6 +253,7 @@ The complete process for generating a Material theme:
|
|
|
236
253
|
## Best Practices
|
|
237
254
|
|
|
238
255
|
### Do's
|
|
256
|
+
|
|
239
257
|
- ✅ Use semantic color roles consistently
|
|
240
258
|
- ✅ Test with all three contrast levels
|
|
241
259
|
- ✅ Validate color combinations for accessibility
|
|
@@ -243,6 +261,7 @@ The complete process for generating a Material theme:
|
|
|
243
261
|
- ✅ Use harmonization for multiple brand colors
|
|
244
262
|
|
|
245
263
|
### Don'ts
|
|
264
|
+
|
|
246
265
|
- ❌ Override tone assignments arbitrarily
|
|
247
266
|
- ❌ Use colors outside the tonal palettes
|
|
248
267
|
- ❌ Ignore contrast requirements
|
|
@@ -252,6 +271,7 @@ The complete process for generating a Material theme:
|
|
|
252
271
|
## Integration Examples
|
|
253
272
|
|
|
254
273
|
### React/CSS
|
|
274
|
+
|
|
255
275
|
```css
|
|
256
276
|
:root {
|
|
257
277
|
--md-sys-color-primary: rgb(99, 102, 241);
|
|
@@ -265,33 +285,39 @@ The complete process for generating a Material theme:
|
|
|
265
285
|
```
|
|
266
286
|
|
|
267
287
|
### Tailwind CSS
|
|
288
|
+
|
|
268
289
|
```javascript
|
|
269
290
|
// tailwind.config.js
|
|
270
291
|
module.exports = {
|
|
271
292
|
theme: {
|
|
272
293
|
extend: {
|
|
273
294
|
colors: {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
295
|
+
"md-primary": "var(--md-sys-color-primary)",
|
|
296
|
+
"md-surface": "var(--md-sys-color-surface)",
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
};
|
|
280
301
|
```
|
|
281
302
|
|
|
282
303
|
## Advanced Features
|
|
283
304
|
|
|
284
305
|
### Dislike Prevention
|
|
306
|
+
|
|
285
307
|
Material Design automatically detects and adjusts universally disliked colors (dark yellow-greens that resemble biological waste) by shifting their hue and increasing tone.
|
|
286
308
|
|
|
287
309
|
### Content-Based Schemes
|
|
310
|
+
|
|
288
311
|
Generate schemes that adapt to content:
|
|
312
|
+
|
|
289
313
|
- Album artwork → Music player theme
|
|
290
314
|
- Product images → E-commerce theme
|
|
291
315
|
- User photos → Gallery theme
|
|
292
316
|
|
|
293
317
|
### Cross-Platform Consistency
|
|
318
|
+
|
|
294
319
|
The same source color produces identical themes across:
|
|
320
|
+
|
|
295
321
|
- Android (Material You)
|
|
296
322
|
- Web (Material Web)
|
|
297
323
|
- Flutter
|
|
@@ -303,4 +329,4 @@ The same source color produces identical themes across:
|
|
|
303
329
|
- [Color Spaces](./color-spaces.md) - Color space comparisons
|
|
304
330
|
- [Accessibility](./accessibility.md) - Contrast and accessibility
|
|
305
331
|
- [Image Analysis](./image-analysis.md) - Extracting colors from images
|
|
306
|
-
- [Material Design Guidelines](https://m3.material.io) - Official documentation
|
|
332
|
+
- [Material Design Guidelines](https://m3.material.io) - Official documentation
|