@duskmoon-dev/core 1.12.4 → 1.13.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 (62) hide show
  1. package/dist/components/alert.css +64 -2
  2. package/dist/components/appbar.css +119 -21
  3. package/dist/components/autocomplete.css +63 -3
  4. package/dist/components/avatar.css +22 -2
  5. package/dist/components/button.css +101 -49
  6. package/dist/components/card.css +38 -2
  7. package/dist/components/cascader.css +59 -9
  8. package/dist/components/checkbox.css +15 -5
  9. package/dist/components/chip.css +122 -2
  10. package/dist/components/collapse.css +32 -0
  11. package/dist/components/datepicker.css +79 -6
  12. package/dist/components/file-upload.css +68 -8
  13. package/dist/components/form.css +2 -1
  14. package/dist/components/index.css +1583 -409
  15. package/dist/components/input.css +21 -67
  16. package/dist/components/multi-select.css +59 -9
  17. package/dist/components/otp-input.css +48 -16
  18. package/dist/components/pin-input.css +50 -13
  19. package/dist/components/radio.css +12 -2
  20. package/dist/components/rating.css +35 -3
  21. package/dist/components/segment-control.css +23 -2
  22. package/dist/components/select.css +21 -37
  23. package/dist/components/slider.css +130 -6
  24. package/dist/components/switch.css +27 -4
  25. package/dist/components/textarea.css +21 -96
  26. package/dist/components/time-input.css +61 -12
  27. package/dist/components/toast.css +72 -3
  28. package/dist/components/toggle.css +63 -6
  29. package/dist/components/tooltip.css +84 -0
  30. package/dist/components/tree-select.css +60 -11
  31. package/dist/esm/components/alert.js +64 -2
  32. package/dist/esm/components/appbar.js +119 -21
  33. package/dist/esm/components/autocomplete.js +63 -3
  34. package/dist/esm/components/avatar.js +22 -2
  35. package/dist/esm/components/button.js +101 -49
  36. package/dist/esm/components/card.js +38 -2
  37. package/dist/esm/components/cascader.js +59 -9
  38. package/dist/esm/components/checkbox.js +15 -5
  39. package/dist/esm/components/chip.js +122 -2
  40. package/dist/esm/components/collapse.js +32 -0
  41. package/dist/esm/components/datepicker.js +79 -6
  42. package/dist/esm/components/file-upload.js +68 -8
  43. package/dist/esm/components/form.js +2 -1
  44. package/dist/esm/components/input.js +21 -67
  45. package/dist/esm/components/multi-select.js +59 -9
  46. package/dist/esm/components/otp-input.js +48 -16
  47. package/dist/esm/components/pin-input.js +50 -13
  48. package/dist/esm/components/radio.js +12 -2
  49. package/dist/esm/components/rating.js +35 -3
  50. package/dist/esm/components/segment-control.js +23 -2
  51. package/dist/esm/components/select.js +21 -37
  52. package/dist/esm/components/slider.js +130 -6
  53. package/dist/esm/components/switch.js +27 -4
  54. package/dist/esm/components/textarea.js +21 -96
  55. package/dist/esm/components/time-input.js +61 -12
  56. package/dist/esm/components/toast.js +72 -3
  57. package/dist/esm/components/toggle.js +63 -6
  58. package/dist/esm/components/tooltip.js +84 -0
  59. package/dist/esm/components/tree-select.js +60 -11
  60. package/dist/index.css +1583 -409
  61. package/dist/index.min.css +1 -1
  62. package/package.json +1 -1
@@ -22,7 +22,7 @@ export const css = `/**
22
22
  text-align: center;
23
23
  color: var(--color-on-surface);
24
24
  background-color: var(--color-surface);
25
- border: 2px solid var(--color-outline);
25
+ border: 2px solid currentColor;
26
26
  border-radius: 0.5rem;
27
27
  outline: none;
28
28
  transition: border-color 150ms ease-in-out, box-shadow 150ms ease-in-out;
@@ -36,12 +36,11 @@ export const css = `/**
36
36
  }
37
37
 
38
38
  .pin-input-field:hover:not(:disabled):not(:focus) {
39
- border-color: var(--color-on-surface-variant);
39
+ background-color: var(--color-surface-container);
40
40
  }
41
41
 
42
42
  .pin-input-field:focus {
43
- border-color: var(--color-primary);
44
- box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 10%, transparent);
43
+ box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
45
44
  }
46
45
 
47
46
  .pin-input-field:disabled {
@@ -112,29 +111,60 @@ export const css = `/**
112
111
  }
113
112
 
114
113
  /* Color Variants */
114
+ .pin-input-primary .pin-input-field {
115
+ color: var(--color-primary);
116
+ }
117
+
115
118
  .pin-input-primary .pin-input-field:focus {
116
- border-color: var(--color-primary);
117
119
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 10%, transparent);
118
120
  }
119
121
 
122
+ .pin-input-secondary .pin-input-field {
123
+ color: var(--color-secondary);
124
+ }
125
+
120
126
  .pin-input-secondary .pin-input-field:focus {
121
- border-color: var(--color-secondary);
122
127
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-secondary) 10%, transparent);
123
128
  }
124
129
 
130
+ .pin-input-tertiary .pin-input-field {
131
+ color: var(--color-tertiary);
132
+ }
133
+
125
134
  .pin-input-tertiary .pin-input-field:focus {
126
- border-color: var(--color-tertiary);
127
135
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-tertiary) 10%, transparent);
128
136
  }
129
137
 
130
- /* Error State */
138
+ .pin-input-info .pin-input-field {
139
+ color: var(--color-info);
140
+ }
141
+
142
+ .pin-input-info .pin-input-field:focus {
143
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-info) 10%, transparent);
144
+ }
145
+
146
+ .pin-input-success .pin-input-field {
147
+ color: var(--color-success);
148
+ }
149
+
150
+ .pin-input-success .pin-input-field:focus {
151
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-success) 10%, transparent);
152
+ }
153
+
154
+ .pin-input-warning .pin-input-field {
155
+ color: var(--color-warning);
156
+ }
157
+
158
+ .pin-input-warning .pin-input-field:focus {
159
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-warning) 10%, transparent);
160
+ }
161
+
131
162
  .pin-input-error .pin-input-field {
132
- border-color: var(--color-error);
163
+ color: var(--color-error);
133
164
  animation: pin-shake 300ms ease-in-out;
134
165
  }
135
166
 
136
167
  .pin-input-error .pin-input-field:focus {
137
- border-color: var(--color-error);
138
168
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-error) 10%, transparent);
139
169
  }
140
170
 
@@ -144,9 +174,16 @@ export const css = `/**
144
174
  40%, 80% { transform: translateX(4px); }
145
175
  }
146
176
 
147
- /* Success State */
148
- .pin-input-success .pin-input-field {
149
- border-color: var(--color-success);
177
+ /* Ghost Variant */
178
+ .pin-input-ghost .pin-input-field {
179
+ background-color: transparent;
180
+ border-color: transparent;
181
+ }
182
+
183
+ .pin-input-ghost .pin-input-field:focus {
184
+ background-color: var(--color-surface-container);
185
+ border-color: transparent;
186
+ box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
150
187
  }
151
188
 
152
189
  /* PIN Group with Label */
@@ -13,6 +13,7 @@ export const css = `/**
13
13
  --radio-size: 1.25rem;
14
14
  --radio-color: var(--color-primary);
15
15
  --radio-border-color: var(--color-on-surface-variant);
16
+ color: var(--color-on-surface);
16
17
 
17
18
  position: relative;
18
19
  display: inline-grid;
@@ -63,8 +64,8 @@ export const css = `/**
63
64
 
64
65
  /* Focus State */
65
66
  .radio:focus-visible {
66
- outline: 2px solid var(--radio-color);
67
- outline-offset: 2px;
67
+ outline: none;
68
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--radio-color) 20%, transparent);
68
69
  }
69
70
 
70
71
  /* Disabled State */
@@ -129,6 +130,15 @@ export const css = `/**
129
130
  --radio-color: var(--color-info);
130
131
  }
131
132
 
133
+ /* Ghost Variant — borderless unchecked state */
134
+ .radio-ghost {
135
+ --radio-border-color: transparent;
136
+ }
137
+
138
+ .radio-ghost:hover:not(:disabled):not(:checked) {
139
+ border-color: transparent;
140
+ }
141
+
132
142
  /* ========================================
133
143
  * Radio with Label (wrapper pattern)
134
144
  * ======================================== */
@@ -10,6 +10,7 @@ export const css = `/**
10
10
  display: inline-flex;
11
11
  align-items: center;
12
12
  gap: 0.125rem;
13
+ color: var(--color-on-surface);
13
14
  }
14
15
 
15
16
  /* Rating Item */
@@ -113,6 +114,21 @@ export const css = `/**
113
114
  color: var(--color-success);
114
115
  }
115
116
 
117
+ .rating-tertiary .rating-item.filled {
118
+ color: var(--color-tertiary);
119
+ }
120
+
121
+ .rating-info .rating-item.filled {
122
+ color: var(--color-info);
123
+ }
124
+
125
+ /* Note: .rating-warning is explicit even though the default rating filled color is
126
+ already --color-warning. This allows resetting to warning after applying another
127
+ color variant (e.g. class="rating rating-primary rating-warning"). */
128
+ .rating-warning .rating-item.filled {
129
+ color: var(--color-warning);
130
+ }
131
+
116
132
  /* Read Only */
117
133
  .rating-readonly .rating-item {
118
134
  cursor: default;
@@ -156,13 +172,29 @@ export const css = `/**
156
172
  color: var(--color-warning);
157
173
  }
158
174
 
159
- /* Focus Visible */
175
+ .rating-primary:not(.rating-readonly):hover .rating-item { color: var(--color-primary); }
176
+ .rating-secondary:not(.rating-readonly):hover .rating-item { color: var(--color-secondary); }
177
+ .rating-tertiary:not(.rating-readonly):hover .rating-item { color: var(--color-tertiary); }
178
+ .rating-info:not(.rating-readonly):hover .rating-item { color: var(--color-info); }
179
+ .rating-success:not(.rating-readonly):hover .rating-item { color: var(--color-success); }
180
+ .rating-error:not(.rating-readonly):hover .rating-item { color: var(--color-error); }
181
+
182
+ /* Focus Visible — use warning (the default fill color) for the base ring;
183
+ per-variant overrides below match the active fill color for each variant. */
160
184
  .rating-item:focus-visible {
161
- outline: 2px solid var(--color-primary);
162
- outline-offset: 2px;
185
+ outline: none;
186
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-warning) 20%, transparent);
163
187
  border-radius: 0.25rem;
164
188
  }
165
189
 
190
+ .rating-primary .rating-item:focus-visible { box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 20%, transparent); }
191
+ .rating-secondary .rating-item:focus-visible { box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-secondary) 20%, transparent); }
192
+ .rating-tertiary .rating-item:focus-visible { box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-tertiary) 20%, transparent); }
193
+ .rating-info .rating-item:focus-visible { box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-info) 20%, transparent); }
194
+ .rating-success .rating-item:focus-visible { box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-success) 20%, transparent); }
195
+ .rating-error .rating-item:focus-visible { box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-error) 20%, transparent); }
196
+ .rating-warning .rating-item:focus-visible { box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-warning) 20%, transparent); }
197
+
166
198
  /* Rating Display (static) */
167
199
  .rating-display {
168
200
  display: inline-flex;
@@ -9,6 +9,7 @@ export const css = `/**
9
9
  .segment-control {
10
10
  display: inline-flex;
11
11
  align-items: stretch;
12
+ color: var(--color-on-surface);
12
13
  background-color: var(--color-surface-container);
13
14
  border: 1px solid var(--color-outline);
14
15
  border-radius: 1.25rem;
@@ -42,8 +43,8 @@ export const css = `/**
42
43
  }
43
44
 
44
45
  .segment-item:focus-visible {
45
- outline: 2px solid var(--color-primary);
46
- outline-offset: 2px;
46
+ outline: none;
47
+ box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
47
48
  }
48
49
 
49
50
  .segment-item:disabled {
@@ -113,6 +114,26 @@ export const css = `/**
113
114
  color: var(--color-on-tertiary-container);
114
115
  }
115
116
 
117
+ .segment-control-info .segment-item-active {
118
+ background-color: var(--color-info-container);
119
+ color: var(--color-on-info-container);
120
+ }
121
+
122
+ .segment-control-success .segment-item-active {
123
+ background-color: var(--color-success-container);
124
+ color: var(--color-on-success-container);
125
+ }
126
+
127
+ .segment-control-warning .segment-item-active {
128
+ background-color: var(--color-warning-container);
129
+ color: var(--color-on-warning-container);
130
+ }
131
+
132
+ .segment-control-error .segment-item-active {
133
+ background-color: var(--color-error-container);
134
+ color: var(--color-on-error-container);
135
+ }
136
+
116
137
  /* Full Width */
117
138
  .segment-control-full {
118
139
  display: flex;
@@ -14,7 +14,7 @@ export const css = `/**
14
14
  line-height: 1.5rem;
15
15
  color: var(--color-on-surface);
16
16
  background-color: var(--color-surface);
17
- border: 1px solid var(--color-outline);
17
+ border: 1px solid currentColor;
18
18
  border-radius: 0.5rem;
19
19
  outline: none;
20
20
  cursor: pointer;
@@ -27,7 +27,7 @@ export const css = `/**
27
27
  }
28
28
 
29
29
  .select:hover:not(:disabled) {
30
- border-color: var(--color-on-surface-variant);
30
+ background-color: var(--color-surface-container);
31
31
  }
32
32
 
33
33
  .select:focus {
@@ -35,8 +35,7 @@ export const css = `/**
35
35
  }
36
36
 
37
37
  .select:focus-visible {
38
- border-color: var(--color-primary);
39
- box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 10%, transparent);
38
+ box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
40
39
  }
41
40
 
42
41
  .select:disabled {
@@ -63,6 +62,14 @@ export const css = `/**
63
62
  box-shadow: none;
64
63
  }
65
64
 
65
+ .select-filled.select-primary:focus-visible { border-bottom-color: var(--color-primary); }
66
+ .select-filled.select-secondary:focus-visible { border-bottom-color: var(--color-secondary); }
67
+ .select-filled.select-tertiary:focus-visible { border-bottom-color: var(--color-tertiary); }
68
+ .select-filled.select-info:focus-visible { border-bottom-color: var(--color-info); }
69
+ .select-filled.select-success:focus-visible { border-bottom-color: var(--color-success); }
70
+ .select-filled.select-warning:focus-visible { border-bottom-color: var(--color-warning); }
71
+ .select-filled.select-error:focus-visible { border-bottom-color: var(--color-error); }
72
+
66
73
  /* Outlined Variant (default is outlined) */
67
74
  .select-outlined {
68
75
  background-color: transparent;
@@ -70,40 +77,17 @@ export const css = `/**
70
77
  border-radius: 0.5rem;
71
78
  }
72
79
 
73
- /* Color Variants */
74
- .select-primary:focus-visible {
75
- border-color: var(--color-primary);
76
- box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 10%, transparent);
77
- }
78
-
79
- .select-secondary:focus-visible {
80
- border-color: var(--color-secondary);
81
- box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-secondary) 10%, transparent);
82
- }
83
-
84
- .select-tertiary:focus-visible {
85
- border-color: var(--color-tertiary);
86
- box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-tertiary) 10%, transparent);
87
- }
80
+ /* Color Variants — base .select:focus-visible uses currentColor 20%, so no per-variant
81
+ focus-visible overrides needed; setting color: here is sufficient. */
82
+ .select-primary { color: var(--color-primary); }
83
+ .select-secondary { color: var(--color-secondary); }
84
+ .select-tertiary { color: var(--color-tertiary); }
88
85
 
89
86
  /* Semantic Colors */
90
- .select-error {
91
- border-color: var(--color-error);
92
- }
93
-
94
- .select-error:focus-visible {
95
- border-color: var(--color-error);
96
- box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-error) 10%, transparent);
97
- }
98
-
99
- .select-success {
100
- border-color: var(--color-success);
101
- }
102
-
103
- .select-success:focus-visible {
104
- border-color: var(--color-success);
105
- box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-success) 10%, transparent);
106
- }
87
+ .select-info { color: var(--color-info); }
88
+ .select-success { color: var(--color-success); }
89
+ .select-warning { color: var(--color-warning); }
90
+ .select-error { color: var(--color-error); }
107
91
 
108
92
  /* Size Variants */
109
93
  .select-xs {
@@ -194,7 +178,7 @@ export const css = `/**
194
178
  .select-ghost:focus-visible {
195
179
  background-color: var(--color-surface-container);
196
180
  border-color: transparent;
197
- box-shadow: none;
181
+ box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
198
182
  }
199
183
 
200
184
  /* Reduce Motion */
@@ -14,6 +14,7 @@ export const css = `/**
14
14
  height: 2.5rem;
15
15
  touch-action: none;
16
16
  user-select: none;
17
+ color: var(--color-on-surface);
17
18
  }
18
19
 
19
20
  /* Slider Track */
@@ -74,7 +75,7 @@ export const css = `/**
74
75
  margin-bottom: 0.5rem;
75
76
  font-size: 0.75rem;
76
77
  font-weight: 500;
77
- color: var(--color-on-primary);
78
+ color: var(--color-primary-content);
78
79
  background-color: var(--color-primary);
79
80
  border-radius: 0.25rem;
80
81
  white-space: nowrap;
@@ -128,7 +129,7 @@ export const css = `/**
128
129
  }
129
130
 
130
131
  .slider-mark-active {
131
- background-color: var(--color-on-primary);
132
+ background-color: var(--color-primary-content);
132
133
  }
133
134
 
134
135
  /* Mark Label */
@@ -179,6 +180,27 @@ export const css = `/**
179
180
  }
180
181
 
181
182
  /* Color Variants */
183
+ .slider-primary .slider-track-filled,
184
+ .slider-primary .slider-thumb {
185
+ background-color: var(--color-primary);
186
+ }
187
+
188
+ .slider-primary .slider-mark-active { background-color: var(--color-primary-content); }
189
+
190
+ .slider-primary .slider-thumb:hover,
191
+ .slider-primary .slider-thumb:focus-visible {
192
+ box-shadow: 0 0 0 8px var(--color-primary-container), 0 2px 4px rgb(0 0 0 / 0.2);
193
+ }
194
+
195
+ .slider-primary .slider-thumb-label {
196
+ background-color: var(--color-primary);
197
+ color: var(--color-primary-content);
198
+ }
199
+
200
+ .slider-primary .slider-thumb-label::after {
201
+ border-top-color: var(--color-primary);
202
+ }
203
+
182
204
  .slider-secondary .slider-track-filled,
183
205
  .slider-secondary .slider-thumb {
184
206
  background-color: var(--color-secondary);
@@ -189,9 +211,11 @@ export const css = `/**
189
211
  box-shadow: 0 0 0 8px var(--color-secondary-container), 0 2px 4px rgb(0 0 0 / 0.2);
190
212
  }
191
213
 
214
+ .slider-secondary .slider-mark-active { background-color: var(--color-secondary-content); }
215
+
192
216
  .slider-secondary .slider-thumb-label {
193
217
  background-color: var(--color-secondary);
194
- color: var(--color-on-secondary);
218
+ color: var(--color-secondary-content);
195
219
  }
196
220
 
197
221
  .slider-secondary .slider-thumb-label::after {
@@ -208,15 +232,105 @@ export const css = `/**
208
232
  box-shadow: 0 0 0 8px var(--color-tertiary-container), 0 2px 4px rgb(0 0 0 / 0.2);
209
233
  }
210
234
 
235
+ .slider-tertiary .slider-mark-active { background-color: var(--color-tertiary-content); }
236
+
211
237
  .slider-tertiary .slider-thumb-label {
212
238
  background-color: var(--color-tertiary);
213
- color: var(--color-on-tertiary);
239
+ color: var(--color-tertiary-content);
214
240
  }
215
241
 
216
242
  .slider-tertiary .slider-thumb-label::after {
217
243
  border-top-color: var(--color-tertiary);
218
244
  }
219
245
 
246
+ /* Info */
247
+ .slider-info .slider-track-filled,
248
+ .slider-info .slider-thumb {
249
+ background-color: var(--color-info);
250
+ }
251
+
252
+ .slider-info .slider-thumb:hover,
253
+ .slider-info .slider-thumb:focus-visible {
254
+ box-shadow: 0 0 0 8px var(--color-info-container), 0 2px 4px rgb(0 0 0 / 0.2);
255
+ }
256
+
257
+ .slider-info .slider-mark-active { background-color: var(--color-info-content); }
258
+
259
+ .slider-info .slider-thumb-label {
260
+ background-color: var(--color-info);
261
+ color: var(--color-info-content);
262
+ }
263
+
264
+ .slider-info .slider-thumb-label::after {
265
+ border-top-color: var(--color-info);
266
+ }
267
+
268
+ /* Success */
269
+ .slider-success .slider-track-filled,
270
+ .slider-success .slider-thumb {
271
+ background-color: var(--color-success);
272
+ }
273
+
274
+ .slider-success .slider-thumb:hover,
275
+ .slider-success .slider-thumb:focus-visible {
276
+ box-shadow: 0 0 0 8px var(--color-success-container), 0 2px 4px rgb(0 0 0 / 0.2);
277
+ }
278
+
279
+ .slider-success .slider-mark-active { background-color: var(--color-success-content); }
280
+
281
+ .slider-success .slider-thumb-label {
282
+ background-color: var(--color-success);
283
+ color: var(--color-success-content);
284
+ }
285
+
286
+ .slider-success .slider-thumb-label::after {
287
+ border-top-color: var(--color-success);
288
+ }
289
+
290
+ /* Warning */
291
+ .slider-warning .slider-track-filled,
292
+ .slider-warning .slider-thumb {
293
+ background-color: var(--color-warning);
294
+ }
295
+
296
+ .slider-warning .slider-thumb:hover,
297
+ .slider-warning .slider-thumb:focus-visible {
298
+ box-shadow: 0 0 0 8px var(--color-warning-container), 0 2px 4px rgb(0 0 0 / 0.2);
299
+ }
300
+
301
+ .slider-warning .slider-mark-active { background-color: var(--color-warning-content); }
302
+
303
+ .slider-warning .slider-thumb-label {
304
+ background-color: var(--color-warning);
305
+ color: var(--color-warning-content);
306
+ }
307
+
308
+ .slider-warning .slider-thumb-label::after {
309
+ border-top-color: var(--color-warning);
310
+ }
311
+
312
+ /* Error */
313
+ .slider-error .slider-track-filled,
314
+ .slider-error .slider-thumb {
315
+ background-color: var(--color-error);
316
+ }
317
+
318
+ .slider-error .slider-thumb:hover,
319
+ .slider-error .slider-thumb:focus-visible {
320
+ box-shadow: 0 0 0 8px var(--color-error-container), 0 2px 4px rgb(0 0 0 / 0.2);
321
+ }
322
+
323
+ .slider-error .slider-mark-active { background-color: var(--color-error-content); }
324
+
325
+ .slider-error .slider-thumb-label {
326
+ background-color: var(--color-error);
327
+ color: var(--color-error-content);
328
+ }
329
+
330
+ .slider-error .slider-thumb-label::after {
331
+ border-top-color: var(--color-error);
332
+ }
333
+
220
334
  /* Disabled State */
221
335
  .slider-disabled {
222
336
  opacity: 0.6;
@@ -273,9 +387,18 @@ export const css = `/**
273
387
  right: 100%;
274
388
  transform: translateY(-50%);
275
389
  border-top-color: transparent;
276
- border-right-color: var(--color-primary);
390
+ border-right-color: var(--color-primary); /* overridden per-variant below */
277
391
  }
278
392
 
393
+ /* Variant-specific vertical arrow colors (border-right-color cannot use currentColor
394
+ since it must match the label background, not the text color) */
395
+ .slider-secondary.slider-vertical .slider-thumb-label::after { border-right-color: var(--color-secondary); }
396
+ .slider-tertiary.slider-vertical .slider-thumb-label::after { border-right-color: var(--color-tertiary); }
397
+ .slider-info.slider-vertical .slider-thumb-label::after { border-right-color: var(--color-info); }
398
+ .slider-success.slider-vertical .slider-thumb-label::after { border-right-color: var(--color-success); }
399
+ .slider-warning.slider-vertical .slider-thumb-label::after { border-right-color: var(--color-warning); }
400
+ .slider-error.slider-vertical .slider-thumb-label::after { border-right-color: var(--color-error); }
401
+
279
402
  .slider-vertical .slider-marks {
280
403
  flex-direction: column;
281
404
  top: 0;
@@ -315,7 +438,8 @@ export const css = `/**
315
438
 
316
439
  .slider-input:focus {
317
440
  outline: none;
318
- border-color: var(--color-primary);
441
+ border-color: currentColor;
442
+ box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
319
443
  }
320
444
 
321
445
  /* Reduce Motion */
@@ -12,8 +12,11 @@ export const css = `/**
12
12
  .switch {
13
13
  --switch-width: 3.25rem;
14
14
  --switch-height: 2rem;
15
+ color: var(--color-on-surface);
15
16
  --switch-thumb-size: 1rem;
16
17
  --switch-color: var(--color-primary);
18
+ --switch-content-color: var(--color-primary-content);
19
+ --switch-container-color: var(--color-primary-container);
17
20
  --switch-track-color: var(--color-surface-container-highest);
18
21
  --switch-border-color: var(--color-outline);
19
22
  --switch-thumb-color: var(--color-outline);
@@ -59,7 +62,7 @@ export const css = `/**
59
62
  }
60
63
 
61
64
  .switch:checked::before {
62
- background-color: var(--color-primary-content);
65
+ background-color: var(--switch-content-color);
63
66
  }
64
67
 
65
68
  /* Hover State (unchecked) */
@@ -78,13 +81,13 @@ export const css = `/**
78
81
  }
79
82
 
80
83
  .switch:checked:hover:not(:disabled)::before {
81
- background-color: var(--color-primary-container);
84
+ background-color: var(--switch-container-color);
82
85
  }
83
86
 
84
87
  /* Focus State */
85
88
  .switch:focus-visible {
86
- outline: 2px solid var(--switch-color);
87
- outline-offset: 2px;
89
+ outline: none;
90
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--switch-color) 20%, transparent);
88
91
  }
89
92
 
90
93
  /* Pressed/Active State - expand thumb slightly */
@@ -161,30 +164,50 @@ export const css = `/**
161
164
 
162
165
  .switch-primary {
163
166
  --switch-color: var(--color-primary);
167
+ --switch-content-color: var(--color-primary-content);
168
+ --switch-container-color: var(--color-primary-container);
164
169
  }
165
170
 
166
171
  .switch-secondary {
167
172
  --switch-color: var(--color-secondary);
173
+ --switch-content-color: var(--color-secondary-content);
174
+ --switch-container-color: var(--color-secondary-container);
168
175
  }
169
176
 
170
177
  .switch-tertiary {
171
178
  --switch-color: var(--color-tertiary);
179
+ --switch-content-color: var(--color-tertiary-content);
180
+ --switch-container-color: var(--color-tertiary-container);
172
181
  }
173
182
 
174
183
  .switch-success {
175
184
  --switch-color: var(--color-success);
185
+ --switch-content-color: var(--color-success-content);
186
+ --switch-container-color: var(--color-success-container);
176
187
  }
177
188
 
178
189
  .switch-warning {
179
190
  --switch-color: var(--color-warning);
191
+ --switch-content-color: var(--color-warning-content);
192
+ --switch-container-color: var(--color-warning-container);
180
193
  }
181
194
 
182
195
  .switch-error {
183
196
  --switch-color: var(--color-error);
197
+ --switch-content-color: var(--color-error-content);
198
+ --switch-container-color: var(--color-error-container);
184
199
  }
185
200
 
186
201
  .switch-info {
187
202
  --switch-color: var(--color-info);
203
+ --switch-content-color: var(--color-info-content);
204
+ --switch-container-color: var(--color-info-container);
205
+ }
206
+
207
+ /* Ghost Variant — borderless track */
208
+ .switch-ghost {
209
+ --switch-border-color: transparent;
210
+ --switch-track-color: transparent;
188
211
  }
189
212
 
190
213
  /* ========================================