@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.
Files changed (197) hide show
  1. package/.claude/settings.local.json +39 -0
  2. package/.env +2 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +73 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +71 -0
  5. package/.github/pull_request_template.md +97 -0
  6. package/.github/workflows/ci.yml +127 -0
  7. package/.github/workflows/deploy-docs.yml +56 -0
  8. package/.github/workflows/release.yml +99 -0
  9. package/.mcp.json +12 -0
  10. package/.prettierignore +1 -0
  11. package/CLAUDE.md +201 -0
  12. package/DOCUMENTATION.md +274 -0
  13. package/GEMINI.md +54 -0
  14. package/LICENSE +21 -0
  15. package/README.md +401 -0
  16. package/demo/content_based_color.png +0 -0
  17. package/demo/music-player.html +621 -0
  18. package/demo/podcast-player.html +903 -0
  19. package/dist/bin/coolors-mcp.d.ts +1 -0
  20. package/dist/bin/coolors-mcp.js +154 -0
  21. package/dist/bin/coolors-mcp.js.map +1 -0
  22. package/dist/bin/server.d.ts +1 -0
  23. package/dist/bin/server.js +3292 -0
  24. package/dist/bin/server.js.map +1 -0
  25. package/dist/chunk-IQ7NN26V.js +114 -0
  26. package/dist/chunk-IQ7NN26V.js.map +1 -0
  27. package/dist/chunk-P3ARRKLS.js +1214 -0
  28. package/dist/chunk-P3ARRKLS.js.map +1 -0
  29. package/dist/color/index.d.ts +716 -0
  30. package/dist/color/index.js +153 -0
  31. package/dist/color/index.js.map +1 -0
  32. package/dist/coolors-mcp.d.ts +136 -0
  33. package/dist/coolors-mcp.js +7 -0
  34. package/dist/coolors-mcp.js.map +1 -0
  35. package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js +93 -0
  36. package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js.map +7 -0
  37. package/docs/.vitepress/cache/deps/_metadata.json +127 -0
  38. package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js +9 -0
  39. package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js.map +7 -0
  40. package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js +12683 -0
  41. package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js.map +7 -0
  42. package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js +9719 -0
  43. package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js.map +7 -0
  44. package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js +4710 -0
  45. package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js.map +7 -0
  46. package/docs/.vitepress/cache/deps/cytoscape.js +30278 -0
  47. package/docs/.vitepress/cache/deps/cytoscape.js.map +7 -0
  48. package/docs/.vitepress/cache/deps/dayjs.js +285 -0
  49. package/docs/.vitepress/cache/deps/dayjs.js.map +7 -0
  50. package/docs/.vitepress/cache/deps/debug.js +468 -0
  51. package/docs/.vitepress/cache/deps/debug.js.map +7 -0
  52. package/docs/.vitepress/cache/deps/package.json +3 -0
  53. package/docs/.vitepress/cache/deps/prismjs.js +1466 -0
  54. package/docs/.vitepress/cache/deps/prismjs.js.map +7 -0
  55. package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js +228 -0
  56. package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js.map +7 -0
  57. package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js +142 -0
  58. package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js.map +7 -0
  59. package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js +27 -0
  60. package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js.map +7 -0
  61. package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js +65 -0
  62. package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js.map +7 -0
  63. package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js +53 -0
  64. package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js.map +7 -0
  65. package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js +73 -0
  66. package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js.map +7 -0
  67. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4507 -0
  68. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
  69. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +584 -0
  70. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
  71. package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +1146 -0
  72. package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +7 -0
  73. package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +1667 -0
  74. package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +7 -0
  75. package/docs/.vitepress/cache/deps/vitepress___minisearch.js +1814 -0
  76. package/docs/.vitepress/cache/deps/vitepress___minisearch.js.map +7 -0
  77. package/docs/.vitepress/cache/deps/vue.js +344 -0
  78. package/docs/.vitepress/cache/deps/vue.js.map +7 -0
  79. package/docs/.vitepress/components/ClientGrid.vue +125 -0
  80. package/docs/.vitepress/components/CodeBlock.vue +231 -0
  81. package/docs/.vitepress/components/ConfigModal.vue +477 -0
  82. package/docs/.vitepress/components/DiagramModal.vue +528 -0
  83. package/docs/.vitepress/components/TroubleshootingModal.vue +472 -0
  84. package/docs/.vitepress/config.js +162 -0
  85. package/docs/.vitepress/theme/FundingLayout.vue +251 -0
  86. package/docs/.vitepress/theme/Layout.vue +134 -0
  87. package/docs/.vitepress/theme/components/AdBanner.vue +317 -0
  88. package/docs/.vitepress/theme/components/AdPlaceholder.vue +78 -0
  89. package/docs/.vitepress/theme/components/FundingEffects.vue +322 -0
  90. package/docs/.vitepress/theme/components/FundingHero.vue +345 -0
  91. package/docs/.vitepress/theme/components/SupportSection.vue +511 -0
  92. package/docs/.vitepress/theme/custom-app.css +339 -0
  93. package/docs/.vitepress/theme/custom.css +699 -0
  94. package/docs/.vitepress/theme/index.js +25 -0
  95. package/docs/README.md +198 -0
  96. package/docs/concepts/accessibility.md +473 -0
  97. package/docs/concepts/color-spaces.md +222 -0
  98. package/docs/concepts/distance-metrics.md +384 -0
  99. package/docs/concepts/hct.md +261 -0
  100. package/docs/concepts/image-analysis.md +396 -0
  101. package/docs/concepts/material-design.md +306 -0
  102. package/docs/concepts/theme-matching.md +399 -0
  103. package/docs/examples/basic-colors.md +490 -0
  104. package/docs/examples/creating-themes.md +898 -0
  105. package/docs/examples/css-refactoring.md +824 -0
  106. package/docs/examples/image-extraction.md +882 -0
  107. package/docs/getting-started.md +366 -0
  108. package/docs/index.md +190 -0
  109. package/docs/installation.md +157 -0
  110. package/docs/tools/README.md +234 -0
  111. package/docs/tools/accessibility.md +614 -0
  112. package/docs/tools/color-operations.md +374 -0
  113. package/docs/tools/image-extraction.md +624 -0
  114. package/docs/tools/material-design.md +347 -0
  115. package/docs/tools/theme-matching.md +552 -0
  116. package/eslint.config.ts +14 -0
  117. package/examples/theme-matching.md +113 -0
  118. package/jsr.json +7 -0
  119. package/mcp-config.json +8 -0
  120. package/note.md +35 -0
  121. package/package.json +122 -0
  122. package/research_results.md +53 -0
  123. package/src/bin/coolors-mcp.ts +194 -0
  124. package/src/bin/server.ts +61 -0
  125. package/src/color/__tests__/conversions-argb.test.ts +198 -0
  126. package/src/color/__tests__/extract-colors.test.ts +360 -0
  127. package/src/color/__tests__/image-utils.test.ts +242 -0
  128. package/src/color/__tests__/reference-colors.test.ts +278 -0
  129. package/src/color/__tests__/round-trip.test.ts +197 -0
  130. package/src/color/conversions.test.ts +402 -0
  131. package/src/color/conversions.ts +393 -0
  132. package/src/color/dislike/__tests__/dislike-analyzer.test.ts +248 -0
  133. package/src/color/dislike/dislike-analyzer.ts +114 -0
  134. package/src/color/extract-colors.ts +228 -0
  135. package/src/color/hct/__tests__/hct-class.test.ts +232 -0
  136. package/src/color/hct/harmonization.ts +204 -0
  137. package/src/color/hct/hct-class.ts +109 -0
  138. package/src/color/hct/hct-solver.ts +168 -0
  139. package/src/color/hct/index.ts +39 -0
  140. package/src/color/hct/tonal-palette.ts +211 -0
  141. package/src/color/hct/types.ts +88 -0
  142. package/src/color/image-utils.ts +79 -0
  143. package/src/color/index.ts +87 -0
  144. package/src/color/material-theme.ts +157 -0
  145. package/src/color/metrics.test.ts +276 -0
  146. package/src/color/metrics.ts +281 -0
  147. package/src/color/quantize/__tests__/quantizer_celebi.test.ts +195 -0
  148. package/src/color/quantize/lab_point_provider.ts +55 -0
  149. package/src/color/quantize/point_provider.ts +27 -0
  150. package/src/color/quantize/quantizer_celebi.ts +51 -0
  151. package/src/color/quantize/quantizer_celebi_test.ts +71 -0
  152. package/src/color/quantize/quantizer_map.ts +47 -0
  153. package/src/color/quantize/quantizer_wsmeans.ts +232 -0
  154. package/src/color/quantize/quantizer_wu.ts +472 -0
  155. package/src/color/score/__tests__/score.test.ts +224 -0
  156. package/src/color/score/score.ts +175 -0
  157. package/src/color/types.ts +151 -0
  158. package/src/color/utils/color_utils.ts +292 -0
  159. package/src/color/utils/math_utils.ts +145 -0
  160. package/src/color/utils.test.ts +403 -0
  161. package/src/color/utils.ts +315 -0
  162. package/src/constants.ts +5 -0
  163. package/src/coolors-mcp.ts +37 -0
  164. package/src/examples/addition.ts +333 -0
  165. package/src/examples/color-demo.ts +125 -0
  166. package/src/examples/custom-logger.ts +201 -0
  167. package/src/examples/oauth-server.ts +113 -0
  168. package/src/examples/session-context.ts +269 -0
  169. package/src/session.ts +116 -0
  170. package/src/theme/__tests__/matcher.test.ts +180 -0
  171. package/src/theme/__tests__/parser.test.ts +148 -0
  172. package/src/theme/__tests__/refactor.test.ts +224 -0
  173. package/src/theme/index.ts +34 -0
  174. package/src/theme/matcher.ts +395 -0
  175. package/src/theme/parser.ts +392 -0
  176. package/src/theme/refactor.ts +360 -0
  177. package/src/theme/types.ts +152 -0
  178. package/src/tools/__tests__/gradient-generator.test.ts +206 -0
  179. package/src/tools/__tests__/palette-with-locks.test.ts +109 -0
  180. package/src/tools/color-conversion.tool.ts +54 -0
  181. package/src/tools/color-distance.tool.ts +41 -0
  182. package/src/tools/colors.ts +31 -0
  183. package/src/tools/contrast-checker.tool.ts +37 -0
  184. package/src/tools/dislike-analyzer.tool.ts +247 -0
  185. package/src/tools/gradient-generator.tool.ts +250 -0
  186. package/src/tools/image-extraction.tools.ts +289 -0
  187. package/src/tools/index.ts +39 -0
  188. package/src/tools/material-theme.tools.ts +250 -0
  189. package/src/tools/palette-generator.tool.ts +135 -0
  190. package/src/tools/palette-with-locks.tool.ts +221 -0
  191. package/src/tools/registry.ts +142 -0
  192. package/src/tools/simple-tools.ts +37 -0
  193. package/src/tools/theme-matching.tools.ts +334 -0
  194. package/src/types.ts +182 -0
  195. package/src/utils.ts +22 -0
  196. package/tsconfig.json +8 -0
  197. package/vitest.config.js +15 -0
@@ -0,0 +1,898 @@
1
+ # Creating Themes Examples
2
+
3
+ Learn how to create comprehensive color themes using Material Design 3 principles and Coolors MCP's advanced theme generation tools.
4
+
5
+ ## Quick Start
6
+
7
+ ### Generate from a Single Color
8
+
9
+ ```javascript
10
+ // Create a complete theme from one color
11
+ "Generate a Material Design theme from #6366f1"
12
+
13
+ // Result: Complete light and dark schemes with:
14
+ // - Primary, secondary, tertiary, neutral, error palettes
15
+ // - Surface colors with elevation levels
16
+ // - Semantic color roles
17
+ // - Accessible color pairs
18
+ ```
19
+
20
+ ### Generate from an Image
21
+
22
+ ```javascript
23
+ // Extract colors and create theme
24
+ "Generate a theme from this logo image"
25
+
26
+ // Process:
27
+ // 1. Extracts dominant colors using Celebi algorithm
28
+ // 2. Scores colors for UI suitability
29
+ // 3. Generates harmonious Material Design theme
30
+ // 4. Provides both light and dark modes
31
+ ```
32
+
33
+ ## Complete Theme Examples
34
+
35
+ ### Brand Theme Creation
36
+
37
+ Starting with brand colors to create a full design system:
38
+
39
+ ```javascript
40
+ // Brand colors
41
+ const brandColors = {
42
+ primary: "#6366f1", // Indigo
43
+ secondary: "#ec4899", // Pink
44
+ accent: "#10b981" // Emerald
45
+ };
46
+
47
+ // Generate Material Design 3 theme
48
+ const theme = generateMaterialTheme({
49
+ sourceColor: brandColors.primary,
50
+ customColors: [
51
+ { name: "brand", color: brandColors.primary },
52
+ { name: "accent", color: brandColors.accent }
53
+ ]
54
+ });
55
+
56
+ // Result structure
57
+ {
58
+ schemes: {
59
+ light: {
60
+ // Primary colors
61
+ primary: "#5256c9",
62
+ onPrimary: "#ffffff",
63
+ primaryContainer: "#e0e0ff",
64
+ onPrimaryContainer: "#070764",
65
+
66
+ // Secondary colors
67
+ secondary: "#5d5d72",
68
+ onSecondary: "#ffffff",
69
+ secondaryContainer: "#e2e0f9",
70
+ onSecondaryContainer: "#1a1b2e",
71
+
72
+ // Tertiary colors
73
+ tertiary: "#79536a",
74
+ onTertiary: "#ffffff",
75
+ tertiaryContainer: "#ffd8ec",
76
+ onTertiaryContainer: "#2e1125",
77
+
78
+ // Surface colors
79
+ surface: "#fffbff",
80
+ onSurface: "#1b1b1f",
81
+ surfaceVariant: "#e4e1ec",
82
+ onSurfaceVariant: "#46464f",
83
+
84
+ // Additional roles
85
+ outline: "#777680",
86
+ outlineVariant: "#c7c5d0",
87
+ shadow: "#000000",
88
+ scrim: "#000000",
89
+ inverseSurface: "#303034",
90
+ inverseOnSurface: "#f2eff4",
91
+ inversePrimary: "#bfc1ff"
92
+ },
93
+ dark: {
94
+ // Dark theme colors...
95
+ }
96
+ },
97
+ palettes: {
98
+ primary: { /* Tonal palette 0-100 */ },
99
+ secondary: { /* Tonal palette 0-100 */ },
100
+ tertiary: { /* Tonal palette 0-100 */ },
101
+ neutral: { /* Tonal palette 0-100 */ },
102
+ neutralVariant: { /* Tonal palette 0-100 */ },
103
+ error: { /* Tonal palette 0-100 */ }
104
+ },
105
+ customColors: [
106
+ {
107
+ name: "brand",
108
+ light: { /* Custom color light scheme */ },
109
+ dark: { /* Custom color dark scheme */ }
110
+ }
111
+ ]
112
+ }
113
+ ```
114
+
115
+ ### Application Themes
116
+
117
+ #### SaaS Dashboard Theme
118
+
119
+ ```javascript
120
+ // Professional dashboard colors
121
+ const dashboardTheme = {
122
+ sourceColor: "#2563eb", // Blue
123
+ variant: "neutral", // Minimal color variation
124
+ contrastLevel: 0 // Standard contrast
125
+ };
126
+
127
+ // Generated theme emphasizes:
128
+ // - Professional appearance
129
+ // - High readability
130
+ // - Clear hierarchy
131
+ // - Subtle color usage
132
+
133
+ const result = {
134
+ light: {
135
+ // Main UI
136
+ surface: "#fffbff",
137
+ surfaceContainer: "#f5f5f5",
138
+ surfaceContainerHigh: "#ebebeb",
139
+
140
+ // Navigation
141
+ primary: "#2563eb",
142
+ primaryContainer: "#dce4ff",
143
+
144
+ // Data visualization
145
+ chart1: "#2563eb",
146
+ chart2: "#10b981",
147
+ chart3: "#f59e0b",
148
+ chart4: "#ef4444",
149
+
150
+ // Status colors
151
+ success: "#10b981",
152
+ warning: "#f59e0b",
153
+ error: "#ef4444",
154
+ info: "#3b82f6"
155
+ }
156
+ };
157
+ ```
158
+
159
+ #### E-commerce Theme
160
+
161
+ ```javascript
162
+ // Vibrant shopping experience
163
+ const ecommerceTheme = {
164
+ sourceColor: "#ec4899", // Pink
165
+ variant: "vibrant", // Higher chroma
166
+ contrastLevel: 0.5 // Medium contrast
167
+ };
168
+
169
+ // Features:
170
+ // - Engaging, energetic colors
171
+ // - Clear CTAs
172
+ // - Product emphasis
173
+ // - Sale/promotion support
174
+
175
+ const shopTheme = {
176
+ light: {
177
+ // Product cards
178
+ surface: "#fffbff",
179
+ surfaceVariant: "#ffeef6",
180
+
181
+ // CTAs
182
+ buyButton: "#ec4899",
183
+ onBuyButton: "#ffffff",
184
+
185
+ // Promotions
186
+ saleBadge: "#ef4444",
187
+ newBadge: "#10b981",
188
+
189
+ // Reviews
190
+ starActive: "#f59e0b",
191
+ starInactive: "#e5e7eb"
192
+ }
193
+ };
194
+ ```
195
+
196
+ #### Music Player Theme
197
+
198
+ ```javascript
199
+ // Dynamic album-based theming
200
+ async function createMusicTheme(albumArtUrl) {
201
+ // Extract colors from album art
202
+ const imageColors = await extractImageColors(albumArtUrl);
203
+
204
+ // Generate theme from dominant color
205
+ const theme = await generateThemeFromImage({
206
+ imageData: imageColors,
207
+ variant: "expressive", // Creative combinations
208
+ contrastLevel: 0
209
+ });
210
+
211
+ return {
212
+ // Player background (dark for immersion)
213
+ playerBg: theme.dark.surface,
214
+
215
+ // Controls
216
+ playButton: theme.dark.primary,
217
+ controls: theme.dark.onSurface,
218
+
219
+ // Progress bar
220
+ progressBar: theme.dark.primary,
221
+ progressBg: theme.dark.surfaceVariant,
222
+
223
+ // Album info
224
+ artistName: theme.dark.onSurface,
225
+ songTitle: theme.dark.onSurfaceVariant,
226
+
227
+ // Visualizer colors
228
+ visualizer: [
229
+ theme.dark.primary,
230
+ theme.dark.secondary,
231
+ theme.dark.tertiary
232
+ ]
233
+ };
234
+ }
235
+ ```
236
+
237
+ ### Design System Creation
238
+
239
+ #### Complete Design System
240
+
241
+ ```javascript
242
+ // Foundation color
243
+ const systemFoundation = "#6366f1";
244
+
245
+ // Generate comprehensive system
246
+ const designSystem = {
247
+ // Core palettes
248
+ palettes: generateTonalPalettes(systemFoundation),
249
+
250
+ // Semantic colors
251
+ semantic: {
252
+ // Actions
253
+ action: {
254
+ primary: "#6366f1",
255
+ secondary: "#8b92ff",
256
+ disabled: "#c7c7c7"
257
+ },
258
+
259
+ // Feedback
260
+ feedback: {
261
+ success: "#10b981",
262
+ warning: "#f59e0b",
263
+ error: "#ef4444",
264
+ info: "#3b82f6"
265
+ },
266
+
267
+ // Content
268
+ content: {
269
+ primary: "#1f2937",
270
+ secondary: "#4b5563",
271
+ disabled: "#9ca3af",
272
+ inverse: "#ffffff"
273
+ }
274
+ },
275
+
276
+ // Component tokens
277
+ components: {
278
+ button: {
279
+ primary: {
280
+ bg: "palette.primary.500",
281
+ text: "white",
282
+ hover: "palette.primary.600",
283
+ active: "palette.primary.700"
284
+ },
285
+ secondary: {
286
+ bg: "palette.primary.100",
287
+ text: "palette.primary.700",
288
+ hover: "palette.primary.200",
289
+ active: "palette.primary.300"
290
+ }
291
+ },
292
+
293
+ input: {
294
+ bg: "white",
295
+ border: "palette.neutral.300",
296
+ text: "content.primary",
297
+ placeholder: "content.secondary",
298
+ focus: "palette.primary.500"
299
+ },
300
+
301
+ card: {
302
+ bg: "white",
303
+ border: "palette.neutral.200",
304
+ shadow: "0 1px 3px rgba(0,0,0,0.1)"
305
+ }
306
+ }
307
+ };
308
+ ```
309
+
310
+ ## Theme Variants
311
+
312
+ ### Material Design 3 Variants
313
+
314
+ Each variant creates a different aesthetic:
315
+
316
+ ```javascript
317
+ // TonalSpot (Default)
318
+ // Balanced, versatile theme
319
+ {
320
+ sourceColor: "#6366f1",
321
+ variant: "tonalSpot"
322
+ }
323
+ // Result: Subtle secondary/tertiary colors
324
+
325
+ // Fidelity
326
+ // Preserves brand color exactly
327
+ {
328
+ sourceColor: "#ff5722", // Brand orange
329
+ variant: "fidelity"
330
+ }
331
+ // Result: Primary palette matches brand precisely
332
+
333
+ // Vibrant
334
+ // Energetic, playful theme
335
+ {
336
+ sourceColor: "#6366f1",
337
+ variant: "vibrant"
338
+ }
339
+ // Result: Higher chroma throughout
340
+
341
+ // Expressive
342
+ // Creative, unexpected combinations
343
+ {
344
+ sourceColor: "#6366f1",
345
+ variant: "expressive"
346
+ }
347
+ // Result: Unique secondary/tertiary colors
348
+
349
+ // Neutral
350
+ // Professional, minimal color
351
+ {
352
+ sourceColor: "#6366f1",
353
+ variant: "neutral"
354
+ }
355
+ // Result: Grayed secondary colors
356
+
357
+ // Monochrome
358
+ // Single-hue theme
359
+ {
360
+ sourceColor: "#6366f1",
361
+ variant: "monochrome"
362
+ }
363
+ // Result: All colors from same hue family
364
+ ```
365
+
366
+ ### Contrast Levels
367
+
368
+ Adjust contrast for accessibility needs:
369
+
370
+ ```javascript
371
+ // Standard contrast (WCAG AA)
372
+ const standard = {
373
+ sourceColor: "#6366f1",
374
+ contrastLevel: 0 // Default
375
+ };
376
+
377
+ // Medium contrast (Between AA and AAA)
378
+ const medium = {
379
+ sourceColor: "#6366f1",
380
+ contrastLevel: 0.5
381
+ };
382
+
383
+ // High contrast (WCAG AAA)
384
+ const high = {
385
+ sourceColor: "#6366f1",
386
+ contrastLevel: 1.0
387
+ };
388
+
389
+ // Results in different tone mappings:
390
+ // Standard: primary on primaryContainer = 4.5:1
391
+ // Medium: primary on primaryContainer = 7:1
392
+ // High: primary on primaryContainer = 10:1
393
+ ```
394
+
395
+ ## Dynamic Theming
396
+
397
+ ### User Preference Based
398
+
399
+ ```javascript
400
+ // Adapt to user preferences
401
+ function createUserTheme(preferences) {
402
+ const {
403
+ favoriteColor,
404
+ contrastNeeds, // "normal", "high", "maximum"
405
+ colorBlindness, // null, "protanopia", "deuteranopia", etc.
406
+ darkMode
407
+ } = preferences;
408
+
409
+ // Base theme
410
+ let theme = generateMaterialTheme({
411
+ sourceColor: favoriteColor,
412
+ contrastLevel: contrastNeeds === "high" ? 1.0 : 0
413
+ });
414
+
415
+ // Adjust for color blindness
416
+ if (colorBlindness) {
417
+ theme = adjustForColorBlindness(theme, colorBlindness);
418
+ }
419
+
420
+ // Return appropriate scheme
421
+ return darkMode ? theme.schemes.dark : theme.schemes.light;
422
+ }
423
+ ```
424
+
425
+ ### Time-Based Themes
426
+
427
+ ```javascript
428
+ // Change theme based on time of day
429
+ function getTimeBasedTheme() {
430
+ const hour = new Date().getHours();
431
+
432
+ if (hour < 6) {
433
+ // Night theme (very dark)
434
+ return {
435
+ sourceColor: "#1a1a2e",
436
+ variant: "monochrome",
437
+ scheme: "dark"
438
+ };
439
+ } else if (hour < 12) {
440
+ // Morning theme (bright, energetic)
441
+ return {
442
+ sourceColor: "#fbbf24",
443
+ variant: "vibrant",
444
+ scheme: "light"
445
+ };
446
+ } else if (hour < 18) {
447
+ // Afternoon theme (balanced)
448
+ return {
449
+ sourceColor: "#3b82f6",
450
+ variant: "tonalSpot",
451
+ scheme: "light"
452
+ };
453
+ } else {
454
+ // Evening theme (warm, relaxed)
455
+ return {
456
+ sourceColor: "#f97316",
457
+ variant: "neutral",
458
+ scheme: "dark"
459
+ };
460
+ }
461
+ }
462
+ ```
463
+
464
+ ### Content-Aware Themes
465
+
466
+ ```javascript
467
+ // Generate theme based on content
468
+ async function createContentTheme(contentType, contentData) {
469
+ switch (contentType) {
470
+ case 'article':
471
+ // Clean, readable theme
472
+ return {
473
+ sourceColor: "#1f2937",
474
+ variant: "neutral",
475
+ contrastLevel: 0.5
476
+ };
477
+
478
+ case 'gallery':
479
+ // Let images stand out
480
+ return {
481
+ sourceColor: contentData.dominantColor,
482
+ variant: "monochrome",
483
+ scheme: "dark"
484
+ };
485
+
486
+ case 'video':
487
+ // Dark, immersive theme
488
+ return {
489
+ sourceColor: "#0f172a",
490
+ variant: "monochrome",
491
+ scheme: "dark"
492
+ };
493
+
494
+ case 'product':
495
+ // Match product color
496
+ return generateThemeFromImage(contentData.productImage);
497
+ }
498
+ }
499
+ ```
500
+
501
+ ## CSS Generation
502
+
503
+ ### CSS Custom Properties
504
+
505
+ ```javascript
506
+ // Generate CSS variables
507
+ const cssTheme = generateThemeCSS({
508
+ sourceColor: "#6366f1",
509
+ prefix: "theme",
510
+ includeTones: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99, 100]
511
+ });
512
+
513
+ // Output:
514
+ :root {
515
+ /* Primary palette */
516
+ --theme-primary-0: #000000;
517
+ --theme-primary-10: #00006e;
518
+ --theme-primary-20: #0001ac;
519
+ --theme-primary-30: #1e2bdb;
520
+ --theme-primary-40: #4046f4;
521
+ --theme-primary-50: #6366f1;
522
+ --theme-primary-60: #7f81ff;
523
+ --theme-primary-70: #9da0ff;
524
+ --theme-primary-80: #bcc0ff;
525
+ --theme-primary-90: #dee0ff;
526
+ --theme-primary-95: #eff0ff;
527
+ --theme-primary-99: #fffbff;
528
+ --theme-primary-100: #ffffff;
529
+
530
+ /* Secondary, tertiary, neutral, error palettes... */
531
+ }
532
+
533
+ /* Dark mode overrides */
534
+ @media (prefers-color-scheme: dark) {
535
+ :root {
536
+ /* Dark scheme mappings */
537
+ }
538
+ }
539
+ ```
540
+
541
+ ### Tailwind Configuration
542
+
543
+ ```javascript
544
+ // Generate Tailwind config from theme
545
+ function generateTailwindConfig(theme) {
546
+ return {
547
+ theme: {
548
+ extend: {
549
+ colors: {
550
+ primary: {
551
+ DEFAULT: theme.primary,
552
+ 50: theme.palettes.primary[95],
553
+ 100: theme.palettes.primary[90],
554
+ 200: theme.palettes.primary[80],
555
+ 300: theme.palettes.primary[70],
556
+ 400: theme.palettes.primary[60],
557
+ 500: theme.palettes.primary[50],
558
+ 600: theme.palettes.primary[40],
559
+ 700: theme.palettes.primary[30],
560
+ 800: theme.palettes.primary[20],
561
+ 900: theme.palettes.primary[10],
562
+ 950: theme.palettes.primary[0]
563
+ },
564
+ surface: {
565
+ DEFAULT: theme.surface,
566
+ container: theme.surfaceContainer,
567
+ variant: theme.surfaceVariant
568
+ }
569
+ }
570
+ }
571
+ }
572
+ };
573
+ }
574
+ ```
575
+
576
+ ### Sass/SCSS Variables
577
+
578
+ ```scss
579
+ // Generate Sass variables
580
+ $theme-primary: #6366f1;
581
+ $theme-on-primary: #ffffff;
582
+ $theme-primary-container: #e0e0ff;
583
+ $theme-on-primary-container: #070764;
584
+
585
+ // Mixin for component theming
586
+ @mixin apply-theme($role: 'surface') {
587
+ @if $role == 'primary' {
588
+ background: $theme-primary;
589
+ color: $theme-on-primary;
590
+ } @else if $role == 'primary-container' {
591
+ background: $theme-primary-container;
592
+ color: $theme-on-primary-container;
593
+ }
594
+ }
595
+
596
+ // Usage
597
+ .button-primary {
598
+ @include apply-theme('primary');
599
+ }
600
+ ```
601
+
602
+ ## Accessibility Considerations
603
+
604
+ ### Ensuring Contrast
605
+
606
+ ```javascript
607
+ // Validate theme accessibility
608
+ function validateThemeAccessibility(theme) {
609
+ const checks = [
610
+ // Text on backgrounds
611
+ { fg: theme.onSurface, bg: theme.surface, min: 4.5 },
612
+ { fg: theme.onPrimary, bg: theme.primary, min: 4.5 },
613
+ { fg: theme.onSecondary, bg: theme.secondary, min: 4.5 },
614
+
615
+ // Interactive elements
616
+ { fg: theme.primary, bg: theme.surface, min: 3.0 },
617
+ { fg: theme.outline, bg: theme.surface, min: 3.0 }
618
+ ];
619
+
620
+ const results = checks.map(check => {
621
+ const ratio = checkContrast(check.fg, check.bg);
622
+ return {
623
+ ...check,
624
+ ratio,
625
+ passes: ratio >= check.min
626
+ };
627
+ });
628
+
629
+ return {
630
+ allPass: results.every(r => r.passes),
631
+ failures: results.filter(r => !r.passes)
632
+ };
633
+ }
634
+ ```
635
+
636
+ ### High Contrast Mode
637
+
638
+ ```javascript
639
+ // Generate high contrast variant
640
+ function createHighContrastTheme(baseTheme) {
641
+ return {
642
+ ...baseTheme,
643
+ // Maximize contrast
644
+ surface: "#ffffff",
645
+ onSurface: "#000000",
646
+
647
+ // Bold colors
648
+ primary: adjustTone(baseTheme.primary, 30),
649
+ onPrimary: "#ffffff",
650
+
651
+ // Strong outlines
652
+ outline: "#000000",
653
+ outlineVariant: "#424242",
654
+
655
+ // Remove subtle variations
656
+ surfaceVariant: "#ffffff",
657
+ surfaceContainer: "#ffffff"
658
+ };
659
+ }
660
+ ```
661
+
662
+ ### Color Blindness Support
663
+
664
+ ```javascript
665
+ // Adjust theme for color blindness
666
+ function adjustForColorBlindness(theme, type) {
667
+ switch (type) {
668
+ case 'protanopia': // Red-blind
669
+ // Shift reds toward blue
670
+ return shiftProblemColors(theme, ['red'], 'blue');
671
+
672
+ case 'deuteranopia': // Green-blind
673
+ // Enhance red-blue distinction
674
+ return enhanceColorDistinction(theme, ['red', 'blue']);
675
+
676
+ case 'tritanopia': // Blue-blind
677
+ // Use red-green distinction
678
+ return shiftProblemColors(theme, ['blue'], 'green');
679
+
680
+ case 'achromatopsia': // Total color blindness
681
+ // Use only lightness variations
682
+ return createMonochromeTheme(theme);
683
+ }
684
+ }
685
+ ```
686
+
687
+ ## Real-World Examples
688
+
689
+ ### News Website
690
+
691
+ ```javascript
692
+ // Serious, trustworthy appearance
693
+ const newsTheme = {
694
+ // Core colors
695
+ primary: "#1e40af", // Deep blue
696
+ secondary: "#dc2626", // Breaking news red
697
+ neutral: "#1f2937", // Text
698
+
699
+ // Sections
700
+ politics: "#1e40af",
701
+ business: "#059669",
702
+ sports: "#ea580c",
703
+ entertainment: "#9333ea",
704
+ technology: "#0891b2",
705
+
706
+ // UI elements
707
+ surface: "#ffffff",
708
+ surfaceRaised: "#f9fafb",
709
+ border: "#e5e7eb",
710
+
711
+ // Typography
712
+ headline: "#111827",
713
+ body: "#374151",
714
+ caption: "#6b7280"
715
+ };
716
+ ```
717
+
718
+ ### Social Media Platform
719
+
720
+ ```javascript
721
+ // Friendly, engaging theme
722
+ const socialTheme = generateMaterialTheme({
723
+ sourceColor: "#3b82f6", // Facebook-like blue
724
+ customColors: [
725
+ { name: "like", color: "#ef4444" }, // Red heart
726
+ { name: "share", color: "#10b981" }, // Green share
727
+ { name: "comment", color: "#6366f1" } // Blue comment
728
+ ],
729
+ variant: "vibrant"
730
+ });
731
+
732
+ // Additional social elements
733
+ const socialElements = {
734
+ // User-generated content
735
+ userPost: socialTheme.surface,
736
+ userPostHover: socialTheme.surfaceVariant,
737
+
738
+ // Interactions
739
+ likeButton: "#ef4444",
740
+ likeButtonActive: "#dc2626",
741
+
742
+ // Status indicators
743
+ online: "#10b981",
744
+ away: "#f59e0b",
745
+ offline: "#6b7280"
746
+ };
747
+ ```
748
+
749
+ ### Educational Platform
750
+
751
+ ```javascript
752
+ // Clear, focused learning environment
753
+ const eduTheme = {
754
+ // Subject colors
755
+ math: "#3b82f6", // Blue
756
+ science: "#10b981", // Green
757
+ literature: "#8b5cf6", // Purple
758
+ history: "#f59e0b", // Amber
759
+ arts: "#ec4899", // Pink
760
+
761
+ // Progress indicators
762
+ notStarted: "#e5e7eb",
763
+ inProgress: "#fbbf24",
764
+ completed: "#10b981",
765
+
766
+ // Difficulty levels
767
+ beginner: "#10b981",
768
+ intermediate: "#3b82f6",
769
+ advanced: "#7c3aed",
770
+ expert: "#dc2626"
771
+ };
772
+ ```
773
+
774
+ ## Theme Testing
775
+
776
+ ### Visual Testing
777
+
778
+ ```javascript
779
+ // Generate theme preview
780
+ function previewTheme(theme) {
781
+ const preview = {
782
+ // Color swatches
783
+ swatches: Object.entries(theme).map(([name, color]) => ({
784
+ name,
785
+ color,
786
+ hex: color,
787
+ rgb: hexToRgb(color),
788
+ hsl: hexToHsl(color)
789
+ })),
790
+
791
+ // Sample components
792
+ components: {
793
+ button: generateButtonPreview(theme),
794
+ card: generateCardPreview(theme),
795
+ form: generateFormPreview(theme)
796
+ },
797
+
798
+ // Accessibility report
799
+ accessibility: validateThemeAccessibility(theme),
800
+
801
+ // Color harmony analysis
802
+ harmony: analyzeColorHarmony(theme)
803
+ };
804
+
805
+ return preview;
806
+ }
807
+ ```
808
+
809
+ ### Automated Testing
810
+
811
+ ```javascript
812
+ // Test theme generation
813
+ describe('Theme Creation', () => {
814
+ test('generates accessible color pairs', () => {
815
+ const theme = generateMaterialTheme('#6366f1');
816
+
817
+ // Check primary colors
818
+ const ratio = getContrast(
819
+ theme.schemes.light.primary,
820
+ theme.schemes.light.onPrimary
821
+ );
822
+ expect(ratio).toBeGreaterThanOrEqual(4.5);
823
+ });
824
+
825
+ test('maintains brand color fidelity', () => {
826
+ const brand = '#ff5722';
827
+ const theme = generateMaterialTheme({
828
+ sourceColor: brand,
829
+ variant: 'fidelity'
830
+ });
831
+
832
+ const distance = colorDistance(brand, theme.schemes.light.primary);
833
+ expect(distance).toBeLessThan(5);
834
+ });
835
+ });
836
+ ```
837
+
838
+ ## Export Formats
839
+
840
+ ### JSON Export
841
+
842
+ ```javascript
843
+ // Export theme as JSON
844
+ const themeJson = {
845
+ version: "1.0.0",
846
+ name: "My Theme",
847
+ author: "Designer Name",
848
+ colors: theme,
849
+ metadata: {
850
+ created: new Date().toISOString(),
851
+ sourceColor: "#6366f1",
852
+ variant: "tonalSpot",
853
+ contrastLevel: 0
854
+ }
855
+ };
856
+
857
+ fs.writeFileSync('theme.json', JSON.stringify(themeJson, null, 2));
858
+ ```
859
+
860
+ ### Design Tokens
861
+
862
+ ```javascript
863
+ // Export as design tokens
864
+ const tokens = {
865
+ color: {
866
+ primary: {
867
+ value: theme.primary,
868
+ type: "color"
869
+ },
870
+ onPrimary: {
871
+ value: theme.onPrimary,
872
+ type: "color"
873
+ }
874
+ },
875
+ spacing: {
876
+ small: { value: "8px", type: "dimension" },
877
+ medium: { value: "16px", type: "dimension" },
878
+ large: { value: "24px", type: "dimension" }
879
+ },
880
+ typography: {
881
+ heading: {
882
+ value: {
883
+ fontFamily: "Inter",
884
+ fontSize: "24px",
885
+ fontWeight: 600
886
+ },
887
+ type: "typography"
888
+ }
889
+ }
890
+ };
891
+ ```
892
+
893
+ ## Next Steps
894
+
895
+ - Explore [Image Extraction](./image-extraction.md) for dynamic theme generation
896
+ - Learn about [CSS Refactoring](./css-refactoring.md) to apply themes
897
+ - Read [Material Design Concepts](../concepts/material-design.md) for theory
898
+ - Check [Theme Matching Tools](../tools/theme-matching.md) for implementation