@zohodesk/components 1.6.7 → 1.6.11-exp-6

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 (123) hide show
  1. package/README.md +15 -0
  2. package/assets/Appearance/dark/mode/Component_v1_DarkMode.module.css +68 -0
  3. package/assets/Appearance/light/mode/Component_v1_LightMode.module.css +68 -0
  4. package/assets/Appearance/pureDark/mode/Component_v1_PureDarkMode.module.css +68 -0
  5. package/es/Buttongroup/Buttongroup.module.css +10 -30
  6. package/es/CheckBox/CheckBox.module.css +3 -10
  7. package/es/DateTime/DateTime.module.css +22 -35
  8. package/es/DateTime/YearView.module.css +8 -10
  9. package/es/DropBox/DropBoxElement/css/DropBoxElement.module.css +3 -2
  10. package/es/DropDown/DropDown.module.css +2 -1
  11. package/es/DropDown/DropDownItem.module.css +1 -8
  12. package/es/DropDown/DropDownSeparator.module.css +2 -1
  13. package/es/ListItem/ListItem.module.css +4 -15
  14. package/es/MultiSelect/MobileHeader/MobileHeader.module.css +3 -2
  15. package/es/MultiSelect/MultiSelect.module.css +21 -34
  16. package/es/MultiSelect/SelectedOptions.module.css +6 -10
  17. package/es/Radio/Radio.module.css +3 -3
  18. package/es/ResponsiveDropBox/ResponsiveDropBox.module.css +1 -1
  19. package/es/Ribbon/Ribbon.module.css +9 -12
  20. package/es/Select/Select.module.css +22 -17
  21. package/es/Switch/Switch.module.css +1 -8
  22. package/es/Tab/Tab.module.css +8 -15
  23. package/es/Tab/Tabs.module.css +12 -22
  24. package/es/Tag/Tag.module.css +4 -3
  25. package/es/Tooltip/Tooltip.module.css +3 -2
  26. package/es/Typography/Typography.js +18 -8
  27. package/es/Typography/__tests__/Typography.spec.js +198 -6
  28. package/es/Typography/__tests__/__snapshots__/Typography.spec.js.snap +1235 -2
  29. package/es/Typography/css/Typography.module.css +4 -0
  30. package/es/Typography/css/cssJSLogic.js +53 -21
  31. package/es/Typography/props/defaultProps.js +4 -3
  32. package/es/Typography/props/propTypes.js +68 -26
  33. package/es/Typography/utils/textHighlighter.js +4 -2
  34. package/es/shared/ArrowIcon/ArrowIcon.module.css +3 -2
  35. package/es/v1/Button/Button.js +201 -0
  36. package/es/v1/Button/README.md +110 -0
  37. package/es/v1/Button/__tests__/Button.spec.js +272 -0
  38. package/es/v1/Button/__tests__/__snapshots__/Button.spec.js.snap +1160 -0
  39. package/es/v1/Button/_shared/Loader/Loader.js +33 -0
  40. package/es/v1/Button/_shared/Loader/Loader.module.css +42 -0
  41. package/es/v1/Button/_shared/Loader/__tests__/Loader.spec.js +21 -0
  42. package/es/v1/Button/_shared/Loader/__tests__/__snapshots__/Loader.spec.js.snap +49 -0
  43. package/es/v1/Button/_shared/Loader/props/defaultProps.js +4 -0
  44. package/es/v1/Button/_shared/Loader/props/propTypes.js +7 -0
  45. package/es/v1/Button/_shared/SuccessTick/SuccessTick.js +25 -0
  46. package/es/v1/Button/_shared/SuccessTick/SuccessTick.module.css +21 -0
  47. package/es/v1/Button/_shared/SuccessTick/__tests__/SuccessTick.spec.js +21 -0
  48. package/es/v1/Button/_shared/SuccessTick/__tests__/__snapshots__/SuccessTick.spec.js.snap +31 -0
  49. package/es/v1/Button/_shared/SuccessTick/props/defaultProps.js +4 -0
  50. package/es/v1/Button/_shared/SuccessTick/props/propTypes.js +7 -0
  51. package/es/v1/Button/constants/index.js +82 -0
  52. package/es/v1/Button/css/Button_v1.module.css +119 -0
  53. package/es/v1/Button/css/cssJSLogic.js +96 -0
  54. package/es/v1/Button/index.js +2 -0
  55. package/es/v1/Button/props/defaultProps.js +26 -0
  56. package/es/v1/Button/props/propTypes.js +43 -0
  57. package/es/v1/helpers/colorHelpers/background/backgroundColor.module.css +629 -0
  58. package/es/v1/helpers/colorHelpers/border/borderColor.module.css +489 -0
  59. package/es/v1/helpers/colorHelpers/colorHelper.js +176 -0
  60. package/es/v1/helpers/colorHelpers/constants/index.js +79 -0
  61. package/es/v1/helpers/colorHelpers/index.js +4 -0
  62. package/es/v1/helpers/colorHelpers/paletteUtilities.README.md +415 -0
  63. package/es/v1/helpers/colorHelpers/text/textColor.module.css +368 -0
  64. package/lib/Buttongroup/Buttongroup.module.css +10 -30
  65. package/lib/CheckBox/CheckBox.module.css +3 -10
  66. package/lib/DateTime/DateTime.module.css +22 -35
  67. package/lib/DateTime/YearView.module.css +8 -10
  68. package/lib/DropBox/DropBoxElement/css/DropBoxElement.module.css +3 -2
  69. package/lib/DropDown/DropDown.module.css +2 -1
  70. package/lib/DropDown/DropDownItem.module.css +1 -8
  71. package/lib/DropDown/DropDownSeparator.module.css +2 -1
  72. package/lib/ListItem/ListItem.module.css +4 -15
  73. package/lib/MultiSelect/MobileHeader/MobileHeader.module.css +3 -2
  74. package/lib/MultiSelect/MultiSelect.module.css +21 -34
  75. package/lib/MultiSelect/SelectedOptions.module.css +6 -10
  76. package/lib/Radio/Radio.module.css +3 -3
  77. package/lib/ResponsiveDropBox/ResponsiveDropBox.module.css +1 -1
  78. package/lib/Ribbon/Ribbon.module.css +9 -12
  79. package/lib/Select/Select.module.css +22 -17
  80. package/lib/Switch/Switch.module.css +1 -8
  81. package/lib/Tab/Tab.module.css +8 -15
  82. package/lib/Tab/Tabs.module.css +12 -22
  83. package/lib/Tag/Tag.module.css +4 -3
  84. package/lib/Tooltip/Tooltip.module.css +3 -2
  85. package/lib/Typography/Typography.js +15 -5
  86. package/lib/Typography/__tests__/Typography.spec.js +284 -92
  87. package/lib/Typography/__tests__/__snapshots__/Typography.spec.js.snap +1235 -2
  88. package/lib/Typography/css/Typography.module.css +4 -0
  89. package/lib/Typography/css/cssJSLogic.js +38 -6
  90. package/lib/Typography/props/defaultProps.js +6 -3
  91. package/lib/Typography/props/propTypes.js +67 -23
  92. package/lib/Typography/utils/textHighlighter.js +6 -3
  93. package/lib/shared/ArrowIcon/ArrowIcon.module.css +3 -2
  94. package/lib/v1/Button/Button.js +239 -0
  95. package/lib/v1/Button/README.md +110 -0
  96. package/lib/v1/Button/__tests__/Button.spec.js +293 -0
  97. package/lib/v1/Button/__tests__/__snapshots__/Button.spec.js.snap +1160 -0
  98. package/lib/v1/Button/_shared/Loader/Loader.js +43 -0
  99. package/lib/v1/Button/_shared/Loader/Loader.module.css +42 -0
  100. package/lib/v1/Button/_shared/Loader/__tests__/Loader.spec.js +28 -0
  101. package/lib/v1/Button/_shared/Loader/__tests__/__snapshots__/Loader.spec.js.snap +49 -0
  102. package/lib/v1/Button/_shared/Loader/props/defaultProps.js +11 -0
  103. package/lib/v1/Button/_shared/Loader/props/propTypes.js +18 -0
  104. package/lib/v1/Button/_shared/SuccessTick/SuccessTick.js +35 -0
  105. package/lib/v1/Button/_shared/SuccessTick/SuccessTick.module.css +21 -0
  106. package/lib/v1/Button/_shared/SuccessTick/__tests__/SuccessTick.spec.js +28 -0
  107. package/lib/v1/Button/_shared/SuccessTick/__tests__/__snapshots__/SuccessTick.spec.js.snap +31 -0
  108. package/lib/v1/Button/_shared/SuccessTick/props/defaultProps.js +11 -0
  109. package/lib/v1/Button/_shared/SuccessTick/props/propTypes.js +18 -0
  110. package/lib/v1/Button/constants/index.js +114 -0
  111. package/lib/v1/Button/css/Button_v1.module.css +119 -0
  112. package/lib/v1/Button/css/cssJSLogic.js +88 -0
  113. package/lib/v1/Button/index.js +21 -0
  114. package/lib/v1/Button/props/defaultProps.js +36 -0
  115. package/lib/v1/Button/props/propTypes.js +56 -0
  116. package/lib/v1/helpers/colorHelpers/background/backgroundColor.module.css +629 -0
  117. package/lib/v1/helpers/colorHelpers/border/borderColor.module.css +489 -0
  118. package/lib/v1/helpers/colorHelpers/colorHelper.js +190 -0
  119. package/lib/v1/helpers/colorHelpers/constants/index.js +87 -0
  120. package/lib/v1/helpers/colorHelpers/index.js +57 -0
  121. package/lib/v1/helpers/colorHelpers/paletteUtilities.README.md +415 -0
  122. package/lib/v1/helpers/colorHelpers/text/textColor.module.css +368 -0
  123. package/package.json +9 -9
@@ -0,0 +1,79 @@
1
+ export const TONE_INTENSITY = {
2
+ brand: {
3
+ base: 80,
4
+ hover: 100,
5
+ light: 10,
6
+ lightHover: 20,
7
+ borderLight: 10
8
+ },
9
+ grey: {
10
+ base: 65,
11
+ hover: 55,
12
+ light: 10,
13
+ lightHover: 15,
14
+ borderLight: 15,
15
+ textHover: 100
16
+ },
17
+ blue: {
18
+ base: 80,
19
+ hover: 100,
20
+ light: 10,
21
+ lightHover: 20,
22
+ borderLight: 10
23
+ },
24
+ green: {
25
+ base: 80,
26
+ hover: 100,
27
+ light: 10,
28
+ lightHover: 30,
29
+ borderLight: 30
30
+ },
31
+ orange: {
32
+ base: 80,
33
+ hover: 100,
34
+ light: 10,
35
+ lightHover: 15,
36
+ borderLight: 15
37
+ },
38
+ red: {
39
+ base: 70,
40
+ hover: 100,
41
+ light: 10,
42
+ lightHover: 30,
43
+ borderLight: 30
44
+ },
45
+ yellow: {
46
+ base: 80,
47
+ hover: 100,
48
+ light: 10,
49
+ lightHover: 20,
50
+ borderLight: 20
51
+ }
52
+ };
53
+ export const PALETTE_CONFIG = {
54
+ default: {
55
+ tone: 'brand',
56
+ textTone: 'brand',
57
+ filledTextTone: 'brand-filled'
58
+ },
59
+ primary: {
60
+ tone: 'blue',
61
+ textTone: 'blue',
62
+ filledTextTone: 'white'
63
+ },
64
+ secondary: {
65
+ tone: 'grey',
66
+ textTone: 'grey',
67
+ filledTextTone: 'white'
68
+ },
69
+ danger: {
70
+ tone: 'red',
71
+ textTone: 'red',
72
+ filledTextTone: 'white'
73
+ },
74
+ success: {
75
+ tone: 'green',
76
+ textTone: 'green',
77
+ filledTextTone: 'white'
78
+ }
79
+ };
@@ -0,0 +1,4 @@
1
+ export { default } from "./colorHelper";
2
+ export { default as getPaletteClasses } from "./colorHelper";
3
+ export { getBgClass, getTextClass, getBorderClass } from "./colorHelper";
4
+ export { PALETTE_CONFIG, TONE_INTENSITY } from "./constants";
@@ -0,0 +1,415 @@
1
+ # Color Helpers
2
+
3
+ Tailwind-inspired color utility classes and a `colorHelper` for DOT components.
4
+
5
+ ---
6
+
7
+ ## File Structure
8
+
9
+ ```
10
+ colorHelpers/
11
+ ├── background/
12
+ │ └── backgroundColor.module.css # Background color utilities
13
+ ├── text/
14
+ │ └── textColor.module.css # Text color utilities
15
+ ├── border/
16
+ │ └── borderColor.module.css # Border color utilities
17
+ ├── constants/
18
+ │ └── index.js # PALETTE_CONFIG (palette → tone mapping)
19
+ ├── colorHelper.js # getPaletteClasses + getBgClass, getTextClass, getBorderClass
20
+ └── paletteUtilities.README.md # This file
21
+ ```
22
+
23
+ ---
24
+
25
+ ## Available Colors
26
+
27
+ All three CSS files share the same 7 color tones:
28
+
29
+ | Tone | Token Family | Use Case |
30
+ |------|--------------|----------|
31
+ | **default** | `--zdt_v1_palette_default_*` | Default/neutral actions |
32
+ | **grey** | `--zdt_v1_palette_grey_*` | Secondary, muted elements |
33
+ | **blue** | `--zdt_v1_palette_blue_*` | Information, primary actions |
34
+ | **green** | `--zdt_v1_palette_green_*` | Success, positive status |
35
+ | **orange** | `--zdt_v1_palette_orange_*` | Warning, caution |
36
+ | **red** | `--zdt_v1_palette_red_*` | Error, danger, destructive actions |
37
+ | **yellow** | `--zdt_v1_palette_yellow_*` | Alerts, highlights |
38
+
39
+ ---
40
+
41
+ ## Available Utilities
42
+
43
+ ### Background (`background/backgroundColor.module.css`)
44
+
45
+ Per color (`default`, `grey`, `blue`, `green`, `orange`, `red`, `yellow`):
46
+
47
+ | Class Pattern | Description |
48
+ |---------------|-------------|
49
+ | `.bg-{color}` | Base background |
50
+ | `.bg-{color}-light` | Light background variant |
51
+ | `.hover\:bg-{color}:hover` | Hover state |
52
+ | `.hover\:bg-{color}-light:hover` | Light hover state |
53
+ | `.focus\:bg-{color}:focus` | Focus state |
54
+ | `.focus\:bg-{color}-light:focus` | Light focus state |
55
+ | `.active\:bg-{color}:active` | Active state |
56
+ | `.active\:bg-{color}-light:active` | Light active state |
57
+ | `.selected\:bg-{color}` | Selected state |
58
+ | `.selected\:bg-{color}-light` | Light selected state |
59
+
60
+ **Utility classes:** `.bg-transparent`, `.bg-white`, `.bg-black`
61
+
62
+ ### Text (`text/textColor.module.css`)
63
+
64
+ Per color (`default`, `grey`, `blue`, `green`, `orange`, `red`, `yellow`):
65
+
66
+ | Class Pattern | Description |
67
+ |---------------|-------------|
68
+ | `.text-{color}` | Base text color |
69
+ | `.hover\:text-{color}:hover` | Hover state |
70
+ | `.focus\:text-{color}:focus` | Focus state |
71
+ | `.active\:text-{color}:active` | Active state |
72
+ | `.selected\:text-{color}` | Selected state |
73
+
74
+ **Special:** `.text-default-filled` (+ hover/focus/active/selected) — uses `--zdt_v1_palette_default_filled_text` for filled default backgrounds.
75
+
76
+ **Utility classes:** `.text-transparent`, `.text-white`, `.text-black`
77
+
78
+ > **Note:** Text has no `-light` variant. The `colorHelper` switches to `filledTextTone` (e.g., `white`) when the background is filled.
79
+
80
+ ### Border (`border/borderColor.module.css`)
81
+
82
+ Per color (`default`, `grey`, `blue`, `green`, `orange`, `red`, `yellow`):
83
+
84
+ | Class Pattern | Description |
85
+ |---------------|-------------|
86
+ | `.border-{color}` | Base border |
87
+ | `.border-{color}-light` | Light border variant (resting state only) |
88
+ | `.hover\:border-{color}:hover` | Hover state |
89
+ | `.focus\:border-{color}:focus` | Focus state |
90
+ | `.active\:border-{color}:active` | Active state |
91
+ | `.selected\:border-{color}` | Selected state |
92
+
93
+ **Utility classes:** `.border-transparent`, `.border-white`, `.border-black`
94
+
95
+ > **Note:** Border state classes only use the base tone — no `-light` state variants. The `-light` class is available for the resting state only.
96
+
97
+ ---
98
+
99
+ ## Direct CSS Usage (Examples)
100
+
101
+ Import only the CSS modules you need and compose classes directly.
102
+
103
+ ### Example 1: Status Tag (text + background)
104
+
105
+ ```javascript
106
+ import bgStyle from './background/backgroundColor.module.css';
107
+ import textStyle from './text/textColor.module.css';
108
+
109
+ function StatusTag({ status }) {
110
+ const className = compileClassNames({
111
+ [bgStyle['bg-green-light']]: status === 'success',
112
+ [bgStyle['bg-red-light']]: status === 'error',
113
+ [bgStyle['bg-orange-light']]: status === 'warning',
114
+ [textStyle['text-green']]: status === 'success',
115
+ [textStyle['text-red']]: status === 'error',
116
+ [textStyle['text-orange']]: status === 'warning',
117
+ });
118
+
119
+ return <span className={className}>{status}</span>;
120
+ }
121
+ ```
122
+
123
+ ### Example 2: Bordered Card (border + background)
124
+
125
+ ```javascript
126
+ import bgStyle from './background/backgroundColor.module.css';
127
+ import borderStyle from './border/borderColor.module.css';
128
+
129
+ function Card({ children, variant }) {
130
+ const className = compileClassNames({
131
+ [bgStyle['bg-blue-light']]: variant === 'info',
132
+ [bgStyle['bg-red-light']]: variant === 'error',
133
+ [borderStyle['border-blue']]: variant === 'info',
134
+ [borderStyle['border-red']]: variant === 'error',
135
+ });
136
+
137
+ return <div className={className}>{children}</div>;
138
+ }
139
+ ```
140
+
141
+ ### Example 3: Interactive Button (text + background + border + hover)
142
+
143
+ ```javascript
144
+ import bgStyle from './background/backgroundColor.module.css';
145
+ import textStyle from './text/textColor.module.css';
146
+ import borderStyle from './border/borderColor.module.css';
147
+
148
+ function Button({ label, variant }) {
149
+ // Primary: blue bg, white text, blue border
150
+ const primaryClasses = compileClassNames({
151
+ [bgStyle['bg-blue']]: true,
152
+ [bgStyle['hover:bg-blue']]: true,
153
+ [textStyle['text-white']]: true,
154
+ [borderStyle['border-blue']]: true,
155
+ [borderStyle['hover:border-blue']]: true,
156
+ });
157
+
158
+ // Danger: red bg, white text, red border
159
+ const dangerClasses = compileClassNames({
160
+ [bgStyle['bg-red']]: true,
161
+ [bgStyle['hover:bg-red']]: true,
162
+ [textStyle['text-white']]: true,
163
+ [borderStyle['border-red']]: true,
164
+ [borderStyle['hover:border-red']]: true,
165
+ });
166
+
167
+ return <button className={variant === 'danger' ? dangerClasses : primaryClasses}>{label}</button>;
168
+ }
169
+ ```
170
+ ---
171
+
172
+ ## Using `colorHelper.js`
173
+
174
+ ### Named Exports
175
+
176
+ Three utility functions return individual CSS module classes:
177
+
178
+ ```javascript
179
+ import { getBgClass, getTextClass, getBorderClass } from './colorHelper';
180
+ ```
181
+
182
+ #### `getBgClass({ state?, tone, isLighter? })`
183
+
184
+ Returns a background CSS class from `backgroundColor.module.css`.
185
+
186
+ | Parameter | Type | Required | Description |
187
+ |-----------|------|----------|-------------|
188
+ | `tone` | `string` | Yes | Color tone (`default`, `grey`, `blue`, `green`, `orange`, `red`, `yellow`, `white`, `black`) |
189
+ | `state` | `string` | No | State prefix (`hover`, `focus`, `active`, `selected`). Omit for base class. |
190
+ | `isLighter` | `boolean` | No | `true` → appends `-light` to the tone |
191
+
192
+ **Generated key pattern:** `[state:]bg-{tone}[-light]`
193
+
194
+ ```javascript
195
+ getBgClass({ tone: 'blue' }) // → paletteBgStyle['bg-blue']
196
+ getBgClass({ tone: 'blue', isLighter: true }) // → paletteBgStyle['bg-blue-light']
197
+ getBgClass({ state: 'hover', tone: 'red' }) // → paletteBgStyle['hover:bg-red']
198
+ getBgClass({ state: 'hover', tone: 'red', isLighter: true }) // → paletteBgStyle['hover:bg-red-light']
199
+ ```
200
+
201
+ #### `getTextClass({ state?, textTone })`
202
+
203
+ Returns a text CSS class from `textColor.module.css`.
204
+
205
+ | Parameter | Type | Required | Description |
206
+ |-----------|------|----------|-------------|
207
+ | `textTone` | `string` | Yes | Text tone (`default`, `grey`, `blue`, `green`, `orange`, `red`, `yellow`, `white`, `black`, `default-filled`) |
208
+ | `state` | `string` | No | State prefix (`hover`, `focus`, `active`, `selected`). Omit for base class. |
209
+
210
+ > **Note:** `textTone` has no `isLighter` equivalent. Use `filledTextTone` (e.g. `white`) directly when needed.
211
+
212
+ **Generated key pattern:** `[state:]text-{textTone}`
213
+
214
+ ```javascript
215
+ getTextClass({ textTone: 'green' }) // → paletteTextStyle['text-green']
216
+ getTextClass({ state: 'hover', textTone: 'white' }) // → paletteTextStyle['hover:text-white']
217
+ getTextClass({ textTone: 'default-filled' }) // → paletteTextStyle['text-default-filled']
218
+ ```
219
+
220
+ #### `getBorderClass({ state?, tone, isLighter? })`
221
+
222
+ Returns a border CSS class from `borderColor.module.css`.
223
+
224
+ | Parameter | Type | Required | Description |
225
+ |-----------|------|----------|-------------|
226
+ | `tone` | `string` | Yes | Color tone (`default`, `grey`, `blue`, `green`, `orange`, `red`, `yellow`) |
227
+ | `state` | `string` | No | State prefix (`hover`, `focus`, `active`, `selected`). Omit for base class. |
228
+ | `isLighter` | `boolean` | No | `true` → appends `-light` to the tone (resting state only by convention) |
229
+
230
+ **Generated key pattern:** `[state:]border-{tone}[-light]`
231
+
232
+ ```javascript
233
+ getBorderClass({ tone: 'blue' }) // → paletteBorderStyle['border-blue']
234
+ getBorderClass({ tone: 'blue', isLighter: true }) // → paletteBorderStyle['border-blue-light']
235
+ getBorderClass({ state: 'hover', tone: 'red' }) // → paletteBorderStyle['hover:border-red']
236
+ ```
237
+
238
+ #### Internal Helpers (not exported)
239
+
240
+ - **`toTone(tone, isLighter)`** — returns `'{tone}-light'` if `isLighter` is truthy, else `'{tone}'`
241
+ - **`withState(state, key)`** — returns `'{state}:{key}'` if `state` is truthy, else `'{key}'`
242
+
243
+ ---
244
+
245
+ ### Default Export: `getPaletteClasses`
246
+
247
+ For components accepting `palette`, `bgAppearance`, `borderAppearance`, and `paletteShade` props.
248
+
249
+ ```javascript
250
+ import getPaletteClasses from './colorHelper';
251
+ ```
252
+
253
+ #### Palette → Tone Mapping (from `PALETTE_CONFIG`)
254
+
255
+ | Palette | Tone (bg/border) | Text Tone | Filled Text Tone |
256
+ |---------|-------------------|-----------|-------------------|
257
+ | `default` | `default` | `default` | `default-filled` |
258
+ | `primary` | `blue` | `blue` | `white` |
259
+ | `secondary` | `grey` | `grey` | `white` |
260
+ | `danger` | `red` | `red` | `white` |
261
+ | `success` | `green` | `green` | `white` |
262
+
263
+ Unknown palettes return `DUMMY_OBJECT` (empty frozen object).
264
+
265
+ #### Parameters
266
+
267
+ | Parameter | Values | Effect |
268
+ |-----------|--------|--------|
269
+ | `palette` | `default` \| `primary` \| `secondary` \| `danger` \| `success` | Selects the color tone config from `PALETTE_CONFIG` |
270
+ | `bgAppearance` | `'none'` \| `'filled'` \| other | `'filled'` → base bg + state bg; `'none'` → no bg, no state bg, no filled text logic; other → no base bg but state bg + filled text logic |
271
+ | `borderAppearance` | `'none'` \| `'onHover'` \| other | `'none'` → transparent base, no state borders; `'onHover'` → transparent base, with state borders; other → visible base + state borders |
272
+ | `paletteShade` | `'lighter'` \| other | `'lighter'` → `-light` variant for bg and base border; also keeps text as `textTone` instead of `filledTextTone` |
273
+
274
+ #### Text Tone Logic
275
+
276
+ The text color depends on both `bgAppearance` and `paletteShade`:
277
+
278
+ | Condition | Base text (`text`) | State text (`hoverText`, etc.) |
279
+ |---|---|---|
280
+ | `bgAppearance: 'filled'` + default shade | `filledTextTone` (e.g. `white`) | `filledTextTone` |
281
+ | `bgAppearance: 'filled'` + `'lighter'` shade | `textTone` (e.g. `blue`) | `textTone` |
282
+ | `bgAppearance:` other (not `'none'`) + default shade | `textTone` | `filledTextTone` |
283
+ | `bgAppearance:` other (not `'none'`) + `'lighter'` shade | `textTone` | `textTone` |
284
+ | `bgAppearance: 'none'` | `textTone` | `textTone` |
285
+
286
+ > **Key insight:** `baseTextTone = isFilledBg && !isLighter ? filledTextTone : textTone`. `stateTextTone = hasBgState && !isLighter ? filledTextTone : textTone`. This means state text can differ from base text when `bgAppearance` is not `'filled'` but also not `'none'`.
287
+
288
+ #### Return Value
289
+
290
+ ```javascript
291
+ {
292
+ bg, // getBgClass({ tone, isLighter }) — only if bgAppearance === 'filled'
293
+ hoverBg, // getBgClass({ state: 'hover', tone, isLighter }) — if bgAppearance !== 'none'
294
+ focusBg, // getBgClass({ state: 'focus', tone, isLighter }) — if bgAppearance !== 'none'
295
+ activeBg, // getBgClass({ state: 'active', tone, isLighter }) — if bgAppearance !== 'none'
296
+ selectedBg, // getBgClass({ state: 'selected', tone, isLighter }) — if bgAppearance !== 'none'
297
+ text, // getTextClass({ textTone: baseTextTone })
298
+ hoverText, // getTextClass({ state: 'hover', textTone: stateTextTone })
299
+ focusText, // getTextClass({ state: 'focus', textTone: stateTextTone })
300
+ activeText, // getTextClass({ state: 'active', textTone: stateTextTone })
301
+ selectedText, // getTextClass({ state: 'selected', textTone: stateTextTone })
302
+ border, // 'border-transparent' if onHover/none — else getBorderClass({ tone, isLighter })
303
+ hoverBorder, // getBorderClass({ state: 'hover', tone }) — if borderAppearance !== 'none'
304
+ focusBorder, // getBorderClass({ state: 'focus', tone }) — if borderAppearance !== 'none'
305
+ activeBorder, // getBorderClass({ state: 'active', tone }) — if borderAppearance !== 'none'
306
+ selectedBorder // getBorderClass({ state: 'selected', tone }) — if borderAppearance !== 'none'
307
+ }
308
+ ```
309
+
310
+ > **Note:** State border classes always use the base tone (no `isLighter`), even when the resting border uses `-light`.
311
+
312
+ #### Example: Filled Primary Button
313
+
314
+ ```javascript
315
+ const classes = getPaletteClasses({
316
+ palette: 'primary',
317
+ bgAppearance: 'filled',
318
+ borderAppearance: 'visible',
319
+ paletteShade: 'default',
320
+ });
321
+ // classes.bg → 'bg-blue' (filled + default shade)
322
+ // classes.hoverBg → 'hover:bg-blue'
323
+ // classes.text → 'text-white' (filledTextTone — filled + not lighter)
324
+ // classes.hoverText → 'hover:text-white' (filledTextTone — hasBgState + not lighter)
325
+ // classes.border → 'border-blue' (visible appearance)
326
+ // classes.hoverBorder → 'hover:border-blue'
327
+ ```
328
+
329
+ #### Example: Light Danger Tag
330
+
331
+ ```javascript
332
+ const classes = getPaletteClasses({
333
+ palette: 'danger',
334
+ bgAppearance: 'filled',
335
+ borderAppearance: 'none',
336
+ paletteShade: 'lighter',
337
+ });
338
+ // classes.bg → 'bg-red-light' (filled + lighter shade)
339
+ // classes.hoverBg → 'hover:bg-red-light'
340
+ // classes.text → 'text-red' (textTone — lighter shade overrides filledTextTone)
341
+ // classes.hoverText → 'hover:text-red' (textTone — lighter shade)
342
+ // classes.border → 'border-transparent' (borderAppearance: 'none')
343
+ // classes.hoverBorder → undefined (no state borders with 'none')
344
+ ```
345
+
346
+ #### Example: Ghost Secondary Button
347
+
348
+ ```javascript
349
+ const classes = getPaletteClasses({
350
+ palette: 'secondary',
351
+ bgAppearance: 'none',
352
+ borderAppearance: 'onHover',
353
+ paletteShade: 'default',
354
+ });
355
+ // classes.bg → undefined (not filled)
356
+ // classes.hoverBg → undefined (bgAppearance: 'none')
357
+ // classes.text → 'text-grey' (textTone — not filled)
358
+ // classes.hoverText → 'hover:text-grey' (textTone — bgAppearance 'none' → no filled text)
359
+ // classes.border → 'border-transparent' (onHover → transparent base)
360
+ // classes.hoverBorder → 'hover:border-grey' (onHover → state borders present)
361
+ ```
362
+
363
+ #### Example: Hover-fill Button (bgAppearance: non-standard value)
364
+
365
+ ```javascript
366
+ const classes = getPaletteClasses({
367
+ palette: 'primary',
368
+ bgAppearance: 'hover-fill', // any value that isn't 'none' or 'filled'
369
+ borderAppearance: 'visible',
370
+ paletteShade: 'default',
371
+ });
372
+ // classes.bg → undefined (not 'filled' → no base bg)
373
+ // classes.hoverBg → 'hover:bg-blue' (not 'none' → state bg present)
374
+ // classes.text → 'text-blue' (baseTextTone — not filled, so textTone)
375
+ // classes.hoverText → 'hover:text-white' (stateTextTone — hasBgState + not lighter → filledTextTone!)
376
+ // classes.border → 'border-blue' (visible)
377
+ // classes.hoverBorder → 'hover:border-blue'
378
+ ```
379
+
380
+ > This shows a key behavior: the base text is the normal tone, but **state text switches to `filledTextTone`** because the hover/state background will be filled (dark).
381
+
382
+ ---
383
+
384
+ ## Behavior Summary
385
+
386
+ | Property | Lighter shade (`paletteShade: 'lighter'`) | Default shade |
387
+ |----------|-------------------------------------------|---------------|
388
+ | **Background** | Uses `-light` variant (e.g. `bg-blue-light`) | Uses base (e.g. `bg-blue`) |
389
+ | **Base text** | Always `textTone` (e.g. `text-blue`) | `filledTextTone` when filled (e.g. `text-white`), else `textTone` |
390
+ | **State text** | Always `textTone` (e.g. `hover:text-blue`) | `filledTextTone` when `bgAppearance !== 'none'` (e.g. `hover:text-white`), else `textTone` |
391
+ | **Border (base)** | Uses `-light` variant if not transparent (e.g. `border-blue-light`) | Uses base if not transparent (e.g. `border-blue`) |
392
+ | **Border (states)** | Always base tone (e.g. `hover:border-blue`) | Always base tone |
393
+
394
+ ---
395
+
396
+ ## FAQ
397
+
398
+ **Q: Why do text classes have no `-light` variant?**
399
+ A: Text on a light background should stay the base color for readability. When the background is filled (dark), text switches to a contrasting tone (e.g. `white`) instead.
400
+
401
+ **Q: Why do border state classes not use `-light`?**
402
+ A: Border hover/focus/active/selected states always use the full-intensity base tone for visibility, even when the resting border uses a lighter shade.
403
+
404
+ **Q: What happens if I pass an unknown palette to `getPaletteClasses`?**
405
+ A: It returns `DUMMY_OBJECT` (an empty frozen object), so no classes are applied.
406
+
407
+ **Q: Can I use CSS classes directly without `getPaletteClasses`?**
408
+ A: Yes. The CSS modules are standalone. `getPaletteClasses` is a convenience for components that accept palette/appearance/shade props.
409
+
410
+ **Q: When does state text differ from base text?**
411
+ A: When `bgAppearance` is neither `'none'` nor `'filled'` with default (non-lighter) shade. Base text uses `textTone` (colored), but state text uses `filledTextTone` (e.g. `white`) — because the hover/state will show a filled background.
412
+
413
+ ---
414
+
415
+ **Last Updated:** March 2026