@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.
Files changed (140) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +20 -8
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +22 -8
  3. package/.github/pull_request_template.md +33 -8
  4. package/.github/workflows/ci.yml +107 -104
  5. package/.github/workflows/deploy-docs.yml +14 -11
  6. package/.github/workflows/release.yml +25 -23
  7. package/README.md +149 -15
  8. package/dist/bin/server.js +997 -256
  9. package/dist/bin/server.js.map +1 -1
  10. package/dist/{chunk-P3ARRKLS.js → chunk-HOMDMKUY.js} +3 -1
  11. package/dist/{chunk-P3ARRKLS.js.map → chunk-HOMDMKUY.js.map} +1 -1
  12. package/dist/{chunk-IQ7NN26V.js → chunk-LHW2ZTOU.js} +14 -2
  13. package/dist/chunk-LHW2ZTOU.js.map +1 -0
  14. package/dist/color/index.js +1 -1
  15. package/dist/coolors-mcp.d.ts +4 -4
  16. package/dist/coolors-mcp.js +1 -1
  17. package/docs/.vitepress/components/ClientGrid.vue +9 -3
  18. package/docs/.vitepress/components/CodeBlock.vue +51 -44
  19. package/docs/.vitepress/components/ConfigModal.vue +151 -67
  20. package/docs/.vitepress/components/DiagramModal.vue +186 -154
  21. package/docs/.vitepress/components/TroubleshootingModal.vue +101 -96
  22. package/docs/.vitepress/config.js +171 -141
  23. package/docs/.vitepress/theme/FundingLayout.vue +65 -54
  24. package/docs/.vitepress/theme/Layout.vue +21 -21
  25. package/docs/.vitepress/theme/components/AdBanner.vue +73 -52
  26. package/docs/.vitepress/theme/components/AdPlaceholder.vue +3 -3
  27. package/docs/.vitepress/theme/components/FundingEffects.vue +77 -53
  28. package/docs/.vitepress/theme/components/FundingHero.vue +78 -63
  29. package/docs/.vitepress/theme/components/SupportSection.vue +106 -89
  30. package/docs/.vitepress/theme/custom-app.css +19 -12
  31. package/docs/.vitepress/theme/custom.css +33 -25
  32. package/docs/.vitepress/theme/index.js +19 -16
  33. package/docs/concepts/accessibility.md +59 -47
  34. package/docs/concepts/color-spaces.md +28 -6
  35. package/docs/concepts/distance-metrics.md +45 -30
  36. package/docs/concepts/hct.md +30 -27
  37. package/docs/concepts/image-analysis.md +52 -21
  38. package/docs/concepts/material-design.md +43 -17
  39. package/docs/concepts/theme-matching.md +64 -40
  40. package/docs/examples/basic-colors.md +92 -108
  41. package/docs/examples/creating-themes.md +104 -108
  42. package/docs/examples/css-refactoring.md +33 -29
  43. package/docs/examples/image-extraction.md +145 -138
  44. package/docs/getting-started.md +45 -34
  45. package/docs/index.md +5 -1
  46. package/docs/installation.md +15 -1
  47. package/docs/tools/accessibility.md +74 -68
  48. package/docs/tools/image-extraction.md +62 -54
  49. package/docs/tools/theme-matching.md +45 -42
  50. package/eslint.config.ts +13 -0
  51. package/jsr.json +1 -1
  52. package/package.json +17 -13
  53. package/src/bin/server.ts +13 -1
  54. package/src/color/__tests__/extract-colors.test.ts +20 -30
  55. package/src/color/apca.ts +105 -0
  56. package/src/color/color-blindness.ts +109 -0
  57. package/src/coolors-mcp.ts +1 -1
  58. package/src/session.ts +10 -2
  59. package/src/theme/matcher.ts +1 -1
  60. package/src/theme/refactor.ts +1 -1
  61. package/src/theme/types.ts +3 -0
  62. package/src/tools/__tests__/cohesion.test.ts +97 -0
  63. package/src/tools/__tests__/color-blindness.test.ts +45 -0
  64. package/src/tools/__tests__/color-conversion.test.ts +38 -0
  65. package/src/tools/__tests__/contrast-checker.test.ts +56 -0
  66. package/src/tools/__tests__/palette-export.test.ts +54 -0
  67. package/src/tools/adjust-color.tool.ts +80 -0
  68. package/src/tools/cohesion.tools.ts +380 -0
  69. package/src/tools/color-blindness.tool.ts +168 -0
  70. package/src/tools/color-conversion.tool.ts +1 -1
  71. package/src/tools/contrast-checker.tool.ts +53 -14
  72. package/src/tools/dislike-analyzer.tool.ts +41 -54
  73. package/src/tools/image-extraction.tools.ts +62 -115
  74. package/src/tools/index.ts +15 -2
  75. package/src/tools/palette-export.tool.ts +174 -0
  76. package/src/tools/palette-with-locks.tool.ts +8 -6
  77. package/src/types.ts +2 -3
  78. package/tsconfig.json +12 -2
  79. package/vitest.config.js +1 -3
  80. package/.claude/settings.local.json +0 -39
  81. package/.env +0 -2
  82. package/.mcp.json +0 -12
  83. package/CLAUDE.md +0 -201
  84. package/DOCUMENTATION.md +0 -274
  85. package/GEMINI.md +0 -54
  86. package/demo/content_based_color.png +0 -0
  87. package/demo/music-player.html +0 -621
  88. package/demo/podcast-player.html +0 -903
  89. package/dist/chunk-IQ7NN26V.js.map +0 -1
  90. package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js +0 -93
  91. package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js.map +0 -7
  92. package/docs/.vitepress/cache/deps/_metadata.json +0 -127
  93. package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js +0 -9
  94. package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js.map +0 -7
  95. package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js +0 -12683
  96. package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js.map +0 -7
  97. package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js +0 -9719
  98. package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js.map +0 -7
  99. package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js +0 -4710
  100. package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js.map +0 -7
  101. package/docs/.vitepress/cache/deps/cytoscape.js +0 -30278
  102. package/docs/.vitepress/cache/deps/cytoscape.js.map +0 -7
  103. package/docs/.vitepress/cache/deps/dayjs.js +0 -285
  104. package/docs/.vitepress/cache/deps/dayjs.js.map +0 -7
  105. package/docs/.vitepress/cache/deps/debug.js +0 -468
  106. package/docs/.vitepress/cache/deps/debug.js.map +0 -7
  107. package/docs/.vitepress/cache/deps/package.json +0 -3
  108. package/docs/.vitepress/cache/deps/prismjs.js +0 -1466
  109. package/docs/.vitepress/cache/deps/prismjs.js.map +0 -7
  110. package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js +0 -228
  111. package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js.map +0 -7
  112. package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js +0 -142
  113. package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js.map +0 -7
  114. package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js +0 -27
  115. package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js.map +0 -7
  116. package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js +0 -65
  117. package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js.map +0 -7
  118. package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js +0 -53
  119. package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js.map +0 -7
  120. package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js +0 -73
  121. package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js.map +0 -7
  122. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -4507
  123. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
  124. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -584
  125. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
  126. package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +0 -1146
  127. package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +0 -7
  128. package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +0 -1667
  129. package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +0 -7
  130. package/docs/.vitepress/cache/deps/vitepress___minisearch.js +0 -1814
  131. package/docs/.vitepress/cache/deps/vitepress___minisearch.js.map +0 -7
  132. package/docs/.vitepress/cache/deps/vue.js +0 -344
  133. package/docs/.vitepress/cache/deps/vue.js.map +0 -7
  134. package/examples/theme-matching.md +0 -113
  135. package/mcp-config.json +0 -8
  136. package/note.md +0 -35
  137. package/research_results.md +0 -53
  138. package/src/tools/colors.ts +0 -31
  139. package/src/tools/registry.ts +0 -142
  140. package/src/tools/simple-tools.ts +0 -37
@@ -1,621 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Content-Based Color Demo - Music Player</title>
7
- <style>
8
- :root {
9
- /* Material Design 3 - Light Theme (from teal seed color #0E7490) */
10
- --md-sys-color-primary: #006d9e;
11
- --md-sys-color-on-primary: #ffffff;
12
- --md-sys-color-primary-container: #c0e9fb;
13
- --md-sys-color-on-primary-container: #002851;
14
-
15
- --md-sys-color-secondary: #3c6473;
16
- --md-sys-color-on-secondary: #ffffff;
17
- --md-sys-color-secondary-container: #c0e9fb;
18
- --md-sys-color-on-secondary-container: #00202d;
19
-
20
- --md-sys-color-tertiary: #5b5b82;
21
- --md-sys-color-on-tertiary: #ffffff;
22
- --md-sys-color-tertiary-container: #e1deff;
23
- --md-sys-color-on-tertiary-container: #151839;
24
-
25
- --md-sys-color-background: #f8fdff;
26
- --md-sys-color-on-background: #181c1e;
27
- --md-sys-color-surface: #f8fdff;
28
- --md-sys-color-on-surface: #181c1e;
29
- --md-sys-color-surface-variant: #d9e4e9;
30
- --md-sys-color-on-surface-variant: #3f484c;
31
-
32
- --md-sys-color-outline: #6f797d;
33
- --md-sys-color-outline-variant: #bdc8cd;
34
-
35
- /* Tonal variations for UI elements */
36
- --md-sys-color-surface-container: #e8f4f9;
37
- --md-sys-color-surface-container-high: #dfeef4;
38
- --md-sys-color-surface-container-highest: #d9e4e9;
39
- }
40
-
41
- @media (prefers-color-scheme: dark) {
42
- :root {
43
- /* Material Design 3 - Dark Theme */
44
- --md-sys-color-primary: #00d8ff;
45
- --md-sys-color-on-primary: #003d6a;
46
- --md-sys-color-primary-container: #005583;
47
- --md-sys-color-on-primary-container: #32f5ff;
48
-
49
- --md-sys-color-secondary: #a4cdde;
50
- --md-sys-color-on-secondary: #063543;
51
- --md-sys-color-secondary-container: #234c5a;
52
- --md-sys-color-on-secondary-container: #c0e9fb;
53
-
54
- --md-sys-color-tertiary: #c5c2ef;
55
- --md-sys-color-on-tertiary: #2c2d50;
56
- --md-sys-color-tertiary-container: #434369;
57
- --md-sys-color-on-tertiary-container: #e1deff;
58
-
59
- --md-sys-color-background: #0f1416;
60
- --md-sys-color-on-background: #dee3e6;
61
- --md-sys-color-surface: #181c1e;
62
- --md-sys-color-on-surface: #dee3e6;
63
- --md-sys-color-surface-variant: #3f484c;
64
- --md-sys-color-on-surface-variant: #bdc8cd;
65
-
66
- --md-sys-color-outline: #889297;
67
- --md-sys-color-outline-variant: #3f484c;
68
-
69
- --md-sys-color-surface-container: #1e2426;
70
- --md-sys-color-surface-container-high: #272d30;
71
- --md-sys-color-surface-container-highest: #323739;
72
- }
73
- }
74
-
75
- * {
76
- margin: 0;
77
- padding: 0;
78
- box-sizing: border-box;
79
- }
80
-
81
- body {
82
- font-family:
83
- -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu,
84
- sans-serif;
85
- background: var(--md-sys-color-background);
86
- color: var(--md-sys-color-on-background);
87
- min-height: 100vh;
88
- display: flex;
89
- justify-content: center;
90
- align-items: center;
91
- padding: 20px;
92
- background: linear-gradient(
93
- 135deg,
94
- var(--md-sys-color-primary-container) 0%,
95
- var(--md-sys-color-secondary-container) 100%
96
- );
97
- }
98
-
99
- .phone-container {
100
- width: 375px;
101
- height: 812px;
102
- background: var(--md-sys-color-surface);
103
- border-radius: 40px;
104
- box-shadow:
105
- 0 20px 60px rgba(0, 0, 0, 0.3),
106
- 0 0 0 1px var(--md-sys-color-outline-variant);
107
- overflow: hidden;
108
- position: relative;
109
- }
110
-
111
- .status-bar {
112
- height: 44px;
113
- padding: 0 24px;
114
- display: flex;
115
- justify-content: space-between;
116
- align-items: center;
117
- background: var(--md-sys-color-surface);
118
- font-size: 14px;
119
- font-weight: 600;
120
- }
121
-
122
- .status-icons {
123
- display: flex;
124
- gap: 6px;
125
- }
126
-
127
- .header {
128
- height: 56px;
129
- padding: 0 16px;
130
- display: flex;
131
- align-items: center;
132
- gap: 16px;
133
- background: var(--md-sys-color-surface);
134
- border-bottom: 1px solid var(--md-sys-color-outline-variant);
135
- }
136
-
137
- .back-button {
138
- width: 40px;
139
- height: 40px;
140
- border: none;
141
- background: transparent;
142
- color: var(--md-sys-color-on-surface);
143
- cursor: pointer;
144
- border-radius: 20px;
145
- display: flex;
146
- align-items: center;
147
- justify-content: center;
148
- transition: background 0.2s;
149
- }
150
-
151
- .back-button:hover {
152
- background: var(--md-sys-color-surface-variant);
153
- }
154
-
155
- .header-title {
156
- font-size: 20px;
157
- font-weight: 500;
158
- color: var(--md-sys-color-on-surface);
159
- }
160
-
161
- .content {
162
- padding: 32px 24px;
163
- display: flex;
164
- flex-direction: column;
165
- align-items: center;
166
- gap: 32px;
167
- height: calc(100% - 100px);
168
- overflow-y: auto;
169
- }
170
-
171
- .album-container {
172
- position: relative;
173
- width: 280px;
174
- height: 280px;
175
- }
176
-
177
- .album-art {
178
- width: 100%;
179
- height: 100%;
180
- border-radius: 24px;
181
- background: var(--md-sys-color-primary);
182
- position: relative;
183
- overflow: hidden;
184
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
185
- }
186
-
187
- .album-pattern {
188
- position: absolute;
189
- inset: 0;
190
- display: grid;
191
- grid-template-columns: repeat(12, 1fr);
192
- grid-template-rows: repeat(12, 1fr);
193
- gap: 3px;
194
- padding: 20px;
195
- }
196
-
197
- .pattern-cell {
198
- border-radius: 2px;
199
- animation: pulse 3s ease-in-out infinite;
200
- }
201
-
202
- .pattern-cell:nth-child(3n) {
203
- background: var(--md-sys-color-tertiary);
204
- animation-delay: 0.1s;
205
- }
206
-
207
- .pattern-cell:nth-child(3n + 1) {
208
- background: var(--md-sys-color-secondary);
209
- animation-delay: 0.2s;
210
- }
211
-
212
- .pattern-cell:nth-child(3n + 2) {
213
- background: var(--md-sys-color-primary-container);
214
- animation-delay: 0.3s;
215
- }
216
-
217
- .pattern-cell:nth-child(5n) {
218
- background: var(--md-sys-color-tertiary-container);
219
- }
220
-
221
- .pattern-cell:nth-child(7n) {
222
- background: var(--md-sys-color-on-primary);
223
- opacity: 0.8;
224
- }
225
-
226
- .pattern-cell:nth-child(11n) {
227
- background: var(--md-sys-color-secondary-container);
228
- }
229
-
230
- @keyframes pulse {
231
- 0%,
232
- 100% {
233
- opacity: 0.6;
234
- transform: scale(0.95);
235
- }
236
- 50% {
237
- opacity: 1;
238
- transform: scale(1);
239
- }
240
- }
241
-
242
- .track-info {
243
- text-align: center;
244
- width: 100%;
245
- }
246
-
247
- .track-title {
248
- font-size: 28px;
249
- font-weight: 600;
250
- color: var(--md-sys-color-on-surface);
251
- margin-bottom: 8px;
252
- }
253
-
254
- .track-artist {
255
- font-size: 16px;
256
- color: var(--md-sys-color-on-surface-variant);
257
- }
258
-
259
- .progress-container {
260
- width: 100%;
261
- }
262
-
263
- .progress-bar {
264
- width: 100%;
265
- height: 4px;
266
- background: var(--md-sys-color-surface-variant);
267
- border-radius: 2px;
268
- position: relative;
269
- margin-bottom: 8px;
270
- }
271
-
272
- .progress-fill {
273
- height: 100%;
274
- width: 40%;
275
- background: var(--md-sys-color-primary);
276
- border-radius: 2px;
277
- position: relative;
278
- }
279
-
280
- .progress-handle {
281
- position: absolute;
282
- right: -8px;
283
- top: -6px;
284
- width: 16px;
285
- height: 16px;
286
- background: var(--md-sys-color-primary);
287
- border-radius: 50%;
288
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
289
- }
290
-
291
- .time-labels {
292
- display: flex;
293
- justify-content: space-between;
294
- font-size: 12px;
295
- color: var(--md-sys-color-on-surface-variant);
296
- }
297
-
298
- .controls {
299
- display: flex;
300
- align-items: center;
301
- justify-content: center;
302
- gap: 24px;
303
- width: 100%;
304
- }
305
-
306
- .control-btn {
307
- background: transparent;
308
- border: none;
309
- color: var(--md-sys-color-on-surface);
310
- cursor: pointer;
311
- display: flex;
312
- align-items: center;
313
- justify-content: center;
314
- transition: transform 0.2s;
315
- }
316
-
317
- .control-btn:hover {
318
- transform: scale(1.1);
319
- }
320
-
321
- .control-btn:active {
322
- transform: scale(0.95);
323
- }
324
-
325
- .control-btn.small {
326
- width: 32px;
327
- height: 32px;
328
- opacity: 0.7;
329
- }
330
-
331
- .control-btn.medium {
332
- width: 48px;
333
- height: 48px;
334
- }
335
-
336
- .control-btn.primary {
337
- width: 72px;
338
- height: 72px;
339
- background: var(--md-sys-color-primary);
340
- color: var(--md-sys-color-on-primary);
341
- border-radius: 50%;
342
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
343
- }
344
-
345
- .volume-container {
346
- width: 100%;
347
- padding: 24px 0;
348
- display: flex;
349
- align-items: center;
350
- gap: 16px;
351
- }
352
-
353
- .volume-icon {
354
- color: var(--md-sys-color-on-surface-variant);
355
- }
356
-
357
- .volume-slider {
358
- flex: 1;
359
- height: 48px;
360
- background: var(--md-sys-color-primary);
361
- border-radius: 24px;
362
- position: relative;
363
- display: flex;
364
- align-items: center;
365
- }
366
-
367
- .volume-fill {
368
- height: 100%;
369
- width: 70%;
370
- background: var(--md-sys-color-on-primary);
371
- border-radius: 24px;
372
- opacity: 0.3;
373
- }
374
-
375
- /* Icons */
376
- .icon {
377
- width: 24px;
378
- height: 24px;
379
- fill: currentColor;
380
- }
381
-
382
- .icon.large {
383
- width: 32px;
384
- height: 32px;
385
- }
386
-
387
- /* Demo controls */
388
- .demo-controls {
389
- position: absolute;
390
- bottom: 20px;
391
- right: 20px;
392
- display: flex;
393
- flex-direction: column;
394
- gap: 12px;
395
- z-index: 10;
396
- }
397
-
398
- .theme-toggle {
399
- padding: 12px 20px;
400
- background: var(--md-sys-color-primary);
401
- color: var(--md-sys-color-on-primary);
402
- border: none;
403
- border-radius: 20px;
404
- cursor: pointer;
405
- font-size: 14px;
406
- font-weight: 500;
407
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
408
- transition: transform 0.2s;
409
- }
410
-
411
- .theme-toggle:hover {
412
- transform: translateY(-2px);
413
- }
414
-
415
- .theme-toggle:active {
416
- transform: translateY(0);
417
- }
418
- </style>
419
- </head>
420
- <body>
421
- <div class="phone-container">
422
- <div class="status-bar">
423
- <span>9:30</span>
424
- <div class="status-icons">
425
- <span>🔋</span>
426
- <span>📶</span>
427
- <span>📡</span>
428
- </div>
429
- </div>
430
-
431
- <div class="header">
432
- <button class="back-button">
433
- <svg class="icon" viewBox="0 0 24 24">
434
- <path
435
- d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"
436
- />
437
- </svg>
438
- </button>
439
- <span class="header-title">Now playing</span>
440
- </div>
441
-
442
- <div class="content">
443
- <div class="album-container">
444
- <div class="album-art">
445
- <div class="album-pattern">
446
- <!-- Generate pattern cells -->
447
- <script>
448
- for (let i = 0; i < 144; i++) {
449
- document.write('<div class="pattern-cell"></div>');
450
- }
451
- </script>
452
- </div>
453
- </div>
454
- </div>
455
-
456
- <div class="track-info">
457
- <div class="track-title">Early Aughts</div>
458
- <div class="track-artist">Song Histories Podcast</div>
459
- </div>
460
-
461
- <div class="progress-container">
462
- <div class="progress-bar">
463
- <div class="progress-fill">
464
- <div class="progress-handle"></div>
465
- </div>
466
- </div>
467
- <div class="time-labels">
468
- <span>1:28</span>
469
- <span>3:03</span>
470
- </div>
471
- </div>
472
-
473
- <div class="controls">
474
- <button class="control-btn small">
475
- <svg class="icon" viewBox="0 0 24 24">
476
- <path
477
- d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z"
478
- />
479
- </svg>
480
- </button>
481
-
482
- <button class="control-btn medium">
483
- <svg class="icon large" viewBox="0 0 24 24">
484
- <path d="M6 6h2v12H6zm3.5 6l8.5 6V6z" />
485
- </svg>
486
- </button>
487
-
488
- <button class="control-btn primary">
489
- <svg class="icon large" viewBox="0 0 24 24">
490
- <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
491
- </svg>
492
- </button>
493
-
494
- <button class="control-btn medium">
495
- <svg class="icon large" viewBox="0 0 24 24">
496
- <path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z" />
497
- </svg>
498
- </button>
499
-
500
- <button class="control-btn small">
501
- <svg class="icon" viewBox="0 0 24 24">
502
- <path
503
- d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z"
504
- />
505
- </svg>
506
- </button>
507
- </div>
508
-
509
- <div class="volume-container">
510
- <svg class="icon volume-icon" viewBox="0 0 24 24">
511
- <path
512
- d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"
513
- />
514
- </svg>
515
- <div class="volume-slider">
516
- <div class="volume-fill"></div>
517
- </div>
518
- </div>
519
- </div>
520
- </div>
521
-
522
- <div class="demo-controls">
523
- <button class="theme-toggle" onclick="toggleTheme()">Toggle Theme</button>
524
- <button class="theme-toggle" onclick="changeAlbumColors()">
525
- Change Album
526
- </button>
527
- </div>
528
-
529
- <script>
530
- let darkMode = false;
531
-
532
- function toggleTheme() {
533
- darkMode = !darkMode;
534
- if (darkMode) {
535
- document.documentElement.style.colorScheme = "dark";
536
- applyDarkTheme();
537
- } else {
538
- document.documentElement.style.colorScheme = "light";
539
- applyLightTheme();
540
- }
541
- }
542
-
543
- function applyLightTheme() {
544
- const root = document.documentElement;
545
- root.style.setProperty("--md-sys-color-primary", "#006d9e");
546
- root.style.setProperty("--md-sys-color-on-primary", "#ffffff");
547
- root.style.setProperty("--md-sys-color-primary-container", "#c0e9fb");
548
- root.style.setProperty("--md-sys-color-secondary", "#3c6473");
549
- root.style.setProperty("--md-sys-color-secondary-container", "#c0e9fb");
550
- root.style.setProperty("--md-sys-color-tertiary", "#5b5b82");
551
- root.style.setProperty("--md-sys-color-tertiary-container", "#e1deff");
552
- root.style.setProperty("--md-sys-color-background", "#f8fdff");
553
- root.style.setProperty("--md-sys-color-on-background", "#181c1e");
554
- root.style.setProperty("--md-sys-color-surface", "#f8fdff");
555
- root.style.setProperty("--md-sys-color-on-surface", "#181c1e");
556
- root.style.setProperty("--md-sys-color-surface-variant", "#d9e4e9");
557
- root.style.setProperty("--md-sys-color-on-surface-variant", "#3f484c");
558
- }
559
-
560
- function applyDarkTheme() {
561
- const root = document.documentElement;
562
- root.style.setProperty("--md-sys-color-primary", "#00d8ff");
563
- root.style.setProperty("--md-sys-color-on-primary", "#003d6a");
564
- root.style.setProperty("--md-sys-color-primary-container", "#005583");
565
- root.style.setProperty("--md-sys-color-secondary", "#a4cdde");
566
- root.style.setProperty("--md-sys-color-secondary-container", "#234c5a");
567
- root.style.setProperty("--md-sys-color-tertiary", "#c5c2ef");
568
- root.style.setProperty("--md-sys-color-tertiary-container", "#434369");
569
- root.style.setProperty("--md-sys-color-background", "#0f1416");
570
- root.style.setProperty("--md-sys-color-on-background", "#dee3e6");
571
- root.style.setProperty("--md-sys-color-surface", "#181c1e");
572
- root.style.setProperty("--md-sys-color-on-surface", "#dee3e6");
573
- root.style.setProperty("--md-sys-color-surface-variant", "#3f484c");
574
- root.style.setProperty("--md-sys-color-on-surface-variant", "#bdc8cd");
575
- }
576
-
577
- const albumThemes = [
578
- {
579
- name: "Ocean",
580
- primary: "#006d9e",
581
- secondary: "#3c6473",
582
- tertiary: "#5b5b82",
583
- },
584
- {
585
- name: "Sunset",
586
- primary: "#d84315",
587
- secondary: "#ff6e40",
588
- tertiary: "#ffab00",
589
- },
590
- {
591
- name: "Forest",
592
- primary: "#2e7d32",
593
- secondary: "#66bb6a",
594
- tertiary: "#8bc34a",
595
- },
596
- {
597
- name: "Purple Dream",
598
- primary: "#6a1b9a",
599
- secondary: "#ab47bc",
600
- tertiary: "#ce93d8",
601
- },
602
- ];
603
-
604
- let currentAlbum = 0;
605
-
606
- function changeAlbumColors() {
607
- currentAlbum = (currentAlbum + 1) % albumThemes.length;
608
- const theme = albumThemes[currentAlbum];
609
-
610
- const root = document.documentElement;
611
- root.style.setProperty("--md-sys-color-primary", theme.primary);
612
- root.style.setProperty("--md-sys-color-secondary", theme.secondary);
613
- root.style.setProperty("--md-sys-color-tertiary", theme.tertiary);
614
-
615
- // Update track info to match album
616
- document.querySelector(".track-title").textContent =
617
- theme.name + " Vibes";
618
- }
619
- </script>
620
- </body>
621
- </html>