@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
package/docs/README.md ADDED
@@ -0,0 +1,198 @@
1
+ # Coolors MCP Documentation
2
+
3
+ Coolors MCP is a Model Context Protocol server for color operations, Material Design theme generation, and CSS theme matching.
4
+
5
+ ## Quick Navigation
6
+
7
+ ### Getting Started
8
+
9
+ - [Installation & Setup](../README.md#installation)
10
+ - [Configuration](../README.md#configure-with-claude-desktop)
11
+ - [Quick Start Guide](../README.md#quick-start)
12
+
13
+ ### Tools Reference
14
+
15
+ - [Tools Overview](./tools/README.md) - Complete list of available tools
16
+ - [Color Operations](./tools/color-operations.md) - Conversion, distance, contrast
17
+ - [Material Design](./tools/material-design.md) - Theme generation, tonal palettes
18
+ - [Theme Matching](./tools/theme-matching.md) - CSS refactoring, variable matching
19
+ - [Image Extraction](./tools/image-extraction.md) - Extract colors from images
20
+ - [Color Psychology](./tools/color-psychology.md) - Dislike analysis and fixes
21
+
22
+ ### API Documentation
23
+
24
+ - [API Reference](./api/README.md) - Complete API documentation
25
+ - [TypeScript Types](./api/types.md) - Type definitions and interfaces
26
+
27
+ ### Concepts
28
+
29
+ - [HCT Color Space](./concepts/hct-color-space.md) - Understanding HCT vs traditional color spaces
30
+ - [Distance Metrics](./concepts/distance-metrics.md) - Color difference calculations
31
+ - [Material Design 3](./concepts/material-design-3.md) - Core concepts and principles
32
+ - [Theme Matching Algorithm](./concepts/theme-matching-algorithm.md) - How matching works
33
+
34
+ ### Examples & Guides
35
+
36
+ - [Usage Examples](./examples/README.md) - Practical code examples
37
+ - [Design System Migration](./examples/design-system-migration.md) - Converting legacy CSS
38
+ - [Accessibility Compliance](./examples/accessibility-compliance.md) - WCAG guidelines
39
+ - [Dynamic Theming](./examples/dynamic-theming.md) - Image-based themes
40
+ - [Color Harmonization](./examples/color-harmonization.md) - Creating palettes
41
+
42
+ ## Features
43
+
44
+ ### Color Space Support
45
+
46
+ - RGB, HSL, HSV color models
47
+ - LAB, XYZ perceptual spaces
48
+ - HCT (Hue, Chroma, Tone) - Google's color space for UI
49
+
50
+ ### Distance Metrics
51
+
52
+ - Delta E 76 - Basic perceptual difference
53
+ - Delta E 94 - Improved for graphics arts
54
+ - Delta E 2000 - Most accurate perceptual metric
55
+ - HCT distance - Optimized for UI components
56
+
57
+ ### Material Design Integration
58
+
59
+ - Complete Material Design 3 theme generation
60
+ - Tonal palette creation (0-100 tones)
61
+ - Color harmonization algorithms
62
+ - Light and dark theme variants
63
+
64
+ ### CSS Theme Tools
65
+
66
+ - Extract theme variables from CSS
67
+ - Match colors to closest theme variables
68
+ - Automated CSS refactoring
69
+ - Context-aware matching (text, background, borders)
70
+
71
+ ### Image Processing
72
+
73
+ - Extract dominant colors from images
74
+ - Generate themes from photographs
75
+ - Quantization using Celebi algorithm
76
+ - Color scoring for UI suitability
77
+
78
+ ### Color Psychology
79
+
80
+ - Detect universally disliked colors
81
+ - Automatic color correction
82
+ - Batch processing for palettes
83
+ - Based on research into color perception
84
+
85
+ ## Tool Categories
86
+
87
+ ### 1. Basic Color Operations
88
+
89
+ Tools for fundamental color manipulation:
90
+
91
+ - `convert_color` - Format conversion
92
+ - `color_distance` - Perceptual difference
93
+ - `check_contrast` - WCAG compliance
94
+ - `generate_palette` - Create color schemes
95
+
96
+ ### 2. Material Design Tools
97
+
98
+ Google's Material Design 3 implementation:
99
+
100
+ - `generate_material_theme` - Complete theme from source color
101
+ - `generate_tonal_palette` - Create tonal variations
102
+ - `harmonize_colors` - Blend colors together
103
+
104
+ ### 3. Theme Matching & Refactoring
105
+
106
+ CSS and design system integration:
107
+
108
+ - `match_theme_color` - Find closest variable
109
+ - `refactor_css_with_theme` - Automate CSS updates
110
+ - `match_theme_colors_batch` - Process multiple colors
111
+ - `generate_theme_css` - Create CSS custom properties
112
+
113
+ ### 4. Image-Based Tools
114
+
115
+ Extract and generate from images:
116
+
117
+ - `extract_image_colors` - Get dominant colors
118
+ - `generate_theme_from_image` - Create theme from photo
119
+
120
+ ### 5. Color Analysis
121
+
122
+ Psychology and perception:
123
+
124
+ - `analyze_color_likability` - Check for problematic colors
125
+ - `fix_disliked_colors_batch` - Correct multiple colors
126
+
127
+ ## Use Cases
128
+
129
+ ### Design Systems
130
+
131
+ - Migrate from hardcoded colors to CSS variables
132
+ - Ensure consistency across components
133
+ - Generate comprehensive color palettes
134
+ - Maintain brand guidelines
135
+
136
+ ### Accessibility
137
+
138
+ - Verify WCAG AA/AAA compliance
139
+ - Find accessible color combinations
140
+ - Fix contrast issues automatically
141
+ - Test entire themes for compliance
142
+
143
+ ### Dynamic Theming
144
+
145
+ - Generate themes from user images
146
+ - Create seasonal color schemes
147
+ - Match brand colors automatically
148
+ - Adapt to content dynamically
149
+
150
+ ### Development Workflow
151
+
152
+ - Refactor legacy CSS efficiently
153
+ - Validate color choices during development
154
+ - Generate Material Design themes
155
+ - Ensure psychological appropriateness
156
+
157
+ ## Architecture Overview
158
+
159
+ The server is organized into logical modules:
160
+
161
+ ```
162
+ src/
163
+ ├── tools/ # MCP tool implementations
164
+ ├── color/ # Core color algorithms
165
+ │ ├── conversions # Color space conversions
166
+ │ ├── metrics # Distance calculations
167
+ │ ├── hct/ # HCT color space
168
+ │ └── quantize/ # Image quantization
169
+ ├── theme/ # Theme matching system
170
+ │ ├── parser # CSS parsing
171
+ │ ├── matcher # Matching algorithm
172
+ │ └── refactor # CSS transformation
173
+ └── bin/ # Server entry point
174
+ ```
175
+
176
+ ## Performance Considerations
177
+
178
+ - Color conversions are cached for repeated operations
179
+ - Batch operations available for processing multiple colors
180
+ - Quantization quality settings for image processing
181
+ - Confidence thresholds for theme matching
182
+
183
+ ## Error Handling
184
+
185
+ All tools include error handling for:
186
+
187
+ - Invalid color formats
188
+ - Out-of-range values
189
+ - Missing required parameters
190
+ - Malformed CSS input
191
+
192
+ ## Contributing
193
+
194
+ See the main [README](../README.md#contributing) for contribution guidelines.
195
+
196
+ ## License
197
+
198
+ MIT License - See [LICENSE](../LICENSE) file for details.
@@ -0,0 +1,473 @@
1
+ # Accessibility
2
+
3
+ Coolors MCP ensures color choices meet accessibility standards through comprehensive contrast checking and automatic adjustments based on WCAG guidelines.
4
+
5
+ ## Contrast Standards
6
+
7
+ ### WCAG Overview
8
+
9
+ The Web Content Accessibility Guidelines (WCAG) define contrast requirements for readable content:
10
+
11
+ | Level | Normal Text | Large Text | Non-Text |
12
+ |-------|------------|------------|----------|
13
+ | **AA** | 4.5:1 | 3:1 | 3:1 |
14
+ | **AAA** | 7:1 | 4.5:1 | N/A |
15
+
16
+ **Large text** is defined as:
17
+ - 18pt (24px) or larger
18
+ - 14pt (18.5px) or larger if bold
19
+
20
+ ### Contrast Ratio Calculation
21
+
22
+ Contrast ratio is based on relative luminance:
23
+
24
+ ```javascript
25
+ // Relative luminance calculation
26
+ function getLuminance(rgb) {
27
+ const [r, g, b] = rgb.map(val => {
28
+ val = val / 255;
29
+ return val <= 0.03928
30
+ ? val / 12.92
31
+ : Math.pow((val + 0.055) / 1.055, 2.4);
32
+ });
33
+
34
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
35
+ }
36
+
37
+ // Contrast ratio
38
+ function getContrastRatio(color1, color2) {
39
+ const l1 = getLuminance(color1);
40
+ const l2 = getLuminance(color2);
41
+
42
+ const lighter = Math.max(l1, l2);
43
+ const darker = Math.min(l1, l2);
44
+
45
+ return (lighter + 0.05) / (darker + 0.05);
46
+ }
47
+ ```
48
+
49
+ ### Understanding Contrast Ratios
50
+
51
+ - **1:1** - No contrast (same color)
52
+ - **4.5:1** - Minimum for normal text (AA)
53
+ - **7:1** - Enhanced contrast (AAA)
54
+ - **21:1** - Maximum (black on white)
55
+
56
+ ## HCT and Accessibility
57
+
58
+ ### Tone-Based Contrast
59
+
60
+ HCT's tone component directly correlates with contrast:
61
+
62
+ | Tone Difference | Approximate Contrast | Use Case |
63
+ |-----------------|---------------------|----------|
64
+ | 40 | ~3:1 | Large text, UI elements |
65
+ | 50 | ~4.5:1 | Normal text (AA) |
66
+ | 70 | ~7:1 | Enhanced (AAA) |
67
+ | 90 | ~15:1 | Maximum readability |
68
+
69
+ ### Predictable Relationships
70
+
71
+ ```javascript
72
+ // Guaranteed accessible pairs in HCT
73
+ const background = { h: 200, c: 20, t: 95 }; // Light surface
74
+ const text = { h: 200, c: 20, t: 20 }; // Dark text
75
+ // Tone difference: 75 = guaranteed 7:1+ contrast
76
+ ```
77
+
78
+ ## Checking Contrast
79
+
80
+ ### Basic Contrast Check
81
+
82
+ ```javascript
83
+ {
84
+ "name": "check_contrast",
85
+ "arguments": {
86
+ "foreground": "#1f2937",
87
+ "background": "#ffffff"
88
+ }
89
+ }
90
+
91
+ // Returns
92
+ {
93
+ "ratio": 15.74,
94
+ "passes": {
95
+ "AA": { "normal": true, "large": true },
96
+ "AAA": { "normal": true, "large": true }
97
+ },
98
+ "recommendation": "Excellent contrast for all uses"
99
+ }
100
+ ```
101
+
102
+ ### Context-Aware Checking
103
+
104
+ ```javascript
105
+ // Check with specific requirements
106
+ {
107
+ "name": "check_contrast",
108
+ "arguments": {
109
+ "foreground": "#6366f1",
110
+ "background": "#f3f4f6",
111
+ "fontSize": 14,
112
+ "fontWeight": 400
113
+ }
114
+ }
115
+ ```
116
+
117
+ ## Material Design Contrast Levels
118
+
119
+ ### Default Contrast (0.0)
120
+ Meets AA accessibility:
121
+ - **Guaranteed minimums**:
122
+ - 4.5:1 for all text and icons
123
+ - 3:1 for required non-text elements
124
+ - **Targets**:
125
+ - 7:1 for high emphasis text
126
+
127
+ ### Medium Contrast (+0.5)
128
+ Exceeds AA requirements:
129
+ - **Guaranteed minimums**:
130
+ - 4.5:1 for all text
131
+ - 3:1 for all non-text elements
132
+ - **Targets**:
133
+ - 7:1 for normal text
134
+ - 11:1 for high emphasis
135
+
136
+ ### High Contrast (+1.0)
137
+ Meets AAA accessibility:
138
+ - **Guaranteed minimums**:
139
+ - 7:1 for all text and icons
140
+ - 4.5:1 for all non-text elements
141
+ - **Targets**:
142
+ - 11:1 for normal text
143
+ - 21:1 for high emphasis
144
+
145
+ ## Automatic Adjustments
146
+
147
+ ### Tone Adjustment Algorithm
148
+
149
+ When colors don't meet contrast requirements:
150
+
151
+ ```javascript
152
+ function adjustForContrast(foreground, background, targetRatio) {
153
+ const currentRatio = getContrastRatio(foreground, background);
154
+
155
+ if (currentRatio >= targetRatio) {
156
+ return foreground; // Already accessible
157
+ }
158
+
159
+ // Convert to HCT for tone adjustment
160
+ const fgHct = toHct(foreground);
161
+ const bgHct = toHct(background);
162
+
163
+ // Determine adjustment direction
164
+ const lighten = bgHct.tone < 50;
165
+
166
+ // Binary search for optimal tone
167
+ let low = lighten ? bgHct.tone : 0;
168
+ let high = lighten ? 100 : bgHct.tone;
169
+
170
+ while (high - low > 1) {
171
+ const mid = (low + high) / 2;
172
+ const testColor = { ...fgHct, tone: mid };
173
+ const ratio = getContrastRatio(toRgb(testColor), background);
174
+
175
+ if (ratio >= targetRatio) {
176
+ if (lighten) high = mid;
177
+ else low = mid;
178
+ } else {
179
+ if (lighten) low = mid;
180
+ else high = mid;
181
+ }
182
+ }
183
+
184
+ return toRgb({ ...fgHct, tone: lighten ? high : low });
185
+ }
186
+ ```
187
+
188
+ ### Contrast Libraries
189
+
190
+ Pre-calculated adjustments for common scenarios:
191
+
192
+ ```javascript
193
+ // Ensure text is readable on any background
194
+ function getAccessibleTextColor(background) {
195
+ const bgLuminance = getLuminance(background);
196
+
197
+ // Use white or black based on background
198
+ if (bgLuminance > 0.5) {
199
+ return '#000000'; // Dark text on light background
200
+ } else {
201
+ return '#ffffff'; // Light text on dark background
202
+ }
203
+ }
204
+ ```
205
+
206
+ ## Color Roles and Accessibility
207
+
208
+ ### Guaranteed Accessible Pairs
209
+
210
+ Material Design ensures these pairs always meet contrast requirements:
211
+
212
+ | Background | Foreground | Min Contrast | Use Case |
213
+ |------------|------------|--------------|----------|
214
+ | surface | onSurface | 4.5:1 | Main content |
215
+ | primary | onPrimary | 4.5:1 | Primary actions |
216
+ | primaryContainer | onPrimaryContainer | 4.5:1 | Containers |
217
+ | error | onError | 4.5:1 | Error states |
218
+
219
+ ### Role-Based Adjustments
220
+
221
+ ```javascript
222
+ // Automatic role assignment with contrast guarantee
223
+ function assignColorRoles(sourceColor, contrastLevel = 0) {
224
+ const palette = generateTonalPalette(sourceColor);
225
+
226
+ // Adjust tone mappings based on contrast level
227
+ const toneMap = {
228
+ primary: 40 - (contrastLevel * 10),
229
+ onPrimary: 100,
230
+ primaryContainer: 90 + (contrastLevel * 5),
231
+ onPrimaryContainer: 10 - (contrastLevel * 5)
232
+ };
233
+
234
+ // Ensure minimum contrast
235
+ return Object.entries(toneMap).map(([role, tone]) => ({
236
+ role,
237
+ color: palette[tone],
238
+ meetsContrast: true
239
+ }));
240
+ }
241
+ ```
242
+
243
+ ## Best Practices
244
+
245
+ ### Design Guidelines
246
+
247
+ #### DO's
248
+ - ✅ Test all color combinations for contrast
249
+ - ✅ Provide high contrast mode options
250
+ - ✅ Use semantic color roles consistently
251
+ - ✅ Consider different types of color blindness
252
+ - ✅ Test with real content, not just color swatches
253
+
254
+ #### DON'Ts
255
+ - ❌ Rely on color alone to convey information
256
+ - ❌ Use low contrast for aesthetic reasons
257
+ - ❌ Assume large text allows poor contrast
258
+ - ❌ Ignore user preference for high contrast
259
+ - ❌ Use pure black on pure white (too harsh)
260
+
261
+ ### Testing Strategies
262
+
263
+ #### Automated Testing
264
+ ```javascript
265
+ // Test all color combinations in theme
266
+ function testThemeAccessibility(theme) {
267
+ const results = [];
268
+
269
+ // Test each foreground/background pair
270
+ theme.pairs.forEach(({ fg, bg, context }) => {
271
+ const ratio = getContrastRatio(fg, bg);
272
+ const required = getRequiredRatio(context);
273
+
274
+ results.push({
275
+ pair: `${fg} on ${bg}`,
276
+ context,
277
+ ratio,
278
+ passes: ratio >= required,
279
+ recommendation: getRecommendation(ratio, context)
280
+ });
281
+ });
282
+
283
+ return results;
284
+ }
285
+ ```
286
+
287
+ #### Manual Testing
288
+ 1. **Blur test**: Blur your vision - can you still read it?
289
+ 2. **Grayscale test**: Convert to grayscale - still distinguishable?
290
+ 3. **Sunlight test**: View in bright light conditions
291
+ 4. **Distance test**: Step back from screen
292
+ 5. **Squint test**: Squint eyes - text still readable?
293
+
294
+ ## Special Considerations
295
+
296
+ ### Color Blindness
297
+
298
+ Approximately 8% of men and 0.5% of women have color vision deficiency:
299
+
300
+ | Type | Frequency | Description | Design Impact |
301
+ |------|-----------|-------------|---------------|
302
+ | Protanopia | 1.3% | No red cones | Red/green confusion |
303
+ | Deuteranopia | 1.2% | No green cones | Red/green confusion |
304
+ | Tritanopia | 0.001% | No blue cones | Blue/yellow confusion |
305
+ | Monochromacy | Rare | No color vision | Rely on contrast only |
306
+
307
+ #### Design Strategies
308
+ ```javascript
309
+ // Ensure information isn't conveyed by color alone
310
+ ✓ Error: "❌ Invalid input" (icon + text)
311
+ ✗ Error: Red border only
312
+
313
+ // Use patterns or icons
314
+ ✓ Status: "🟢 Active" / "🔴 Inactive"
315
+ ✗ Status: Green/Red backgrounds only
316
+
317
+ // Provide sufficient contrast
318
+ ✓ Different tones for different states
319
+ ✗ Same tone, different hues only
320
+ ```
321
+
322
+ ### Dark Mode Considerations
323
+
324
+ Dark themes require special attention:
325
+
326
+ ```javascript
327
+ // Light theme
328
+ const lightTheme = {
329
+ surface: { tone: 99 }, // Very light
330
+ onSurface: { tone: 10 }, // Very dark
331
+ // Contrast: ~15:1
332
+ };
333
+
334
+ // Dark theme - NOT just inverted
335
+ const darkTheme = {
336
+ surface: { tone: 10 }, // Very dark
337
+ onSurface: { tone: 90 }, // Light, not white
338
+ // Contrast: ~13:1 (slightly less harsh)
339
+ };
340
+ ```
341
+
342
+ ### Transparency and Overlays
343
+
344
+ Colors with transparency need special handling:
345
+
346
+ ```javascript
347
+ function getEffectiveColor(foreground, background, alpha) {
348
+ // Composite the colors
349
+ const composite = blendColors(foreground, background, alpha);
350
+
351
+ // Check contrast of composite
352
+ return getContrastRatio(composite, background);
353
+ }
354
+
355
+ // Ensure minimum opacity for text
356
+ const minOpacity = {
357
+ normalText: 0.87, // ~87% opacity minimum
358
+ secondaryText: 0.60, // ~60% for secondary
359
+ disabledText: 0.38 // ~38% for disabled
360
+ };
361
+ ```
362
+
363
+ ## Implementation Examples
364
+
365
+ ### React Component
366
+
367
+ ```jsx
368
+ function AccessibleButton({ color, children }) {
369
+ const [textColor, setTextColor] = useState('#ffffff');
370
+
371
+ useEffect(() => {
372
+ // Automatically choose accessible text color
373
+ const accessible = getAccessibleTextColor(color);
374
+ setTextColor(accessible);
375
+ }, [color]);
376
+
377
+ return (
378
+ <button
379
+ style={{
380
+ backgroundColor: color,
381
+ color: textColor
382
+ }}
383
+ aria-label={children}
384
+ >
385
+ {children}
386
+ </button>
387
+ );
388
+ }
389
+ ```
390
+
391
+ ### CSS Custom Properties
392
+
393
+ ```css
394
+ :root {
395
+ /* Define with guaranteed contrast */
396
+ --color-background: hsl(0, 0%, 98%);
397
+ --color-text: hsl(0, 0%, 13%);
398
+ /* Contrast ratio: 15.3:1 ✓ */
399
+
400
+ --color-primary: hsl(239, 84%, 67%);
401
+ --color-on-primary: hsl(0, 0%, 100%);
402
+ /* Contrast ratio: 4.6:1 ✓ */
403
+ }
404
+
405
+ /* High contrast mode */
406
+ @media (prefers-contrast: high) {
407
+ :root {
408
+ --color-background: hsl(0, 0%, 100%);
409
+ --color-text: hsl(0, 0%, 0%);
410
+ /* Contrast ratio: 21:1 ✓ */
411
+ }
412
+ }
413
+ ```
414
+
415
+ ### Validation Tool
416
+
417
+ ```javascript
418
+ class AccessibilityValidator {
419
+ constructor(minRatio = 4.5) {
420
+ this.minRatio = minRatio;
421
+ }
422
+
423
+ validate(theme) {
424
+ const issues = [];
425
+
426
+ Object.entries(theme).forEach(([role, color]) => {
427
+ const background = this.getBackground(role, theme);
428
+ const ratio = getContrastRatio(color, background);
429
+
430
+ if (ratio < this.minRatio) {
431
+ issues.push({
432
+ role,
433
+ color,
434
+ background,
435
+ ratio,
436
+ required: this.minRatio,
437
+ suggestion: this.suggestFix(color, background)
438
+ });
439
+ }
440
+ });
441
+
442
+ return {
443
+ valid: issues.length === 0,
444
+ issues
445
+ };
446
+ }
447
+
448
+ suggestFix(fg, bg) {
449
+ return adjustForContrast(fg, bg, this.minRatio);
450
+ }
451
+ }
452
+ ```
453
+
454
+ ## Resources
455
+
456
+ ### Testing Tools
457
+ - Chrome DevTools (Lighthouse)
458
+ - Firefox Accessibility Inspector
459
+ - axe DevTools
460
+ - WAVE (WebAIM)
461
+ - Stark (Figma/Sketch plugin)
462
+
463
+ ### Guidelines
464
+ - [WCAG 2.1](https://www.w3.org/WAI/WCAG21/quickref/)
465
+ - [Material Design Accessibility](https://m3.material.io/foundations/accessible-design)
466
+ - [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
467
+
468
+ ## See Also
469
+
470
+ - [HCT System](./hct.md) - Tone-based contrast
471
+ - [Material Design](./material-design.md) - Contrast levels
472
+ - [Theme Matching](./theme-matching.md) - Accessibility scoring
473
+ - [Color Spaces](./color-spaces.md) - Understanding luminance