@trishchuk/coolors-mcp 1.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/.claude/settings.local.json +39 -0
- package/.env +2 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +73 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +71 -0
- package/.github/pull_request_template.md +97 -0
- package/.github/workflows/ci.yml +127 -0
- package/.github/workflows/deploy-docs.yml +56 -0
- package/.github/workflows/release.yml +99 -0
- package/.mcp.json +12 -0
- package/.prettierignore +1 -0
- package/CLAUDE.md +201 -0
- package/DOCUMENTATION.md +274 -0
- package/GEMINI.md +54 -0
- package/LICENSE +21 -0
- package/README.md +401 -0
- package/demo/content_based_color.png +0 -0
- package/demo/music-player.html +621 -0
- package/demo/podcast-player.html +903 -0
- package/dist/bin/coolors-mcp.d.ts +1 -0
- package/dist/bin/coolors-mcp.js +154 -0
- package/dist/bin/coolors-mcp.js.map +1 -0
- package/dist/bin/server.d.ts +1 -0
- package/dist/bin/server.js +3292 -0
- package/dist/bin/server.js.map +1 -0
- package/dist/chunk-IQ7NN26V.js +114 -0
- package/dist/chunk-IQ7NN26V.js.map +1 -0
- package/dist/chunk-P3ARRKLS.js +1214 -0
- package/dist/chunk-P3ARRKLS.js.map +1 -0
- package/dist/color/index.d.ts +716 -0
- package/dist/color/index.js +153 -0
- package/dist/color/index.js.map +1 -0
- package/dist/coolors-mcp.d.ts +136 -0
- package/dist/coolors-mcp.js +7 -0
- package/dist/coolors-mcp.js.map +1 -0
- package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js +93 -0
- package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js.map +7 -0
- package/docs/.vitepress/cache/deps/_metadata.json +127 -0
- package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js +9 -0
- package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js.map +7 -0
- package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js +12683 -0
- package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js.map +7 -0
- package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js +9719 -0
- package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js.map +7 -0
- package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js +4710 -0
- package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js.map +7 -0
- package/docs/.vitepress/cache/deps/cytoscape.js +30278 -0
- package/docs/.vitepress/cache/deps/cytoscape.js.map +7 -0
- package/docs/.vitepress/cache/deps/dayjs.js +285 -0
- package/docs/.vitepress/cache/deps/dayjs.js.map +7 -0
- package/docs/.vitepress/cache/deps/debug.js +468 -0
- package/docs/.vitepress/cache/deps/debug.js.map +7 -0
- package/docs/.vitepress/cache/deps/package.json +3 -0
- package/docs/.vitepress/cache/deps/prismjs.js +1466 -0
- package/docs/.vitepress/cache/deps/prismjs.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js +228 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js +142 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js +27 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js +65 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js +53 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js +73 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4507 -0
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +584 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +1146 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +1667 -0
- package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___minisearch.js +1814 -0
- package/docs/.vitepress/cache/deps/vitepress___minisearch.js.map +7 -0
- package/docs/.vitepress/cache/deps/vue.js +344 -0
- package/docs/.vitepress/cache/deps/vue.js.map +7 -0
- package/docs/.vitepress/components/ClientGrid.vue +125 -0
- package/docs/.vitepress/components/CodeBlock.vue +231 -0
- package/docs/.vitepress/components/ConfigModal.vue +477 -0
- package/docs/.vitepress/components/DiagramModal.vue +528 -0
- package/docs/.vitepress/components/TroubleshootingModal.vue +472 -0
- package/docs/.vitepress/config.js +162 -0
- package/docs/.vitepress/theme/FundingLayout.vue +251 -0
- package/docs/.vitepress/theme/Layout.vue +134 -0
- package/docs/.vitepress/theme/components/AdBanner.vue +317 -0
- package/docs/.vitepress/theme/components/AdPlaceholder.vue +78 -0
- package/docs/.vitepress/theme/components/FundingEffects.vue +322 -0
- package/docs/.vitepress/theme/components/FundingHero.vue +345 -0
- package/docs/.vitepress/theme/components/SupportSection.vue +511 -0
- package/docs/.vitepress/theme/custom-app.css +339 -0
- package/docs/.vitepress/theme/custom.css +699 -0
- package/docs/.vitepress/theme/index.js +25 -0
- package/docs/README.md +198 -0
- package/docs/concepts/accessibility.md +473 -0
- package/docs/concepts/color-spaces.md +222 -0
- package/docs/concepts/distance-metrics.md +384 -0
- package/docs/concepts/hct.md +261 -0
- package/docs/concepts/image-analysis.md +396 -0
- package/docs/concepts/material-design.md +306 -0
- package/docs/concepts/theme-matching.md +399 -0
- package/docs/examples/basic-colors.md +490 -0
- package/docs/examples/creating-themes.md +898 -0
- package/docs/examples/css-refactoring.md +824 -0
- package/docs/examples/image-extraction.md +882 -0
- package/docs/getting-started.md +366 -0
- package/docs/index.md +190 -0
- package/docs/installation.md +157 -0
- package/docs/tools/README.md +234 -0
- package/docs/tools/accessibility.md +614 -0
- package/docs/tools/color-operations.md +374 -0
- package/docs/tools/image-extraction.md +624 -0
- package/docs/tools/material-design.md +347 -0
- package/docs/tools/theme-matching.md +552 -0
- package/eslint.config.ts +14 -0
- package/examples/theme-matching.md +113 -0
- package/jsr.json +7 -0
- package/mcp-config.json +8 -0
- package/note.md +35 -0
- package/package.json +122 -0
- package/research_results.md +53 -0
- package/src/bin/coolors-mcp.ts +194 -0
- package/src/bin/server.ts +61 -0
- package/src/color/__tests__/conversions-argb.test.ts +198 -0
- package/src/color/__tests__/extract-colors.test.ts +360 -0
- package/src/color/__tests__/image-utils.test.ts +242 -0
- package/src/color/__tests__/reference-colors.test.ts +278 -0
- package/src/color/__tests__/round-trip.test.ts +197 -0
- package/src/color/conversions.test.ts +402 -0
- package/src/color/conversions.ts +393 -0
- package/src/color/dislike/__tests__/dislike-analyzer.test.ts +248 -0
- package/src/color/dislike/dislike-analyzer.ts +114 -0
- package/src/color/extract-colors.ts +228 -0
- package/src/color/hct/__tests__/hct-class.test.ts +232 -0
- package/src/color/hct/harmonization.ts +204 -0
- package/src/color/hct/hct-class.ts +109 -0
- package/src/color/hct/hct-solver.ts +168 -0
- package/src/color/hct/index.ts +39 -0
- package/src/color/hct/tonal-palette.ts +211 -0
- package/src/color/hct/types.ts +88 -0
- package/src/color/image-utils.ts +79 -0
- package/src/color/index.ts +87 -0
- package/src/color/material-theme.ts +157 -0
- package/src/color/metrics.test.ts +276 -0
- package/src/color/metrics.ts +281 -0
- package/src/color/quantize/__tests__/quantizer_celebi.test.ts +195 -0
- package/src/color/quantize/lab_point_provider.ts +55 -0
- package/src/color/quantize/point_provider.ts +27 -0
- package/src/color/quantize/quantizer_celebi.ts +51 -0
- package/src/color/quantize/quantizer_celebi_test.ts +71 -0
- package/src/color/quantize/quantizer_map.ts +47 -0
- package/src/color/quantize/quantizer_wsmeans.ts +232 -0
- package/src/color/quantize/quantizer_wu.ts +472 -0
- package/src/color/score/__tests__/score.test.ts +224 -0
- package/src/color/score/score.ts +175 -0
- package/src/color/types.ts +151 -0
- package/src/color/utils/color_utils.ts +292 -0
- package/src/color/utils/math_utils.ts +145 -0
- package/src/color/utils.test.ts +403 -0
- package/src/color/utils.ts +315 -0
- package/src/constants.ts +5 -0
- package/src/coolors-mcp.ts +37 -0
- package/src/examples/addition.ts +333 -0
- package/src/examples/color-demo.ts +125 -0
- package/src/examples/custom-logger.ts +201 -0
- package/src/examples/oauth-server.ts +113 -0
- package/src/examples/session-context.ts +269 -0
- package/src/session.ts +116 -0
- package/src/theme/__tests__/matcher.test.ts +180 -0
- package/src/theme/__tests__/parser.test.ts +148 -0
- package/src/theme/__tests__/refactor.test.ts +224 -0
- package/src/theme/index.ts +34 -0
- package/src/theme/matcher.ts +395 -0
- package/src/theme/parser.ts +392 -0
- package/src/theme/refactor.ts +360 -0
- package/src/theme/types.ts +152 -0
- package/src/tools/__tests__/gradient-generator.test.ts +206 -0
- package/src/tools/__tests__/palette-with-locks.test.ts +109 -0
- package/src/tools/color-conversion.tool.ts +54 -0
- package/src/tools/color-distance.tool.ts +41 -0
- package/src/tools/colors.ts +31 -0
- package/src/tools/contrast-checker.tool.ts +37 -0
- package/src/tools/dislike-analyzer.tool.ts +247 -0
- package/src/tools/gradient-generator.tool.ts +250 -0
- package/src/tools/image-extraction.tools.ts +289 -0
- package/src/tools/index.ts +39 -0
- package/src/tools/material-theme.tools.ts +250 -0
- package/src/tools/palette-generator.tool.ts +135 -0
- package/src/tools/palette-with-locks.tool.ts +221 -0
- package/src/tools/registry.ts +142 -0
- package/src/tools/simple-tools.ts +37 -0
- package/src/tools/theme-matching.tools.ts +334 -0
- package/src/types.ts +182 -0
- package/src/utils.ts +22 -0
- package/tsconfig.json +8 -0
- package/vitest.config.js +15 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
# Material Design 3 Color System
|
|
2
|
+
|
|
3
|
+
Material Design 3 introduces a revolutionary approach to color through dynamic color schemes that adapt to user preferences and content while maintaining accessibility and visual harmony.
|
|
4
|
+
|
|
5
|
+
## Dynamic Color Overview
|
|
6
|
+
|
|
7
|
+
Dynamic color is the heart of Material Design 3, enabling personalized experiences through:
|
|
8
|
+
|
|
9
|
+
- **User-generated color**: Extracted from wallpapers or user preferences
|
|
10
|
+
- **Content-based color**: Derived from app content like album art or logos
|
|
11
|
+
- **Systematic generation**: Creating complete themes from a single source color
|
|
12
|
+
|
|
13
|
+
## Color Roles
|
|
14
|
+
|
|
15
|
+
Material Design 3 defines semantic color roles that map to UI elements consistently:
|
|
16
|
+
|
|
17
|
+
### Primary Colors
|
|
18
|
+
- **primary**: Main brand or theme color (tone 40 in light, 80 in dark)
|
|
19
|
+
- **onPrimary**: Text/icons on primary color (tone 100 in light, 20 in dark)
|
|
20
|
+
- **primaryContainer**: Light container variant (tone 90 in light, 30 in dark)
|
|
21
|
+
- **onPrimaryContainer**: Text on primary container (tone 10 in light, 90 in dark)
|
|
22
|
+
|
|
23
|
+
### Secondary Colors
|
|
24
|
+
- **secondary**: Supporting brand color
|
|
25
|
+
- **onSecondary**: Text/icons on secondary
|
|
26
|
+
- **secondaryContainer**: Light container variant
|
|
27
|
+
- **onSecondaryContainer**: Text on secondary container
|
|
28
|
+
|
|
29
|
+
### Tertiary Colors
|
|
30
|
+
- **tertiary**: Accent for special emphasis
|
|
31
|
+
- **onTertiary**: Text/icons on tertiary
|
|
32
|
+
- **tertiaryContainer**: Light container variant
|
|
33
|
+
- **onTertiaryContainer**: Text on tertiary container
|
|
34
|
+
|
|
35
|
+
### Surface Colors
|
|
36
|
+
- **surface**: Main background color (tone 99 in light, 10 in dark)
|
|
37
|
+
- **onSurface**: Primary text color (tone 10 in light, 90 in dark)
|
|
38
|
+
- **surfaceVariant**: Secondary background (tone 95 in light, 30 in dark)
|
|
39
|
+
- **onSurfaceVariant**: Secondary text (tone 30 in light, 80 in dark)
|
|
40
|
+
|
|
41
|
+
### Additional Roles
|
|
42
|
+
- **error**: Error states (hue ~25, chroma 84)
|
|
43
|
+
- **outline**: Borders and dividers
|
|
44
|
+
- **shadow**: Shadow colors
|
|
45
|
+
- **scrim**: Modal overlays
|
|
46
|
+
- **inverseSurface**: Inverted surface for emphasis
|
|
47
|
+
- **inverseOnSurface**: Text on inverted surface
|
|
48
|
+
- **inversePrimary**: Primary color on inverted surface
|
|
49
|
+
|
|
50
|
+
## Tonal Palettes
|
|
51
|
+
|
|
52
|
+
Material Design 3 uses 13 standard tones for each color palette:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99, 100]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Tone Usage Guidelines
|
|
59
|
+
|
|
60
|
+
| Tone Range | Light Theme Usage | Dark Theme Usage |
|
|
61
|
+
|------------|------------------|------------------|
|
|
62
|
+
| 0-10 | On-colors, high emphasis text | Surfaces, containers |
|
|
63
|
+
| 20-40 | Primary actions, emphasis | On-colors, text |
|
|
64
|
+
| 50 | Neutral midpoint | Neutral midpoint |
|
|
65
|
+
| 60-80 | Containers, surfaces | Primary actions |
|
|
66
|
+
| 90-100 | Backgrounds, surfaces | On-colors, text |
|
|
67
|
+
|
|
68
|
+
## Key Colors
|
|
69
|
+
|
|
70
|
+
From a single source color, Material Design generates five key colors:
|
|
71
|
+
|
|
72
|
+
1. **Primary**: Directly from source color
|
|
73
|
+
2. **Secondary**: Complementary color (hue shift ~60°, chroma × 0.5)
|
|
74
|
+
3. **Tertiary**: Triadic color (hue shift ~120°, chroma × 0.7)
|
|
75
|
+
4. **Error**: Standardized error color (hue 25, chroma 84)
|
|
76
|
+
5. **Neutral**: Grayscale derived from source (chroma 4-8)
|
|
77
|
+
|
|
78
|
+
## Scheme Variants
|
|
79
|
+
|
|
80
|
+
Material Design 3 offers multiple scheme variants for different moods:
|
|
81
|
+
|
|
82
|
+
### Tonal Spot (Default)
|
|
83
|
+
- Balanced use of primary color
|
|
84
|
+
- Secondary and tertiary are complementary
|
|
85
|
+
- Most versatile for general use
|
|
86
|
+
|
|
87
|
+
### Fidelity
|
|
88
|
+
- Preserves source color's exact appearance
|
|
89
|
+
- Adjusts tones to maintain chroma
|
|
90
|
+
- Best for brand-critical applications
|
|
91
|
+
|
|
92
|
+
### Vibrant
|
|
93
|
+
- Higher chroma across all colors
|
|
94
|
+
- More colorful, energetic appearance
|
|
95
|
+
- Good for creative, playful apps
|
|
96
|
+
|
|
97
|
+
### Expressive
|
|
98
|
+
- Unexpected color combinations
|
|
99
|
+
- Creative hue rotations
|
|
100
|
+
- For bold, artistic interfaces
|
|
101
|
+
|
|
102
|
+
### Neutral
|
|
103
|
+
- Minimal color, maximum elegance
|
|
104
|
+
- Reduced chroma values
|
|
105
|
+
- Professional, understated look
|
|
106
|
+
|
|
107
|
+
### Monochrome
|
|
108
|
+
- Single hue, varying tones
|
|
109
|
+
- Ultimate minimalism
|
|
110
|
+
- Focus on content over color
|
|
111
|
+
|
|
112
|
+
## Contrast Levels
|
|
113
|
+
|
|
114
|
+
Material Design 3 supports three contrast levels:
|
|
115
|
+
|
|
116
|
+
### Default (0.0)
|
|
117
|
+
- WCAG AA compliant
|
|
118
|
+
- 4.5:1 for normal text
|
|
119
|
+
- 3:1 for large text
|
|
120
|
+
|
|
121
|
+
### Medium (+0.5)
|
|
122
|
+
- Enhanced readability
|
|
123
|
+
- ~6:1 for normal text
|
|
124
|
+
- Better for outdoor/bright conditions
|
|
125
|
+
|
|
126
|
+
### High (+1.0)
|
|
127
|
+
- WCAG AAA compliant
|
|
128
|
+
- 7:1 for normal text
|
|
129
|
+
- Maximum accessibility
|
|
130
|
+
|
|
131
|
+
## Implementation with Coolors MCP
|
|
132
|
+
|
|
133
|
+
### Generate Material Theme
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
// From a source color
|
|
137
|
+
{
|
|
138
|
+
"name": "generate_material_theme",
|
|
139
|
+
"arguments": {
|
|
140
|
+
"sourceColor": "#6366F1"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Create Tonal Palette
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// Generate standard Material tones
|
|
149
|
+
{
|
|
150
|
+
"name": "generate_tonal_palette",
|
|
151
|
+
"arguments": {
|
|
152
|
+
"color": "#6366F1",
|
|
153
|
+
"tones": [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99, 100]
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Generate Theme CSS
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
// Create CSS custom properties
|
|
162
|
+
{
|
|
163
|
+
"name": "generate_theme_css",
|
|
164
|
+
"arguments": {
|
|
165
|
+
"sourceColor": "#6366F1",
|
|
166
|
+
"prefix": "md"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Color Harmonization
|
|
172
|
+
|
|
173
|
+
Material Design uses harmonization to ensure colors work together:
|
|
174
|
+
|
|
175
|
+
### Harmonization Algorithm
|
|
176
|
+
1. Analyze hue relationships
|
|
177
|
+
2. Adjust hues toward harmony angles (0°, 60°, 120°, 180°, 240°, 300°)
|
|
178
|
+
3. Maintain original chroma and tone
|
|
179
|
+
4. Blend based on harmonization strength
|
|
180
|
+
|
|
181
|
+
### Example
|
|
182
|
+
```javascript
|
|
183
|
+
{
|
|
184
|
+
"name": "harmonize_colors",
|
|
185
|
+
"arguments": {
|
|
186
|
+
"colors": ["#6366F1", "#EC4899", "#10B981"],
|
|
187
|
+
"factor": 0.5
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Design Tokens
|
|
193
|
+
|
|
194
|
+
Material Design 3 uses design tokens for consistent application:
|
|
195
|
+
|
|
196
|
+
### Token Structure
|
|
197
|
+
```css
|
|
198
|
+
/* Color tokens */
|
|
199
|
+
--md-sys-color-primary: #6366F1;
|
|
200
|
+
--md-sys-color-on-primary: #FFFFFF;
|
|
201
|
+
--md-sys-color-primary-container: #E0E2FF;
|
|
202
|
+
--md-sys-color-on-primary-container: #000747;
|
|
203
|
+
|
|
204
|
+
/* Elevation tokens */
|
|
205
|
+
--md-sys-elevation-level0: 0px;
|
|
206
|
+
--md-sys-elevation-level1: 1px;
|
|
207
|
+
--md-sys-elevation-level2: 3px;
|
|
208
|
+
|
|
209
|
+
/* Shape tokens */
|
|
210
|
+
--md-sys-shape-corner-small: 4px;
|
|
211
|
+
--md-sys-shape-corner-medium: 8px;
|
|
212
|
+
--md-sys-shape-corner-large: 16px;
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Accessibility Considerations
|
|
216
|
+
|
|
217
|
+
Material Design 3 ensures accessibility through:
|
|
218
|
+
|
|
219
|
+
1. **Guaranteed Contrast**: Tone relationships ensure WCAG compliance
|
|
220
|
+
2. **Color Independence**: Information not conveyed by color alone
|
|
221
|
+
3. **Predictable Patterns**: Consistent color role usage
|
|
222
|
+
4. **Adjustable Contrast**: Support for user preferences
|
|
223
|
+
|
|
224
|
+
## Dynamic Color Algorithm
|
|
225
|
+
|
|
226
|
+
The complete process for generating a Material theme:
|
|
227
|
+
|
|
228
|
+
1. **Extract source color** from image or user input
|
|
229
|
+
2. **Generate key colors** through hue/chroma manipulation
|
|
230
|
+
3. **Create tonal palettes** for each key color
|
|
231
|
+
4. **Map tones to roles** based on scheme variant
|
|
232
|
+
5. **Adjust for contrast** requirements
|
|
233
|
+
6. **Apply fidelity corrections** if needed
|
|
234
|
+
7. **Output theme** as usable color values
|
|
235
|
+
|
|
236
|
+
## Best Practices
|
|
237
|
+
|
|
238
|
+
### Do's
|
|
239
|
+
- ✅ Use semantic color roles consistently
|
|
240
|
+
- ✅ Test with all three contrast levels
|
|
241
|
+
- ✅ Validate color combinations for accessibility
|
|
242
|
+
- ✅ Consider both light and dark themes
|
|
243
|
+
- ✅ Use harmonization for multiple brand colors
|
|
244
|
+
|
|
245
|
+
### Don'ts
|
|
246
|
+
- ❌ Override tone assignments arbitrarily
|
|
247
|
+
- ❌ Use colors outside the tonal palettes
|
|
248
|
+
- ❌ Ignore contrast requirements
|
|
249
|
+
- ❌ Mix scheme variants in one interface
|
|
250
|
+
- ❌ Use extreme chroma values for large surfaces
|
|
251
|
+
|
|
252
|
+
## Integration Examples
|
|
253
|
+
|
|
254
|
+
### React/CSS
|
|
255
|
+
```css
|
|
256
|
+
:root {
|
|
257
|
+
--md-sys-color-primary: rgb(99, 102, 241);
|
|
258
|
+
--md-sys-color-surface: rgb(252, 252, 255);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.button-primary {
|
|
262
|
+
background: var(--md-sys-color-primary);
|
|
263
|
+
color: var(--md-sys-color-on-primary);
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Tailwind CSS
|
|
268
|
+
```javascript
|
|
269
|
+
// tailwind.config.js
|
|
270
|
+
module.exports = {
|
|
271
|
+
theme: {
|
|
272
|
+
extend: {
|
|
273
|
+
colors: {
|
|
274
|
+
'md-primary': 'var(--md-sys-color-primary)',
|
|
275
|
+
'md-surface': 'var(--md-sys-color-surface)',
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Advanced Features
|
|
283
|
+
|
|
284
|
+
### Dislike Prevention
|
|
285
|
+
Material Design automatically detects and adjusts universally disliked colors (dark yellow-greens that resemble biological waste) by shifting their hue and increasing tone.
|
|
286
|
+
|
|
287
|
+
### Content-Based Schemes
|
|
288
|
+
Generate schemes that adapt to content:
|
|
289
|
+
- Album artwork → Music player theme
|
|
290
|
+
- Product images → E-commerce theme
|
|
291
|
+
- User photos → Gallery theme
|
|
292
|
+
|
|
293
|
+
### Cross-Platform Consistency
|
|
294
|
+
The same source color produces identical themes across:
|
|
295
|
+
- Android (Material You)
|
|
296
|
+
- Web (Material Web)
|
|
297
|
+
- Flutter
|
|
298
|
+
- Coolors MCP
|
|
299
|
+
|
|
300
|
+
## See Also
|
|
301
|
+
|
|
302
|
+
- [HCT Color System](./hct.md) - Understanding the HCT color space
|
|
303
|
+
- [Color Spaces](./color-spaces.md) - Color space comparisons
|
|
304
|
+
- [Accessibility](./accessibility.md) - Contrast and accessibility
|
|
305
|
+
- [Image Analysis](./image-analysis.md) - Extracting colors from images
|
|
306
|
+
- [Material Design Guidelines](https://m3.material.io) - Official documentation
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
# Theme Matching Algorithm
|
|
2
|
+
|
|
3
|
+
Coolors MCP provides sophisticated algorithms for matching colors to CSS theme variables, enabling automated refactoring and consistent theming across applications.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The theme matching system analyzes CSS variables and finds the best matches for any given color based on multiple factors:
|
|
8
|
+
|
|
9
|
+
- **Perceptual similarity** using HCT color space
|
|
10
|
+
- **Semantic context** from variable naming
|
|
11
|
+
- **Accessibility constraints** for contrast requirements
|
|
12
|
+
- **Confidence scoring** for replacement decisions
|
|
13
|
+
|
|
14
|
+
## How It Works
|
|
15
|
+
|
|
16
|
+
### 1. CSS Variable Parsing
|
|
17
|
+
|
|
18
|
+
The system first extracts and analyzes CSS variables:
|
|
19
|
+
|
|
20
|
+
```css
|
|
21
|
+
/* Input CSS with theme variables */
|
|
22
|
+
:root {
|
|
23
|
+
--color-primary-50: #eef2ff;
|
|
24
|
+
--color-primary-500: #6366f1;
|
|
25
|
+
--color-primary-900: #312e81;
|
|
26
|
+
--color-surface: #ffffff;
|
|
27
|
+
--color-text: #1f2937;
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. Semantic Role Detection
|
|
32
|
+
|
|
33
|
+
Variable names are analyzed to detect semantic roles:
|
|
34
|
+
|
|
35
|
+
| Pattern | Detected Role | Usage Context |
|
|
36
|
+
|---------|--------------|---------------|
|
|
37
|
+
| `*primary*` | Primary | Main brand color |
|
|
38
|
+
| `*secondary*` | Secondary | Supporting color |
|
|
39
|
+
| `*surface*`, `*background*` | Surface | Backgrounds |
|
|
40
|
+
| `*text*`, `*foreground*` | Text | Typography |
|
|
41
|
+
| `*border*`, `*outline*` | Outline | Borders, dividers |
|
|
42
|
+
| `*error*`, `*danger*` | Error | Error states |
|
|
43
|
+
| `*success*` | Success | Success states |
|
|
44
|
+
| `*warning*` | Warning | Warning states |
|
|
45
|
+
|
|
46
|
+
### 3. Multi-Factor Scoring
|
|
47
|
+
|
|
48
|
+
Each potential match is scored based on multiple factors:
|
|
49
|
+
|
|
50
|
+
#### Perceptual Distance (60% weight)
|
|
51
|
+
Using HCT color space for accurate perception:
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
function calculatePerceptualDistance(color1, color2) {
|
|
55
|
+
const hct1 = toHct(color1);
|
|
56
|
+
const hct2 = toHct(color2);
|
|
57
|
+
|
|
58
|
+
// Weighted distance (tone weighted 2x for UI importance)
|
|
59
|
+
return Math.sqrt(
|
|
60
|
+
Math.pow(hct1.hue - hct2.hue, 2) +
|
|
61
|
+
Math.pow(hct1.chroma - hct2.chroma, 2) +
|
|
62
|
+
Math.pow((hct1.tone - hct2.tone) * 2, 2)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### Semantic Context (20% weight)
|
|
68
|
+
Matching semantic roles improves accuracy:
|
|
69
|
+
|
|
70
|
+
```javascript
|
|
71
|
+
function calculateSemanticScore(colorRole, variableRole, usage) {
|
|
72
|
+
// Perfect match
|
|
73
|
+
if (colorRole === variableRole) return 1.0;
|
|
74
|
+
|
|
75
|
+
// Compatible roles
|
|
76
|
+
if (isCompatible(colorRole, variableRole, usage)) return 0.7;
|
|
77
|
+
|
|
78
|
+
// Incompatible
|
|
79
|
+
return 0.3;
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### Accessibility Score (20% weight)
|
|
84
|
+
Ensuring contrast requirements are met:
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
function calculateAccessibilityScore(color, background, requiredRatio) {
|
|
88
|
+
const actualRatio = getContrastRatio(color, background);
|
|
89
|
+
|
|
90
|
+
if (actualRatio >= requiredRatio) {
|
|
91
|
+
return 1.0; // Meets requirements
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Partial credit based on how close
|
|
95
|
+
return actualRatio / requiredRatio;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 4. Confidence Calculation
|
|
100
|
+
|
|
101
|
+
Final confidence score determines replacement:
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
confidence = (
|
|
105
|
+
perceptualScore * 0.6 +
|
|
106
|
+
semanticScore * 0.2 +
|
|
107
|
+
accessibilityScore * 0.2
|
|
108
|
+
) * 100;
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Matching Strategies
|
|
112
|
+
|
|
113
|
+
### Exact Matching
|
|
114
|
+
For colors that exactly match a theme variable:
|
|
115
|
+
- **Confidence**: 100%
|
|
116
|
+
- **Action**: Direct replacement
|
|
117
|
+
- **Example**: `#6366f1` → `var(--color-primary-500)`
|
|
118
|
+
|
|
119
|
+
### Nearest Neighbor
|
|
120
|
+
For colors close to theme variables:
|
|
121
|
+
- **Confidence**: 70-99%
|
|
122
|
+
- **Action**: Replace with warning
|
|
123
|
+
- **Example**: `#6365f0` → `var(--color-primary-500)` (99% confidence)
|
|
124
|
+
|
|
125
|
+
### Semantic Matching
|
|
126
|
+
For colors matching expected roles:
|
|
127
|
+
- **Confidence**: 60-90%
|
|
128
|
+
- **Action**: Context-aware replacement
|
|
129
|
+
- **Example**: Border color `#e5e7eb` → `var(--color-border)`
|
|
130
|
+
|
|
131
|
+
### Fallback Matching
|
|
132
|
+
When no good matches exist:
|
|
133
|
+
- **Confidence**: <60%
|
|
134
|
+
- **Action**: Keep original or create new variable
|
|
135
|
+
- **Example**: `#123456` → `/* No match: #123456 */`
|
|
136
|
+
|
|
137
|
+
## Usage Examples
|
|
138
|
+
|
|
139
|
+
### Single Color Matching
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// Find best theme variable for a color
|
|
143
|
+
{
|
|
144
|
+
"name": "match_theme_color",
|
|
145
|
+
"arguments": {
|
|
146
|
+
"color": "#6366f1",
|
|
147
|
+
"themeCSS": ":root { --color-primary: #6366f1; }",
|
|
148
|
+
"context": "background",
|
|
149
|
+
"minConfidence": 70
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Response
|
|
154
|
+
{
|
|
155
|
+
"match": "--color-primary",
|
|
156
|
+
"confidence": 100,
|
|
157
|
+
"originalColor": "#6366f1",
|
|
158
|
+
"themeColor": "#6366f1",
|
|
159
|
+
"distance": 0
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### CSS Refactoring
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
// Refactor entire CSS file
|
|
167
|
+
{
|
|
168
|
+
"name": "refactor_css_with_theme",
|
|
169
|
+
"arguments": {
|
|
170
|
+
"css": ".button { background: #6366f1; color: #ffffff; }",
|
|
171
|
+
"themeCSS": ":root { --primary: #6366f1; --white: #ffffff; }",
|
|
172
|
+
"minConfidence": 70,
|
|
173
|
+
"preserveOriginal": true
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Result
|
|
178
|
+
.button {
|
|
179
|
+
background: var(--primary); /* was: #6366f1 */
|
|
180
|
+
color: var(--white); /* was: #ffffff */
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Batch Processing
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
// Match multiple colors at once
|
|
188
|
+
{
|
|
189
|
+
"name": "match_theme_colors_batch",
|
|
190
|
+
"arguments": {
|
|
191
|
+
"colors": ["#6366f1", "#ec4899", "#10b981"],
|
|
192
|
+
"themeCSS": "/* theme variables */",
|
|
193
|
+
"context": "accent"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Advanced Features
|
|
199
|
+
|
|
200
|
+
### Context-Aware Matching
|
|
201
|
+
|
|
202
|
+
Different contexts have different priorities:
|
|
203
|
+
|
|
204
|
+
| Context | Priority | Factors |
|
|
205
|
+
|---------|----------|---------|
|
|
206
|
+
| `text` | Contrast > Semantic > Color | Readability first |
|
|
207
|
+
| `background` | Color > Semantic > Contrast | Visual accuracy |
|
|
208
|
+
| `border` | Semantic > Color > Contrast | Structural meaning |
|
|
209
|
+
| `accent` | Color > Contrast > Semantic | Brand consistency |
|
|
210
|
+
| `decorative` | Color > Semantic > Contrast | Visual appeal |
|
|
211
|
+
|
|
212
|
+
### Threshold Configuration
|
|
213
|
+
|
|
214
|
+
Fine-tune matching behavior:
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
{
|
|
218
|
+
minConfidence: 70, // Minimum confidence for replacement
|
|
219
|
+
maxDistance: 10, // Maximum perceptual distance
|
|
220
|
+
requireAccessibility: true, // Enforce contrast requirements
|
|
221
|
+
preserveOriginal: true // Keep original as comment
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Smart Variable Creation
|
|
226
|
+
|
|
227
|
+
When no match exists above threshold:
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
// Input: #123456 with no close match
|
|
231
|
+
// Output:
|
|
232
|
+
:root {
|
|
233
|
+
--color-custom-1: #123456; /* Auto-generated */
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.element {
|
|
237
|
+
color: var(--color-custom-1);
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Implementation Details
|
|
242
|
+
|
|
243
|
+
### Parser Architecture
|
|
244
|
+
|
|
245
|
+
1. **Tokenization**: Break CSS into tokens
|
|
246
|
+
2. **AST Building**: Create abstract syntax tree
|
|
247
|
+
3. **Variable Extraction**: Find all custom properties
|
|
248
|
+
4. **Color Detection**: Identify color values
|
|
249
|
+
5. **Context Analysis**: Determine usage context
|
|
250
|
+
|
|
251
|
+
### Matching Pipeline
|
|
252
|
+
|
|
253
|
+
```
|
|
254
|
+
Input Color → HCT Conversion → Distance Calculation
|
|
255
|
+
↓
|
|
256
|
+
Final Match ← Confidence Score ← Multi-Factor Analysis
|
|
257
|
+
↑
|
|
258
|
+
Semantic & Accessibility
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Performance Optimization
|
|
262
|
+
|
|
263
|
+
- **Caching**: Theme variables cached after first parse
|
|
264
|
+
- **Indexing**: Pre-computed HCT values for all theme colors
|
|
265
|
+
- **Batching**: Process multiple colors in single pass
|
|
266
|
+
- **Early Exit**: Skip processing if exact match found
|
|
267
|
+
|
|
268
|
+
## Best Practices
|
|
269
|
+
|
|
270
|
+
### Theme Variable Naming
|
|
271
|
+
|
|
272
|
+
Use semantic, hierarchical naming:
|
|
273
|
+
|
|
274
|
+
```css
|
|
275
|
+
/* Good - Clear hierarchy and purpose */
|
|
276
|
+
--color-primary-50
|
|
277
|
+
--color-primary-500
|
|
278
|
+
--color-primary-900
|
|
279
|
+
--color-text-primary
|
|
280
|
+
--color-text-secondary
|
|
281
|
+
|
|
282
|
+
/* Avoid - Ambiguous or color-specific */
|
|
283
|
+
--blue
|
|
284
|
+
--light-blue
|
|
285
|
+
--text-color
|
|
286
|
+
--col1
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Confidence Thresholds
|
|
290
|
+
|
|
291
|
+
Recommended thresholds by use case:
|
|
292
|
+
|
|
293
|
+
| Use Case | Min Confidence | Rationale |
|
|
294
|
+
|----------|---------------|-----------|
|
|
295
|
+
| Production refactor | 85% | High accuracy needed |
|
|
296
|
+
| Development assist | 70% | Balance speed/accuracy |
|
|
297
|
+
| Exploration | 50% | See all possibilities |
|
|
298
|
+
| Exact only | 100% | No false positives |
|
|
299
|
+
|
|
300
|
+
### Handling Edge Cases
|
|
301
|
+
|
|
302
|
+
#### Very Similar Colors
|
|
303
|
+
```css
|
|
304
|
+
/* Original */
|
|
305
|
+
.element1 { color: #6366f1; }
|
|
306
|
+
.element2 { color: #6366f0; }
|
|
307
|
+
|
|
308
|
+
/* After matching - both map to same variable */
|
|
309
|
+
.element1 { color: var(--color-primary); }
|
|
310
|
+
.element2 { color: var(--color-primary); }
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
#### No Good Matches
|
|
314
|
+
```css
|
|
315
|
+
/* Original */
|
|
316
|
+
.special { background: #742a2a; }
|
|
317
|
+
|
|
318
|
+
/* After - preserved with comment */
|
|
319
|
+
.special {
|
|
320
|
+
background: #742a2a; /* No theme match (confidence: 45%) */
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Integration Patterns
|
|
325
|
+
|
|
326
|
+
### Build Tools
|
|
327
|
+
|
|
328
|
+
```javascript
|
|
329
|
+
// Webpack plugin example
|
|
330
|
+
module.exports = {
|
|
331
|
+
plugins: [
|
|
332
|
+
new ThemeMatcherPlugin({
|
|
333
|
+
themeFile: './theme.css',
|
|
334
|
+
minConfidence: 80,
|
|
335
|
+
generateReport: true
|
|
336
|
+
})
|
|
337
|
+
]
|
|
338
|
+
};
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### CI/CD Pipeline
|
|
342
|
+
|
|
343
|
+
```yaml
|
|
344
|
+
# GitHub Actions example
|
|
345
|
+
- name: Refactor CSS with Theme
|
|
346
|
+
run: |
|
|
347
|
+
coolors-mcp refactor \
|
|
348
|
+
--input src/styles \
|
|
349
|
+
--theme src/theme.css \
|
|
350
|
+
--confidence 85 \
|
|
351
|
+
--report
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### IDE Extensions
|
|
355
|
+
|
|
356
|
+
```javascript
|
|
357
|
+
// VS Code extension config
|
|
358
|
+
"coolors.themeMatching": {
|
|
359
|
+
"enabled": true,
|
|
360
|
+
"themeFile": "${workspaceFolder}/theme.css",
|
|
361
|
+
"minConfidence": 75,
|
|
362
|
+
"showInlineHints": true
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## Troubleshooting
|
|
367
|
+
|
|
368
|
+
### Common Issues
|
|
369
|
+
|
|
370
|
+
#### Low Confidence Scores
|
|
371
|
+
- **Cause**: Colors too different from theme
|
|
372
|
+
- **Solution**: Lower threshold or add more theme variables
|
|
373
|
+
|
|
374
|
+
#### Wrong Semantic Matches
|
|
375
|
+
- **Cause**: Ambiguous variable names
|
|
376
|
+
- **Solution**: Use clearer naming conventions
|
|
377
|
+
|
|
378
|
+
#### Accessibility Failures
|
|
379
|
+
- **Cause**: Insufficient contrast with background
|
|
380
|
+
- **Solution**: Adjust theme colors or use different variables
|
|
381
|
+
|
|
382
|
+
### Debugging
|
|
383
|
+
|
|
384
|
+
Enable detailed logging:
|
|
385
|
+
|
|
386
|
+
```javascript
|
|
387
|
+
{
|
|
388
|
+
"generateReport": true,
|
|
389
|
+
"verboseLogging": true,
|
|
390
|
+
"showDistanceMatrix": true
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## See Also
|
|
395
|
+
|
|
396
|
+
- [Color Spaces](./color-spaces.md) - Understanding color models
|
|
397
|
+
- [HCT System](./hct.md) - Perceptual color space
|
|
398
|
+
- [Accessibility](./accessibility.md) - Contrast requirements
|
|
399
|
+
- [Material Design](./material-design.md) - Theme generation
|