@zentauri-ui/zentauri-components 1.8.41 → 1.9.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 (80) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +21 -0
  3. package/README.md +77 -64
  4. package/dist/{chunk-RFT2FLQT.js → chunk-5IJC2OEN.js} +10 -12
  5. package/dist/chunk-5IJC2OEN.js.map +1 -0
  6. package/dist/{chunk-CJXGDY7A.mjs → chunk-DY7HLVGW.mjs} +10 -12
  7. package/dist/chunk-DY7HLVGW.mjs.map +1 -0
  8. package/dist/chunk-KVQI5PLL.mjs +399 -0
  9. package/dist/chunk-KVQI5PLL.mjs.map +1 -0
  10. package/dist/chunk-NRPG2STN.js +401 -0
  11. package/dist/chunk-NRPG2STN.js.map +1 -0
  12. package/dist/{chunk-V5JTDRV5.mjs → chunk-TKVZU56F.mjs} +11 -11
  13. package/dist/chunk-TKVZU56F.mjs.map +1 -0
  14. package/dist/{chunk-Z4KHAD6Y.js → chunk-U3VV22G4.js} +11 -11
  15. package/dist/chunk-U3VV22G4.js.map +1 -0
  16. package/dist/design-system/dynamic-stepper.d.ts +0 -1
  17. package/dist/design-system/dynamic-stepper.d.ts.map +1 -1
  18. package/dist/design-system/inputs.d.ts +65 -0
  19. package/dist/design-system/inputs.d.ts.map +1 -1
  20. package/dist/design-system/kbd.d.ts +1 -0
  21. package/dist/design-system/kbd.d.ts.map +1 -1
  22. package/dist/design-system/marquee.d.ts +9 -9
  23. package/dist/design-system/timeline.d.ts +9 -9
  24. package/dist/test-utils/axe.d.ts +30 -0
  25. package/dist/test-utils/axe.d.ts.map +1 -0
  26. package/dist/ui/dynamic-stepper/variants.d.ts +2 -2
  27. package/dist/ui/dynamic-stepper/variants.d.ts.map +1 -1
  28. package/dist/ui/dynamic-stepper.js +3 -4
  29. package/dist/ui/dynamic-stepper.js.map +1 -1
  30. package/dist/ui/dynamic-stepper.mjs +3 -4
  31. package/dist/ui/dynamic-stepper.mjs.map +1 -1
  32. package/dist/ui/inputs/animated.js +3 -3
  33. package/dist/ui/inputs/animated.mjs +1 -1
  34. package/dist/ui/inputs/variants.d.ts.map +1 -1
  35. package/dist/ui/inputs.js +4 -4
  36. package/dist/ui/inputs.mjs +2 -2
  37. package/dist/ui/kbd/animated.js +2 -2
  38. package/dist/ui/kbd/animated.mjs +1 -1
  39. package/dist/ui/kbd/variants.d.ts.map +1 -1
  40. package/dist/ui/kbd.js +4 -4
  41. package/dist/ui/kbd.mjs +2 -2
  42. package/dist/ui/marquee.js +9 -9
  43. package/dist/ui/marquee.js.map +1 -1
  44. package/dist/ui/marquee.mjs +9 -9
  45. package/dist/ui/marquee.mjs.map +1 -1
  46. package/dist/ui/search.js +2 -2
  47. package/dist/ui/search.mjs +1 -1
  48. package/dist/ui/select/select.d.ts +2 -2
  49. package/dist/ui/select/select.d.ts.map +1 -1
  50. package/dist/ui/select/types.d.ts +2 -0
  51. package/dist/ui/select/types.d.ts.map +1 -1
  52. package/dist/ui/select.js +26 -4
  53. package/dist/ui/select.js.map +1 -1
  54. package/dist/ui/select.mjs +27 -5
  55. package/dist/ui/select.mjs.map +1 -1
  56. package/dist/ui/timeline/animated.js +11 -11
  57. package/dist/ui/timeline/animated.mjs +2 -2
  58. package/dist/ui/timeline.js +14 -14
  59. package/dist/ui/timeline.mjs +2 -2
  60. package/package.json +47 -16
  61. package/src/design-system/dynamic-stepper.ts +0 -7
  62. package/src/design-system/inputs.ts +102 -0
  63. package/src/design-system/kbd.ts +3 -0
  64. package/src/design-system/marquee.ts +9 -9
  65. package/src/design-system/timeline.ts +9 -9
  66. package/src/ui/accessibility/axe-core.test.tsx +139 -0
  67. package/src/ui/dynamic-stepper/variants.ts +7 -3
  68. package/src/ui/inputs/variants.ts +57 -90
  69. package/src/ui/kbd/variants.ts +8 -10
  70. package/src/ui/select/select.test.tsx +24 -0
  71. package/src/ui/select/select.tsx +37 -4
  72. package/src/ui/select/types.ts +2 -0
  73. package/dist/chunk-CJXGDY7A.mjs.map +0 -1
  74. package/dist/chunk-D3VZKUMH.mjs +0 -340
  75. package/dist/chunk-D3VZKUMH.mjs.map +0 -1
  76. package/dist/chunk-RFT2FLQT.js.map +0 -1
  77. package/dist/chunk-UGH23TAH.js +0 -342
  78. package/dist/chunk-UGH23TAH.js.map +0 -1
  79. package/dist/chunk-V5JTDRV5.mjs.map +0 -1
  80. package/dist/chunk-Z4KHAD6Y.js.map +0 -1
@@ -4,8 +4,16 @@ import {
4
4
  zuiInputAppearances,
5
5
  zuiInputAs,
6
6
  zuiInputBase,
7
+ zuiInputCheckboxAppearances,
8
+ zuiInputCheckboxSizes,
9
+ zuiInputDateAppearances,
10
+ zuiInputFileAppearances,
11
+ zuiInputFileSizes,
12
+ zuiInputRadioAppearances,
13
+ zuiInputRadioSizes,
7
14
  zuiInputRing,
8
15
  zuiInputSizes,
16
+ zuiInputTextareaSizes,
9
17
  } from "../../design-system/inputs";
10
18
 
11
19
  export const inputVariants = cva(zuiInputBase, {
@@ -22,291 +30,250 @@ export const inputVariants = cva(zuiInputBase, {
22
30
  ring: true,
23
31
  },
24
32
  compoundVariants: [
25
- // ── textarea size overrides ──────────────────────────────────────────
26
33
  {
27
34
  as: "textarea",
28
35
  size: "sm",
29
- class: "min-h-[5rem]",
36
+ class: zuiInputTextareaSizes.sm,
30
37
  },
31
38
  {
32
39
  as: "textarea",
33
40
  size: "md",
34
- class: "min-h-[6rem]",
41
+ class: zuiInputTextareaSizes.md,
35
42
  },
36
43
  {
37
44
  as: "textarea",
38
45
  size: "lg",
39
- class: "min-h-[7.5rem]",
46
+ class: zuiInputTextareaSizes.lg,
40
47
  },
41
- // ── file input: size – height & file-button padding ──────────────────
42
48
  {
43
49
  as: "file",
44
50
  size: "sm",
45
- class: "h-8 text-xs pl-1 file:h-8 file:px-3 file:text-xs",
51
+ class: zuiInputFileSizes.sm,
46
52
  },
47
53
  {
48
54
  as: "file",
49
55
  size: "md",
50
- class:
51
- "h-9 md:h-11 text-sm pl-1 file:h-9 md:file:h-11 file:px-4 file:text-sm",
56
+ class: zuiInputFileSizes.md,
52
57
  },
53
58
  {
54
59
  as: "file",
55
60
  size: "lg",
56
- class:
57
- "h-10 md:h-12 text-base pl-1 file:h-10 md:file:h-12 file:px-5 file:text-base",
61
+ class: zuiInputFileSizes.lg,
58
62
  },
59
- // ── file input: appearance – file-button accent colour ───────────────
60
63
  {
61
64
  as: "file",
62
65
  appearance: "default",
63
- class: "file:text-slate-700 dark:file:text-slate-200",
66
+ class: zuiInputFileAppearances.default,
64
67
  },
65
68
  {
66
69
  as: "file",
67
70
  appearance: "warning",
68
- class:
69
- "file:bg-yellow-500/20 file:text-yellow-800 dark:file:text-yellow-200 file:border-yellow-500/40 hover:file:bg-yellow-500/30",
71
+ class: zuiInputFileAppearances.warning,
70
72
  },
71
73
  {
72
74
  as: "file",
73
75
  appearance: "error",
74
- class:
75
- "file:bg-rose-500/20 file:text-rose-800 dark:file:text-rose-200 file:border-rose-500/40 hover:file:bg-rose-500/30",
76
+ class: zuiInputFileAppearances.error,
76
77
  },
77
78
  {
78
79
  as: "file",
79
80
  appearance: "success",
80
- class:
81
- "file:bg-emerald-500/20 file:text-emerald-800 dark:file:text-emerald-200 file:border-emerald-500/40 hover:file:bg-emerald-500/30",
81
+ class: zuiInputFileAppearances.success,
82
82
  },
83
83
  {
84
84
  as: "file",
85
85
  appearance: "info",
86
- class:
87
- "file:bg-blue-500/20 file:text-blue-800 dark:file:text-blue-200 file:border-blue-500/40 hover:file:bg-blue-500/30",
86
+ class: zuiInputFileAppearances.info,
88
87
  },
89
88
  {
90
89
  as: "file",
91
90
  appearance: "violet",
92
- class:
93
- "file:bg-violet-500/20 file:text-violet-800 dark:file:text-violet-200 file:border-violet-500/40 hover:file:bg-violet-500/30",
91
+ class: zuiInputFileAppearances.violet,
94
92
  },
95
93
  {
96
94
  as: "file",
97
95
  appearance: "amber",
98
- class:
99
- "file:bg-amber-500/20 file:text-amber-800 dark:file:text-amber-200 file:border-amber-500/40 hover:file:bg-amber-500/30",
96
+ class: zuiInputFileAppearances.amber,
100
97
  },
101
98
  {
102
99
  as: "file",
103
100
  appearance: "pink",
104
- class:
105
- "file:bg-pink-500/20 file:text-pink-800 dark:file:text-pink-200 file:border-pink-500/40 hover:file:bg-pink-500/30",
101
+ class: zuiInputFileAppearances.pink,
106
102
  },
107
103
  {
108
104
  as: "file",
109
105
  appearance: "indigo",
110
- class:
111
- "file:bg-indigo-500/20 file:text-indigo-800 dark:file:text-indigo-200 file:border-indigo-500/40 hover:file:bg-indigo-500/30",
106
+ class: zuiInputFileAppearances.indigo,
112
107
  },
113
- // ── checkbox / radio: size (overrides text-field height & padding) ───
114
108
  {
115
109
  as: "checkbox",
116
110
  size: "sm",
117
- class: "h-4! w-4! min-h-0! rounded-[0.35rem]! px-0! py-0!",
111
+ class: zuiInputCheckboxSizes.sm,
118
112
  },
119
113
  {
120
114
  as: "checkbox",
121
115
  size: "md",
122
- class: "h-5! w-5! min-h-0! rounded-md! px-0! py-0!",
116
+ class: zuiInputCheckboxSizes.md,
123
117
  },
124
118
  {
125
119
  as: "checkbox",
126
120
  size: "lg",
127
- class: "h-6! w-6! min-h-0! rounded-md! px-0! py-0!",
121
+ class: zuiInputCheckboxSizes.lg,
128
122
  },
129
123
  {
130
124
  as: "radio",
131
125
  size: "sm",
132
- class: "h-4! w-4! min-h-0! px-0! py-0!",
126
+ class: zuiInputRadioSizes.sm,
133
127
  },
134
128
  {
135
129
  as: "radio",
136
130
  size: "md",
137
- class: "h-5! w-5! min-h-0! px-0! py-0!",
131
+ class: zuiInputRadioSizes.md,
138
132
  },
139
133
  {
140
134
  as: "radio",
141
135
  size: "lg",
142
- class: "h-6! w-6! min-h-0! px-0! py-0!",
136
+ class: zuiInputRadioSizes.lg,
143
137
  },
144
- // ── checkbox: appearance (border + tick color; fill stays transparent) ─
145
138
  {
146
139
  as: "checkbox",
147
140
  appearance: "default",
148
- class:
149
- "border-slate-400/70! checked:border-slate-700 dark:checked:border-slate-200 checked:text-slate-700 dark:checked:text-slate-200 hover:border-slate-600 dark:hover:border-slate-300 focus-visible:border-slate-600 dark:focus-visible:border-slate-300 focus-visible:ring-slate-500/70 dark:focus-visible:ring-slate-400/70",
141
+ class: zuiInputCheckboxAppearances.default,
150
142
  },
151
143
  {
152
144
  as: "checkbox",
153
145
  appearance: "warning",
154
- class:
155
- "border-yellow-500/70! checked:border-yellow-600 dark:checked:border-yellow-400 checked:text-yellow-700 dark:checked:text-yellow-300 hover:border-yellow-600 dark:hover:border-yellow-400 focus-visible:border-yellow-600 dark:focus-visible:border-yellow-400 focus-visible:ring-yellow-400/80",
146
+ class: zuiInputCheckboxAppearances.warning,
156
147
  },
157
148
  {
158
149
  as: "checkbox",
159
150
  appearance: "error",
160
- class:
161
- "border-rose-500/70! checked:border-rose-600 dark:checked:border-rose-400 checked:text-rose-700 dark:checked:text-rose-300 hover:border-rose-600 dark:hover:border-rose-400 focus-visible:border-rose-600 dark:focus-visible:border-rose-400 focus-visible:ring-rose-400/80",
151
+ class: zuiInputCheckboxAppearances.error,
162
152
  },
163
153
  {
164
154
  as: "checkbox",
165
155
  appearance: "success",
166
- class:
167
- "border-emerald-500/70! checked:border-emerald-600 dark:checked:border-emerald-400 checked:text-emerald-700 dark:checked:text-emerald-300 hover:border-emerald-600 dark:hover:border-emerald-400 focus-visible:border-emerald-600 dark:focus-visible:border-emerald-400 focus-visible:ring-emerald-400/80",
156
+ class: zuiInputCheckboxAppearances.success,
168
157
  },
169
158
  {
170
159
  as: "checkbox",
171
160
  appearance: "info",
172
- class:
173
- "border-blue-500/70! checked:border-blue-600 dark:checked:border-blue-400 checked:text-blue-700 dark:checked:text-blue-300 hover:border-blue-600 dark:hover:border-blue-400 focus-visible:border-blue-600 dark:focus-visible:border-blue-400 focus-visible:ring-blue-400/80",
161
+ class: zuiInputCheckboxAppearances.info,
174
162
  },
175
163
  {
176
164
  as: "checkbox",
177
165
  appearance: "violet",
178
- class:
179
- "border-violet-500/70! checked:after:bg-violet-600 dark:checked:after:bg-violet-400 checked:border-violet-600 dark:checked:border-violet-400 checked:text-violet-700 dark:checked:text-violet-300 hover:border-violet-600 dark:hover:border-violet-400 focus-visible:border-violet-600 dark:focus-visible:border-violet-400 focus-visible:ring-violet-400/80",
166
+ class: zuiInputCheckboxAppearances.violet,
180
167
  },
181
168
  {
182
169
  as: "checkbox",
183
170
  appearance: "amber",
184
- class:
185
- "border-amber-500/70! checked:border-amber-400! checked:text-amber-700 dark:checked:text-amber-300 hover:border-amber-400! focus-visible:border-amber-400! focus-visible:ring-amber-400/80!",
171
+ class: zuiInputCheckboxAppearances.amber,
186
172
  },
187
173
  {
188
174
  as: "checkbox",
189
175
  appearance: "pink",
190
- class:
191
- "border-pink-500/70! checked:border-pink-600 dark:checked:border-pink-400 checked:text-pink-700 dark:checked:text-pink-300 hover:border-pink-600 dark:hover:border-pink-400 focus-visible:border-pink-600 dark:focus-visible:border-pink-400 focus-visible:ring-pink-400/80",
176
+ class: zuiInputCheckboxAppearances.pink,
192
177
  },
193
178
  {
194
179
  as: "checkbox",
195
180
  appearance: "indigo",
196
- class:
197
- "border-indigo-500/70! checked:border-indigo-400! checked:text-indigo-700 dark:checked:text-indigo-300 hover:border-indigo-400! focus-visible:border-indigo-400! focus-visible:ring-indigo-400/80!",
181
+ class: zuiInputCheckboxAppearances.indigo,
198
182
  },
199
- // ── radio: appearance (transparent fill, inner dot, coloured offset ring) ─
200
183
  {
201
184
  as: "radio",
202
185
  appearance: "default",
203
- class:
204
- "border-slate-400/70! checked:border-slate-700 dark:checked:border-slate-200 checked:bg-transparent! checked:shadow-[inset_0_0_0_0.28rem_rgb(226,232,240)]! hover:border-slate-600 dark:hover:border-slate-300 focus-visible:border-slate-600 dark:focus-visible:border-slate-300 focus-visible:ring-slate-500/70 dark:focus-visible:ring-slate-400/70 checked:ring-2! checked:ring-offset-2! checked:ring-offset-white! dark:checked:ring-offset-slate-950! checked:ring-slate-300/90!",
186
+ class: zuiInputRadioAppearances.default,
205
187
  },
206
188
  {
207
189
  as: "radio",
208
190
  appearance: "warning",
209
- class:
210
- "border-yellow-500/70! checked:border-yellow-600 dark:checked:border-yellow-400 checked:bg-transparent! checked:shadow-[inset_0_0_0_0.28rem_rgb(250,204,21)]! hover:border-yellow-600 dark:hover:border-yellow-400 focus-visible:border-yellow-600 dark:focus-visible:border-yellow-400 focus-visible:ring-yellow-400/80 checked:ring-2! checked:ring-offset-2! checked:ring-offset-white! dark:checked:ring-offset-slate-950! checked:ring-yellow-400/90!",
191
+ class: zuiInputRadioAppearances.warning,
211
192
  },
212
193
  {
213
194
  as: "radio",
214
195
  appearance: "error",
215
- class:
216
- "border-rose-500/70! checked:border-rose-600 dark:checked:border-rose-400 checked:bg-transparent! checked:shadow-[inset_0_0_0_0.28rem_rgb(251,113,133)]! hover:border-rose-600 dark:hover:border-rose-400 focus-visible:border-rose-600 dark:focus-visible:border-rose-400 focus-visible:ring-rose-400/80 checked:ring-2! checked:ring-offset-2! checked:ring-offset-white! dark:checked:ring-offset-slate-950! checked:ring-rose-400/90!",
196
+ class: zuiInputRadioAppearances.error,
217
197
  },
218
198
  {
219
199
  as: "radio",
220
200
  appearance: "success",
221
- class:
222
- "border-emerald-500/70! checked:border-emerald-600 dark:checked:border-emerald-400 checked:bg-transparent! checked:shadow-[inset_0_0_0_0.28rem_rgb(52,211,153)]! hover:border-emerald-600 dark:hover:border-emerald-400 focus-visible:border-emerald-600 dark:focus-visible:border-emerald-400 focus-visible:ring-emerald-400/80 checked:ring-2! checked:ring-offset-2! checked:ring-offset-white! dark:checked:ring-offset-slate-950! checked:ring-emerald-400/90!",
201
+ class: zuiInputRadioAppearances.success,
223
202
  },
224
203
  {
225
204
  as: "radio",
226
205
  appearance: "info",
227
- class:
228
- "border-blue-500/70! checked:border-blue-600 dark:checked:border-blue-400 checked:bg-transparent! checked:shadow-[inset_0_0_0_0.28rem_rgb(96,165,250)]! hover:border-blue-600 dark:hover:border-blue-400 focus-visible:border-blue-600 dark:focus-visible:border-blue-400 focus-visible:ring-blue-400/80 checked:ring-2! checked:ring-offset-2! checked:ring-offset-white! dark:checked:ring-offset-slate-950! checked:ring-blue-400/90!",
206
+ class: zuiInputRadioAppearances.info,
229
207
  },
230
208
  {
231
209
  as: "radio",
232
210
  appearance: "violet",
233
- class:
234
- "border-violet-500/70! checked:border-violet-600 dark:checked:border-violet-400 checked:bg-transparent! checked:shadow-[inset_0_0_0_0.28rem_rgb(167,139,250)]! hover:border-violet-600 dark:hover:border-violet-400 focus-visible:border-violet-600 dark:focus-visible:border-violet-400 focus-visible:ring-violet-400/80 checked:ring-2! checked:ring-offset-2! checked:ring-offset-white! dark:checked:ring-offset-slate-950! checked:ring-violet-400/90!",
211
+ class: zuiInputRadioAppearances.violet,
235
212
  },
236
213
  {
237
214
  as: "radio",
238
215
  appearance: "amber",
239
- class:
240
- "border-amber-500/70! checked:border-amber-600 dark:checked:border-amber-400 checked:bg-transparent! checked:shadow-[inset_0_0_0_0.28rem_rgb(251,191,36)]! hover:border-amber-600 dark:hover:border-amber-400 focus-visible:border-amber-600 dark:focus-visible:border-amber-400 focus-visible:ring-amber-400/80 checked:ring-2! checked:ring-offset-2! checked:ring-offset-white! dark:checked:ring-offset-slate-950! checked:ring-amber-400/90!",
216
+ class: zuiInputRadioAppearances.amber,
241
217
  },
242
218
  {
243
219
  as: "radio",
244
220
  appearance: "pink",
245
- class:
246
- "border-pink-500/70! checked:border-pink-600 dark:checked:border-pink-400 checked:bg-transparent! checked:shadow-[inset_0_0_0_0.28rem_rgb(244,114,182)]! hover:border-pink-600 dark:hover:border-pink-400 focus-visible:border-pink-600 dark:focus-visible:border-pink-400 focus-visible:ring-pink-400/80 checked:ring-2! checked:ring-offset-2! checked:ring-offset-white! dark:checked:ring-offset-slate-950! checked:ring-pink-400/90!",
221
+ class: zuiInputRadioAppearances.pink,
247
222
  },
248
223
  {
249
224
  as: "radio",
250
225
  appearance: "indigo",
251
- class:
252
- "border-indigo-500/70! checked:border-indigo-600 dark:checked:border-indigo-400 checked:bg-transparent! checked:shadow-[inset_0_0_0_0.28rem_rgb(129,140,248)]! hover:border-indigo-600 dark:hover:border-indigo-400 focus-visible:border-indigo-600 dark:focus-visible:border-indigo-400 focus-visible:ring-indigo-400/80 checked:ring-2! checked:ring-offset-2! checked:ring-offset-white! dark:checked:ring-offset-slate-950! checked:ring-indigo-400/90!",
226
+ class: zuiInputRadioAppearances.indigo,
253
227
  },
254
228
  {
255
229
  as: "date",
256
230
  appearance: "default",
257
- class:
258
- "bg-white dark:bg-black border border-black/10 dark:border-white/80 text-black dark:text-white",
231
+ class: zuiInputDateAppearances.default,
259
232
  },
260
233
  {
261
234
  as: "date",
262
235
  appearance: "warning",
263
- class:
264
- "bg-yellow-900 dark:bg-transparent text-yellow-50 dark:text-yellow-50",
236
+ class: zuiInputDateAppearances.warning,
265
237
  },
266
238
  {
267
239
  as: "date",
268
240
  appearance: "error",
269
- class: "bg-rose-900 dark:bg-transparent text-rose-50 dark:text-rose-50",
241
+ class: zuiInputDateAppearances.error,
270
242
  },
271
243
  {
272
244
  as: "date",
273
245
  appearance: "success",
274
- class:
275
- "bg-emerald-900 dark:bg-transparent text-emerald-50 dark:text-emerald-50",
246
+ class: zuiInputDateAppearances.success,
276
247
  },
277
248
  {
278
249
  as: "date",
279
250
  appearance: "info",
280
- class: "bg-blue-900 dark:bg-transparent text-blue-50 dark:text-blue-50",
251
+ class: zuiInputDateAppearances.info,
281
252
  },
282
253
  {
283
254
  as: "date",
284
255
  appearance: "violet",
285
- class:
286
- "bg-violet-900 dark:bg-transparent text-violet-50 dark:text-violet-50",
256
+ class: zuiInputDateAppearances.violet,
287
257
  },
288
258
  {
289
259
  as: "date",
290
260
  appearance: "amber",
291
- class:
292
- "bg-amber-900 dark:bg-transparent text-amber-50 dark:text-amber-50",
261
+ class: zuiInputDateAppearances.amber,
293
262
  },
294
263
  {
295
264
  as: "date",
296
265
  appearance: "pink",
297
- class: "bg-pink-900 dark:bg-transparent text-pink-50 dark:text-pink-50",
266
+ class: zuiInputDateAppearances.pink,
298
267
  },
299
268
  {
300
269
  as: "date",
301
270
  appearance: "indigo",
302
- class:
303
- "bg-indigo-900 dark:bg-transparent text-indigo-50 dark:text-indigo-50",
271
+ class: zuiInputDateAppearances.indigo,
304
272
  },
305
273
  {
306
274
  as: "date",
307
275
  appearance: "orange",
308
- class:
309
- "bg-orange-900 dark:bg-transparent text-orange-50 dark:text-orange-50",
276
+ class: zuiInputDateAppearances.orange,
310
277
  },
311
278
  ],
312
279
  });
@@ -4,6 +4,7 @@ import {
4
4
  zuiKbdKeyAppearances,
5
5
  zuiKbdKeyBase,
6
6
  zuiKbdKeySizes,
7
+ zuiKbdSeparatorBase,
7
8
  zuiKbdSeparatorSizes,
8
9
  } from "../../design-system/kbd";
9
10
 
@@ -18,14 +19,11 @@ export const kbdKeyVariants = cva(zuiKbdKeyBase, {
18
19
  },
19
20
  });
20
21
 
21
- export const kbdSeparatorVariants = cva(
22
- "text-[color:var(--zui-kbd-separator-fg,#94a3b8)] dark:text-[color:var(--zui-kbd-separator-fg-dark,#64748b)]",
23
- {
24
- variants: {
25
- size: zuiKbdSeparatorSizes,
26
- },
27
- defaultVariants: {
28
- size: "md",
29
- },
22
+ export const kbdSeparatorVariants = cva(zuiKbdSeparatorBase, {
23
+ variants: {
24
+ size: zuiKbdSeparatorSizes,
30
25
  },
31
- );
26
+ defaultVariants: {
27
+ size: "md",
28
+ },
29
+ });
@@ -152,6 +152,30 @@ describe("Select — keyboard and a11y", () => {
152
152
  expect(listbox).toHaveAttribute("aria-multiselectable", "true");
153
153
  });
154
154
 
155
+ it("uses a custom trigger id as the listbox label reference", async () => {
156
+ const user = userEvent.setup();
157
+ render(
158
+ <Select multiple defaultValue={[]}>
159
+ <SelectTrigger id="custom-select-trigger">
160
+ <SelectValue placeholder="Pick" />
161
+ </SelectTrigger>
162
+ <SelectContent>
163
+ <SelectItem value="a">Alpha</SelectItem>
164
+ </SelectContent>
165
+ </Select>,
166
+ );
167
+
168
+ const trigger = screen.getByRole("button", { name: /pick/i });
169
+ await user.click(trigger);
170
+
171
+ const listbox = screen.getByRole("listbox");
172
+ const labelledBy = listbox.getAttribute("aria-labelledby");
173
+
174
+ expect(trigger).toHaveAttribute("id", "custom-select-trigger");
175
+ expect(listbox).toHaveAttribute("aria-labelledby", "custom-select-trigger");
176
+ expect(document.getElementById(labelledBy ?? "")).toBe(trigger);
177
+ });
178
+
155
179
  it("moves focus across enabled options with arrow keys", async () => {
156
180
  const user = userEvent.setup();
157
181
  render(
@@ -1,5 +1,14 @@
1
1
  "use client";
2
- import { useState, useEffect, useCallback, useRef, useId } from "react";
2
+ import {
3
+ Children,
4
+ isValidElement,
5
+ useState,
6
+ useEffect,
7
+ useCallback,
8
+ useRef,
9
+ useId,
10
+ } from "react";
11
+ import type { ReactNode } from "react";
3
12
  import {
4
13
  SelectProps,
5
14
  SelectOption,
@@ -25,14 +34,34 @@ export const useSelect = () => {
25
34
  return ctx;
26
35
  };
27
36
 
37
+ const findSelectTriggerId = (children: ReactNode): string | undefined => {
38
+ for (const child of Children.toArray(children)) {
39
+ if (!isValidElement<{ id?: unknown; children?: ReactNode }>(child)) {
40
+ continue;
41
+ }
42
+ if (child.type === SelectTrigger && typeof child.props.id === "string") {
43
+ return child.props.id;
44
+ }
45
+ const nestedTriggerId = findSelectTriggerId(child.props.children);
46
+ if (nestedTriggerId) {
47
+ return nestedTriggerId;
48
+ }
49
+ }
50
+ return undefined;
51
+ };
52
+
28
53
  export const Select = ({
29
54
  children,
30
55
  value,
31
56
  defaultValue = [],
32
57
  onChange,
33
58
  multiple = true,
59
+ triggerId: customTriggerId,
34
60
  }: SelectProps) => {
35
- const listboxId = `${useId()}-listbox`;
61
+ const baseId = useId();
62
+ const triggerId =
63
+ customTriggerId ?? findSelectTriggerId(children) ?? `${baseId}-trigger`;
64
+ const listboxId = `${baseId}-listbox`;
36
65
  const [internal, setInternal] = useState<string[]>(defaultValue);
37
66
  const [open, setOpen] = useState(false);
38
67
  const [options, setOptions] = useState<SelectOption[]>([]);
@@ -98,6 +127,7 @@ export const Select = ({
98
127
  registerOption,
99
128
  options,
100
129
  multiple,
130
+ triggerId,
101
131
  listboxId,
102
132
  }}
103
133
  >
@@ -110,15 +140,17 @@ export const Select = ({
110
140
 
111
141
  export const SelectTrigger = ({
112
142
  className,
143
+ id: _customId,
113
144
  variant,
114
145
  size,
115
146
  onClick,
116
147
  ...props
117
148
  }: SelectTriggerProps) => {
118
- const { open, setOpen, listboxId } = useSelect();
149
+ const { open, setOpen, triggerId, listboxId } = useSelect();
119
150
 
120
151
  return (
121
152
  <button
153
+ id={triggerId}
122
154
  type="button"
123
155
  aria-expanded={open}
124
156
  aria-haspopup="listbox"
@@ -172,7 +204,7 @@ export const SelectContent = ({
172
204
  spacing = "default",
173
205
  ...props
174
206
  }: SelectContentProps) => {
175
- const { open, listboxId, multiple } = useSelect();
207
+ const { open, triggerId, listboxId, multiple } = useSelect();
176
208
  const panelRef = useRef<HTMLDivElement>(null);
177
209
 
178
210
  useEffect(() => {
@@ -248,6 +280,7 @@ export const SelectContent = ({
248
280
  ref={panelRef}
249
281
  id={listboxId}
250
282
  role="listbox"
283
+ aria-labelledby={triggerId}
251
284
  aria-multiselectable={multiple}
252
285
  tabIndex={-1}
253
286
  className={cn(
@@ -40,6 +40,7 @@ export type SelectContextType = {
40
40
  registerOption: (option: SelectOption) => void;
41
41
  options: SelectOption[];
42
42
  multiple: boolean;
43
+ triggerId: string;
43
44
  listboxId: string;
44
45
  };
45
46
 
@@ -48,6 +49,7 @@ export type SelectProps = {
48
49
  defaultValue?: string[];
49
50
  onChange?: (value: string[]) => void;
50
51
  multiple?: boolean;
52
+ triggerId?: string;
51
53
  children: ReactNode;
52
54
  className?: string;
53
55
  };
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/design-system/kbd.ts","../src/ui/kbd/variants.ts","../src/ui/kbd/kbd-base.tsx"],"names":[],"mappings":"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","file":"chunk-CJXGDY7A.mjs","sourcesContent":["export const zuiKbdBase = [\n \"inline-flex items-center justify-center gap-1 align-middle\",\n \"rounded-[var(--zui-kbd-radius,0.375rem)] font-mono font-medium leading-none select-none\",\n] as const;\n\nexport const zuiKbdKeyAppearances = {\n default:\n \"bg-[var(--zui-kbd-default-bg,#0f172a)] dark:bg-[var(--zui-kbd-default-bg-dark,#f8fafc)] text-[color:var(--zui-kbd-default-fg,#f8fafc)] dark:text-[color:var(--zui-kbd-default-fg-dark,#020617)] shadow-[var(--zui-kbd-default-shadow,0_1px_2px_#0f172a14)] dark:shadow-[var(--zui-kbd-default-shadow-dark,0_1px_2px_#0f172a1f)]\",\n secondary:\n \"bg-[var(--zui-kbd-secondary-bg,#e2e8f0)] dark:bg-[var(--zui-kbd-secondary-bg-dark,#1e293b)] text-[color:var(--zui-kbd-secondary-fg,#0f172a)] dark:text-[color:var(--zui-kbd-secondary-fg-dark,#f8fafc)]\",\n destructive:\n \"bg-[var(--zui-kbd-destructive-bg,#f43f5e)] dark:bg-[var(--zui-kbd-destructive-bg-dark,#be123c)] text-[color:var(--zui-kbd-destructive-fg,#ffffff)] dark:text-[color:var(--zui-kbd-destructive-fg-dark,#ffffff)]\",\n outline:\n \"border border-[color:var(--zui-kbd-outline-border,#0000001a)] dark:border-[color:var(--zui-kbd-outline-border-dark,#ffffff1a)] bg-[var(--zui-kbd-outline-bg,#0000000d)] dark:bg-[var(--zui-kbd-outline-bg-dark,#ffffff0d)] text-[color:var(--zui-kbd-outline-fg,#0f172a)] dark:text-[color:var(--zui-kbd-outline-fg-dark,#f8fafc)]\",\n ghost:\n \"bg-transparent text-[color:var(--zui-kbd-ghost-fg,#334155)] dark:text-[color:var(--zui-kbd-ghost-fg-dark,#e2e8f0)]\",\n glass:\n \"border border-[color:var(--zui-kbd-glass-border,#00000026)] dark:border-[color:var(--zui-kbd-glass-border-dark,#ffffff26)] bg-[var(--zui-kbd-glass-bg,#0000001a)] dark:bg-[var(--zui-kbd-glass-bg-dark,#ffffff1a)] text-[color:var(--zui-kbd-glass-fg,#0f172a)] dark:text-[color:var(--zui-kbd-glass-fg-dark,#ffffff)] backdrop-blur-md\",\n emerald:\n \"bg-[var(--zui-kbd-emerald-bg,#10b981)] dark:bg-[var(--zui-kbd-emerald-bg-dark,#065f46)] text-[color:var(--zui-kbd-emerald-fg,#ffffff)] dark:text-[color:var(--zui-kbd-emerald-fg-dark,#ffffff)]\",\n indigo:\n \"bg-[var(--zui-kbd-indigo-bg,#3730a3)] dark:bg-[var(--zui-kbd-indigo-bg-dark,#4f46e5)] text-[color:var(--zui-kbd-indigo-fg,#ffffff)] dark:text-[color:var(--zui-kbd-indigo-fg-dark,#ffffff)]\",\n purple:\n \"bg-[var(--zui-kbd-purple-bg,#6b21a8)] dark:bg-[var(--zui-kbd-purple-bg-dark,#9333ea)] text-[color:var(--zui-kbd-purple-fg,#ffffff)] dark:text-[color:var(--zui-kbd-purple-fg-dark,#ffffff)]\",\n pink: \"bg-[var(--zui-kbd-pink-bg,#9d174d)] dark:bg-[var(--zui-kbd-pink-bg-dark,#db2777)] text-[color:var(--zui-kbd-pink-fg,#ffffff)] dark:text-[color:var(--zui-kbd-pink-fg-dark,#ffffff)]\",\n rose: \"bg-[var(--zui-kbd-rose-bg,#9f1239)] dark:bg-[var(--zui-kbd-rose-bg-dark,#e11d48)] text-[color:var(--zui-kbd-rose-fg,#ffffff)] dark:text-[color:var(--zui-kbd-rose-fg-dark,#ffffff)]\",\n sky: \"bg-[var(--zui-kbd-sky-bg,#0ea5e9)] dark:bg-[var(--zui-kbd-sky-bg-dark,#0369a1)] text-[color:var(--zui-kbd-sky-fg,#ffffff)] dark:text-[color:var(--zui-kbd-sky-fg-dark,#ffffff)]\",\n teal: \"bg-[var(--zui-kbd-teal-bg,#14b8a6)] dark:bg-[var(--zui-kbd-teal-bg-dark,#0f766e)] text-[color:var(--zui-kbd-teal-fg,#ffffff)] dark:text-[color:var(--zui-kbd-teal-fg-dark,#ffffff)]\",\n yellow:\n \"bg-[var(--zui-kbd-yellow-bg,#eab308)] dark:bg-[var(--zui-kbd-yellow-bg-dark,#854d0e)] text-[color:var(--zui-kbd-yellow-fg,#ffffff)] dark:text-[color:var(--zui-kbd-yellow-fg-dark,#ffffff)]\",\n orange:\n \"bg-[var(--zui-kbd-orange-bg,#f97316)] dark:bg-[var(--zui-kbd-orange-bg-dark,#9a3412)] text-[color:var(--zui-kbd-orange-fg,#ffffff)] dark:text-[color:var(--zui-kbd-orange-fg-dark,#ffffff)]\",\n gray: \"bg-[var(--zui-kbd-gray-bg,#6b7280)] dark:bg-[var(--zui-kbd-gray-bg-dark,#374151)] text-[color:var(--zui-kbd-gray-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gray-fg-dark,#ffffff)]\",\n amber:\n \"bg-[var(--zui-kbd-amber-bg,#f59e0b)] dark:bg-[var(--zui-kbd-amber-bg-dark,#92400e)] text-[color:var(--zui-kbd-amber-fg,#ffffff)] dark:text-[color:var(--zui-kbd-amber-fg-dark,#ffffff)]\",\n violet:\n \"bg-[var(--zui-kbd-violet-bg,#5b21b6)] dark:bg-[var(--zui-kbd-violet-bg-dark,#7c3aed)] text-[color:var(--zui-kbd-violet-fg,#ffffff)] dark:text-[color:var(--zui-kbd-violet-fg-dark,#ffffff)]\",\n \"gradient-blue\":\n \"bg-linear-to-r from-[var(--zui-kbd-gradient-blue-from,#1e40af)] dark:from-[var(--zui-kbd-gradient-blue-from-dark,#2563eb)] to-[var(--zui-kbd-gradient-blue-to,#6b21a8)] dark:to-[var(--zui-kbd-gradient-blue-to-dark,#9333ea)] text-[color:var(--zui-kbd-gradient-blue-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gradient-blue-fg-dark,#ffffff)]\",\n \"gradient-green\":\n \"bg-linear-to-r from-[var(--zui-kbd-gradient-green-from,#166534)] dark:from-[var(--zui-kbd-gradient-green-from-dark,#16a34a)] to-[var(--zui-kbd-gradient-green-to,#3f6212)] dark:to-[var(--zui-kbd-gradient-green-to-dark,#65a30d)] text-[color:var(--zui-kbd-gradient-green-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gradient-green-fg-dark,#ffffff)]\",\n \"gradient-red\":\n \"bg-linear-to-r from-[var(--zui-kbd-gradient-red-from,#991b1b)] dark:from-[var(--zui-kbd-gradient-red-from-dark,#dc2626)] to-[var(--zui-kbd-gradient-red-to,#9d174d)] dark:to-[var(--zui-kbd-gradient-red-to-dark,#db2777)] text-[color:var(--zui-kbd-gradient-red-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gradient-red-fg-dark,#ffffff)]\",\n \"gradient-yellow\":\n \"bg-linear-to-r from-[var(--zui-kbd-gradient-yellow-from,#854d0e)] dark:from-[var(--zui-kbd-gradient-yellow-from-dark,#ca8a04)] to-[var(--zui-kbd-gradient-yellow-to,#9a3412)] dark:to-[var(--zui-kbd-gradient-yellow-to-dark,#ea580c)] text-[color:var(--zui-kbd-gradient-yellow-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gradient-yellow-fg-dark,#ffffff)]\",\n \"gradient-purple\":\n \"bg-linear-to-r from-[var(--zui-kbd-gradient-purple-from,#6b21a8)] dark:from-[var(--zui-kbd-gradient-purple-from-dark,#9333ea)] to-[var(--zui-kbd-gradient-purple-to,#9d174d)] dark:to-[var(--zui-kbd-gradient-purple-to-dark,#db2777)] text-[color:var(--zui-kbd-gradient-purple-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gradient-purple-fg-dark,#ffffff)]\",\n \"gradient-teal\":\n \"bg-linear-to-r from-[var(--zui-kbd-gradient-teal-from,#115e59)] dark:from-[var(--zui-kbd-gradient-teal-from-dark,#0d9488)] to-[var(--zui-kbd-gradient-teal-to,#155e75)] dark:to-[var(--zui-kbd-gradient-teal-to-dark,#0891b2)] text-[color:var(--zui-kbd-gradient-teal-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gradient-teal-fg-dark,#ffffff)]\",\n \"gradient-indigo\":\n \"bg-linear-to-r from-[var(--zui-kbd-gradient-indigo-from,#3730a3)] dark:from-[var(--zui-kbd-gradient-indigo-from-dark,#4f46e5)] to-[var(--zui-kbd-gradient-indigo-to,#6b21a8)] dark:to-[var(--zui-kbd-gradient-indigo-to-dark,#9333ea)] text-[color:var(--zui-kbd-gradient-indigo-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gradient-indigo-fg-dark,#ffffff)]\",\n \"gradient-pink\":\n \"bg-linear-to-r from-[var(--zui-kbd-gradient-pink-from,#9d174d)] dark:from-[var(--zui-kbd-gradient-pink-from-dark,#db2777)] to-[var(--zui-kbd-gradient-pink-to,#9f1239)] dark:to-[var(--zui-kbd-gradient-pink-to-dark,#e11d48)] text-[color:var(--zui-kbd-gradient-pink-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gradient-pink-fg-dark,#ffffff)]\",\n \"gradient-orange\":\n \"bg-linear-to-r from-[var(--zui-kbd-gradient-orange-from,#9a3412)] dark:from-[var(--zui-kbd-gradient-orange-from-dark,#ea580c)] to-[var(--zui-kbd-gradient-orange-to,#991b1b)] dark:to-[var(--zui-kbd-gradient-orange-to-dark,#dc2626)] text-[color:var(--zui-kbd-gradient-orange-fg,#ffffff)] dark:text-[color:var(--zui-kbd-gradient-orange-fg-dark,#ffffff)]\",\n} as const;\n\nexport type ZuiKbdAppearance = keyof typeof zuiKbdKeyAppearances;\n\nexport const zuiKbdKeyBase = [\n \"inline-flex items-center justify-center font-mono font-medium leading-none\",\n \"rounded-[var(--zui-kbd-radius,0.375rem)]\",\n \"shadow-[var(--zui-kbd-shadow,inset_0_-1px_0_#0000001f)] dark:shadow-[var(--zui-kbd-shadow-dark,inset_0_-1px_0_#0000004d)]\",\n] as const;\n\nexport const zuiKbdKeySizes = {\n sm: \"h-5 min-w-5 px-1 text-[0.7rem]\",\n md: \"h-6 min-w-6 px-1.5 text-xs\",\n lg: \"h-7 min-w-7 px-2 text-sm\",\n} as const;\n\nexport type ZuiKbdSize = keyof typeof zuiKbdKeySizes;\n\nexport const zuiKbdSeparatorSizes = {\n sm: \"text-[0.7rem]\",\n md: \"text-xs\",\n lg: \"text-sm\",\n} as const;\n","import { cva } from \"class-variance-authority\";\n\nimport {\n zuiKbdKeyAppearances,\n zuiKbdKeyBase,\n zuiKbdKeySizes,\n zuiKbdSeparatorSizes,\n} from \"../../design-system/kbd\";\n\nexport const kbdKeyVariants = cva(zuiKbdKeyBase, {\n variants: {\n appearance: zuiKbdKeyAppearances,\n size: zuiKbdKeySizes,\n },\n defaultVariants: {\n appearance: \"outline\",\n size: \"md\",\n },\n});\n\nexport const kbdSeparatorVariants = cva(\n \"text-[color:var(--zui-kbd-separator-fg,#94a3b8)] dark:text-[color:var(--zui-kbd-separator-fg-dark,#64748b)]\",\n {\n variants: {\n size: zuiKbdSeparatorSizes,\n },\n defaultVariants: {\n size: \"md\",\n },\n },\n);\n","\"use client\";\n\nimport { Fragment } from \"react\";\n\nimport { zuiKbdBase } from \"../../design-system/kbd\";\nimport { cn } from \"../../lib/utils\";\n\nimport type { KbdBaseProps } from \"./types\";\nimport { kbdKeyVariants, kbdSeparatorVariants } from \"./variants\";\n\nexport function KbdBase({\n keys,\n separator,\n appearance,\n size,\n children,\n className,\n as: Wrapper = \"span\",\n ref,\n ...rest\n}: KbdBaseProps) {\n const items = keys ?? (children != null ? [children] : []);\n\n return (\n <Wrapper\n ref={ref}\n data-slot=\"kbd\"\n className={cn(zuiKbdBase, className)}\n {...rest}\n >\n {items.map((key, index) => (\n <Fragment key={index}>\n {index > 0 && separator != null ? (\n <span\n data-slot=\"kbd-separator\"\n className={kbdSeparatorVariants({ size })}\n >\n {separator}\n </span>\n ) : null}\n <kbd\n data-slot=\"kbd-key\"\n className={kbdKeyVariants({ appearance, size })}\n >\n {key}\n </kbd>\n </Fragment>\n ))}\n </Wrapper>\n );\n}\n\nKbdBase.displayName = \"Kbd\";\n"]}