@fluixi-ui/tokens 0.3.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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +106 -0
  3. package/dist/css/accordion.css +7 -0
  4. package/dist/css/alert.css +42 -0
  5. package/dist/css/avatar.css +36 -0
  6. package/dist/css/badge.css +12 -0
  7. package/dist/css/base.css +10 -0
  8. package/dist/css/bulk-editor.css +478 -0
  9. package/dist/css/button.css +92 -0
  10. package/dist/css/calendar.css +140 -0
  11. package/dist/css/checkbox-radio.css +66 -0
  12. package/dist/css/command.css +90 -0
  13. package/dist/css/date-field.css +58 -0
  14. package/dist/css/date-picker.css +81 -0
  15. package/dist/css/field.css +19 -0
  16. package/dist/css/hover-card.css +16 -0
  17. package/dist/css/input.css +85 -0
  18. package/dist/css/kbd.css +20 -0
  19. package/dist/css/menubar.css +27 -0
  20. package/dist/css/navigation-menu.css +144 -0
  21. package/dist/css/number-field.css +83 -0
  22. package/dist/css/parts/listbox.css +111 -0
  23. package/dist/css/parts/menu.css +69 -0
  24. package/dist/css/parts/motion.css +34 -0
  25. package/dist/css/parts/overlays.css +36 -0
  26. package/dist/css/progress.css +40 -0
  27. package/dist/css/select-combobox.css +76 -0
  28. package/dist/css/separator.css +15 -0
  29. package/dist/css/skeleton.css +22 -0
  30. package/dist/css/slider.css +71 -0
  31. package/dist/css/spinner.css +17 -0
  32. package/dist/css/switch.css +33 -0
  33. package/dist/css/table.css +173 -0
  34. package/dist/css/tabs.css +32 -0
  35. package/dist/css/toast.css +154 -0
  36. package/dist/css/toggle.css +74 -0
  37. package/dist/css/toolbar.css +48 -0
  38. package/dist/css/tooltip.css +13 -0
  39. package/dist/index.d.ts +6 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +5 -0
  42. package/dist/lib/css/index.d.ts +20 -0
  43. package/dist/lib/css/index.d.ts.map +1 -0
  44. package/dist/lib/css/index.js +135 -0
  45. package/dist/lib/reference/colors.d.ts +24 -0
  46. package/dist/lib/reference/colors.d.ts.map +1 -0
  47. package/dist/lib/reference/colors.js +150 -0
  48. package/dist/lib/reference/index.d.ts +302 -0
  49. package/dist/lib/reference/index.d.ts.map +1 -0
  50. package/dist/lib/reference/index.js +147 -0
  51. package/dist/lib/theme/index.d.ts +32 -0
  52. package/dist/lib/theme/index.d.ts.map +1 -0
  53. package/dist/lib/theme/index.js +87 -0
  54. package/dist/lib/vars/index.d.ts +131 -0
  55. package/dist/lib/vars/index.d.ts.map +1 -0
  56. package/dist/lib/vars/index.js +40 -0
  57. package/dist/preset.css +47 -0
  58. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  59. package/package.json +79 -0
@@ -0,0 +1,478 @@
1
+ @layer flx.components {
2
+ /* ----------------------------------------------------------------------------
3
+ * Bulk editor (spreadsheet grid)
4
+ * ------------------------------------------------------------------------- */
5
+ :where(.flx-ui-bulk-editor) {
6
+ --flx-ui-be-cell-h: 34px;
7
+ --flx-ui-be-head-h: 36px;
8
+ position: relative;
9
+ outline: none;
10
+ color: var(--flx-ui-color-fg);
11
+ font-size: var(--flx-ui-font-size-sm);
12
+ }
13
+ :where(.flx-ui-be-scroll) {
14
+ overflow: auto;
15
+ border: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
16
+ border-radius: var(--flx-ui-radius-md);
17
+ }
18
+ :where(.flx-ui-be-table) {
19
+ border-collapse: collapse;
20
+ table-layout: fixed;
21
+ min-width: 100%;
22
+ }
23
+
24
+ /* Sticky header cells (corner + column headers) */
25
+ :where(.flx-ui-be-corner, .flx-ui-be-colh, .flx-ui-be-actions-head) {
26
+ position: sticky;
27
+ top: 0;
28
+ height: var(--flx-ui-be-head-h);
29
+ background: var(--flx-ui-color-bg-muted);
30
+ border-right: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
31
+ border-bottom: var(--flx-ui-border-width-thick) solid var(--flx-ui-color-border);
32
+ padding: 0 var(--flx-ui-space-3);
33
+ font-size: var(--flx-ui-font-size-xs);
34
+ font-weight: 700;
35
+ text-transform: uppercase;
36
+ letter-spacing: 0.05em;
37
+ color: var(--flx-ui-color-fg-muted);
38
+ box-sizing: border-box;
39
+ user-select: none;
40
+ }
41
+ :where(.flx-ui-be-corner) {
42
+ left: 0;
43
+ z-index: 5;
44
+ text-align: left;
45
+ cursor: pointer;
46
+ border-right-width: var(--flx-ui-border-width-thick);
47
+ }
48
+ :where(.flx-ui-be-colh) {
49
+ z-index: 3;
50
+ cursor: pointer;
51
+ transition: background var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
52
+ color var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
53
+ }
54
+ :where(.flx-ui-be-colh:hover) {
55
+ color: var(--flx-ui-color-primary);
56
+ }
57
+ :where(.flx-ui-be-colh[data-selected]) {
58
+ background: var(--flx-ui-color-primary-subtle);
59
+ color: var(--flx-ui-color-primary-active);
60
+ border-bottom-color: var(--flx-ui-color-primary);
61
+ }
62
+ :where(.flx-ui-be-colh-inner) {
63
+ display: flex;
64
+ align-items: center;
65
+ gap: var(--flx-ui-space-1);
66
+ height: 100%;
67
+ }
68
+ :where(.flx-ui-be-colh-label) {
69
+ flex: 1;
70
+ white-space: nowrap;
71
+ overflow: hidden;
72
+ text-overflow: ellipsis;
73
+ }
74
+ :where(.flx-ui-be-actions-head) {
75
+ z-index: 3;
76
+ width: 56px;
77
+ min-width: 56px;
78
+ }
79
+
80
+ /* Sticky row header (label column) */
81
+ :where(.flx-ui-be-rowh) {
82
+ position: sticky;
83
+ left: 0;
84
+ z-index: 2;
85
+ height: var(--flx-ui-be-cell-h);
86
+ padding: 0 var(--flx-ui-space-3);
87
+ background: var(--flx-ui-color-bg-subtle);
88
+ border-right: var(--flx-ui-border-width-thick) solid var(--flx-ui-color-border);
89
+ border-bottom: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
90
+ text-align: left;
91
+ vertical-align: middle;
92
+ box-sizing: border-box;
93
+ overflow: hidden;
94
+ cursor: pointer;
95
+ }
96
+ :where(.flx-ui-be-rowh:hover) {
97
+ background: var(--flx-ui-color-bg-muted);
98
+ }
99
+ :where(.flx-ui-be-rowh[data-selected]) {
100
+ background: var(--flx-ui-color-primary-subtle);
101
+ }
102
+ :where(.flx-ui-be-rowh-label) {
103
+ font-weight: 500;
104
+ white-space: nowrap;
105
+ overflow: hidden;
106
+ text-overflow: ellipsis;
107
+ }
108
+ :where(.flx-ui-be-rowh-sub) {
109
+ font-size: var(--flx-ui-font-size-xs);
110
+ color: var(--flx-ui-color-fg-subtle);
111
+ white-space: nowrap;
112
+ overflow: hidden;
113
+ text-overflow: ellipsis;
114
+ }
115
+
116
+ /* Data cells */
117
+ :where(.flx-ui-be-cell) {
118
+ position: relative;
119
+ height: var(--flx-ui-be-cell-h);
120
+ padding: 0;
121
+ border-right: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
122
+ border-bottom: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
123
+ background: var(--flx-ui-color-bg);
124
+ cursor: cell;
125
+ user-select: none;
126
+ overflow: hidden;
127
+ box-sizing: border-box;
128
+ vertical-align: middle;
129
+ }
130
+ :where(.flx-ui-be-cell:hover:not([data-selected]):not([data-anchor]):not([data-editing])) {
131
+ background: color-mix(in srgb, var(--flx-ui-color-primary) 6%, var(--flx-ui-color-bg));
132
+ }
133
+ :where(.flx-ui-be-cell[data-selected]) {
134
+ background: var(--flx-ui-color-primary-subtle);
135
+ }
136
+ :where(.flx-ui-be-cell[data-anchor]) {
137
+ background: var(--flx-ui-color-bg);
138
+ box-shadow: inset 0 0 0 2px var(--flx-ui-color-primary);
139
+ z-index: 2;
140
+ }
141
+ :where(.flx-ui-be-cell[data-editing]) {
142
+ overflow: visible;
143
+ box-shadow: inset 0 0 0 2px var(--flx-ui-color-primary), var(--flx-ui-shadow-md);
144
+ z-index: 10;
145
+ }
146
+ :where(.flx-ui-be-cell[data-invalid]) {
147
+ background: var(--flx-ui-color-danger-subtle);
148
+ box-shadow: inset 0 0 0 1px var(--flx-ui-color-danger);
149
+ }
150
+ :where(.flx-ui-be-cell[data-invalid][data-anchor]) {
151
+ box-shadow: inset 0 0 0 2px var(--flx-ui-color-danger);
152
+ }
153
+ :where(.flx-ui-be-val) {
154
+ height: 100%;
155
+ display: flex;
156
+ align-items: center;
157
+ padding: 0 var(--flx-ui-space-3);
158
+ white-space: nowrap;
159
+ overflow: hidden;
160
+ pointer-events: none;
161
+ }
162
+ :where(.flx-ui-be-ph) {
163
+ color: var(--flx-ui-color-fg-subtle);
164
+ font-size: var(--flx-ui-font-size-xs);
165
+ }
166
+ :where(.flx-ui-be-input) {
167
+ position: absolute;
168
+ inset: 0;
169
+ width: 100%;
170
+ height: 100%;
171
+ border: none;
172
+ outline: none;
173
+ background: var(--flx-ui-color-bg);
174
+ color: var(--flx-ui-color-fg);
175
+ font: inherit;
176
+ padding: 0 var(--flx-ui-space-3);
177
+ box-sizing: border-box;
178
+ z-index: 11;
179
+ }
180
+ :where(.flx-ui-be-check-wrap) {
181
+ height: 100%;
182
+ display: flex;
183
+ align-items: center;
184
+ justify-content: center;
185
+ }
186
+ :where(.flx-ui-be-check) {
187
+ width: 15px;
188
+ height: 15px;
189
+ cursor: pointer;
190
+ accent-color: var(--flx-ui-color-primary);
191
+ }
192
+
193
+ /* Fill handle on the active cell */
194
+ :where(.flx-ui-be-fill-handle) {
195
+ position: absolute;
196
+ right: -1px;
197
+ bottom: -1px;
198
+ width: 8px;
199
+ height: 8px;
200
+ background: var(--flx-ui-color-primary);
201
+ cursor: crosshair;
202
+ z-index: 3;
203
+ }
204
+
205
+ /* Group / section rows */
206
+ :where(.flx-ui-be-group-label, .flx-ui-be-group-cell) {
207
+ height: 42px;
208
+ background: var(--flx-ui-color-bg-muted);
209
+ border-top: var(--flx-ui-border-width-thick) solid var(--flx-ui-color-border);
210
+ border-bottom: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
211
+ box-sizing: border-box;
212
+ vertical-align: middle;
213
+ }
214
+ :where(.flx-ui-be-group-label) {
215
+ position: sticky;
216
+ left: 0;
217
+ z-index: 2;
218
+ padding: 0 var(--flx-ui-space-3);
219
+ border-right: var(--flx-ui-border-width-thick) solid var(--flx-ui-color-border);
220
+ }
221
+ :where(.flx-ui-be-group-cell) {
222
+ padding: 0 var(--flx-ui-space-1);
223
+ text-align: right;
224
+ }
225
+ :where(.flx-ui-be-group-head) {
226
+ display: flex;
227
+ align-items: center;
228
+ gap: var(--flx-ui-space-2);
229
+ font-weight: 700;
230
+ white-space: nowrap;
231
+ }
232
+ :where(.flx-ui-be-group-thumb) {
233
+ width: 22px;
234
+ height: 22px;
235
+ border-radius: var(--flx-ui-radius-sm);
236
+ object-fit: cover;
237
+ border: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
238
+ flex-shrink: 0;
239
+ }
240
+
241
+ /* Trailing row actions */
242
+ :where(.flx-ui-be-actions) {
243
+ height: var(--flx-ui-be-cell-h);
244
+ width: 56px;
245
+ min-width: 56px;
246
+ border-bottom: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
247
+ background: var(--flx-ui-color-bg);
248
+ text-align: center;
249
+ vertical-align: middle;
250
+ box-sizing: border-box;
251
+ padding: 0 var(--flx-ui-space-2);
252
+ }
253
+
254
+ /* Keyboard hints */
255
+ :where(.flx-ui-be-hints) {
256
+ display: flex;
257
+ flex-wrap: wrap;
258
+ gap: var(--flx-ui-space-2);
259
+ padding: var(--flx-ui-space-2) var(--flx-ui-space-1) 0;
260
+ font-size: var(--flx-ui-font-size-xs);
261
+ color: var(--flx-ui-color-fg-subtle);
262
+ }
263
+ :where(.flx-ui-be-hints kbd) {
264
+ font-size: 10px;
265
+ padding: 1px 5px;
266
+ border-radius: var(--flx-ui-radius-sm);
267
+ border: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
268
+ background: var(--flx-ui-color-bg-muted);
269
+ font-family: var(--flx-ui-font-mono, monospace);
270
+ }
271
+
272
+ /* Bulk editor — sort caret + filter row */
273
+ :where(.flx-ui-be-sort) {
274
+ appearance: none;
275
+ border: none;
276
+ background: none;
277
+ cursor: pointer;
278
+ color: var(--flx-ui-color-fg-subtle);
279
+ font-size: 10px;
280
+ line-height: 1;
281
+ padding: 2px;
282
+ border-radius: var(--flx-ui-radius-sm);
283
+ flex-shrink: 0;
284
+ }
285
+ :where(.flx-ui-be-sort:hover) {
286
+ color: var(--flx-ui-color-primary);
287
+ }
288
+ :where(.flx-ui-be-filter-row th) {
289
+ position: sticky;
290
+ top: var(--flx-ui-be-head-h);
291
+ z-index: 3;
292
+ background: var(--flx-ui-color-bg);
293
+ border-right: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
294
+ border-bottom: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
295
+ padding: 3px 4px;
296
+ box-sizing: border-box;
297
+ }
298
+ :where(.flx-ui-be-filter-corner) {
299
+ left: 0;
300
+ z-index: 5;
301
+ border-right: var(--flx-ui-border-width-thick) solid var(--flx-ui-color-border);
302
+ }
303
+ :where(.flx-ui-be-filter) {
304
+ width: 100%;
305
+ height: 24px;
306
+ box-sizing: border-box;
307
+ border: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
308
+ border-radius: var(--flx-ui-radius-sm);
309
+ background: var(--flx-ui-color-bg-subtle);
310
+ color: var(--flx-ui-color-fg);
311
+ font: inherit;
312
+ font-size: var(--flx-ui-font-size-xs);
313
+ padding: 0 var(--flx-ui-space-2);
314
+ outline: none;
315
+ }
316
+ :where(.flx-ui-be-filter:focus) {
317
+ border-color: var(--flx-ui-color-primary);
318
+ }
319
+
320
+ /* Bulk editor — locking */
321
+ :where(.flx-ui-be-cell[data-locked]) {
322
+ background: var(--flx-ui-color-bg-muted);
323
+ }
324
+ :where(.flx-ui-be-cell[data-locked] .flx-ui-be-val) {
325
+ color: var(--flx-ui-color-fg-muted);
326
+ }
327
+ :where(.flx-ui-be-lock) {
328
+ position: absolute;
329
+ top: 2px;
330
+ left: 2px;
331
+ z-index: 4;
332
+ display: none;
333
+ align-items: center;
334
+ justify-content: center;
335
+ padding: 1px;
336
+ border: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
337
+ background: var(--flx-ui-color-bg);
338
+ border-radius: var(--flx-ui-radius-sm);
339
+ color: var(--flx-ui-color-fg-subtle);
340
+ cursor: pointer;
341
+ line-height: 0;
342
+ }
343
+ :where(.flx-ui-be-cell:hover .flx-ui-be-lock) {
344
+ display: flex;
345
+ }
346
+ :where(.flx-ui-be-cell[data-locked] .flx-ui-be-lock) {
347
+ display: flex;
348
+ color: var(--flx-ui-color-primary);
349
+ border-color: var(--flx-ui-color-primary);
350
+ }
351
+ :where(.flx-ui-be-lock:hover) {
352
+ color: var(--flx-ui-color-primary);
353
+ border-color: var(--flx-ui-color-primary);
354
+ }
355
+
356
+ /* Row header lock (tri-state) */
357
+ :where(.flx-ui-be-rowh-inner) {
358
+ display: flex;
359
+ align-items: center;
360
+ gap: var(--flx-ui-space-2);
361
+ height: 100%;
362
+ }
363
+ :where(.flx-ui-be-rowh-text) {
364
+ min-width: 0;
365
+ flex: 1;
366
+ }
367
+ :where(.flx-ui-be-row-lock) {
368
+ flex-shrink: 0;
369
+ display: none;
370
+ align-items: center;
371
+ justify-content: center;
372
+ padding: 2px;
373
+ border: none;
374
+ background: none;
375
+ border-radius: var(--flx-ui-radius-sm);
376
+ color: var(--flx-ui-color-fg-subtle);
377
+ cursor: pointer;
378
+ line-height: 0;
379
+ }
380
+ :where(.flx-ui-be-rowh:hover .flx-ui-be-row-lock),
381
+ :where(.flx-ui-be-rowh[data-lock-state='some'] .flx-ui-be-row-lock),
382
+ :where(.flx-ui-be-rowh[data-lock-state='all'] .flx-ui-be-row-lock) {
383
+ display: flex;
384
+ }
385
+ :where(.flx-ui-be-rowh[data-lock-state='all'] .flx-ui-be-row-lock) {
386
+ color: var(--flx-ui-color-primary);
387
+ }
388
+ :where(.flx-ui-be-rowh[data-lock-state='some'] .flx-ui-be-row-lock) {
389
+ color: var(--flx-ui-color-primary);
390
+ opacity: 0.55;
391
+ }
392
+ :where(.flx-ui-be-row-lock:hover) {
393
+ color: var(--flx-ui-color-primary);
394
+ opacity: 1;
395
+ }
396
+
397
+ /* Bulk editor — context menu (reuses the shared [role=menu] surface skin) */
398
+ :where(.flx-ui-be-menu) {
399
+ position: fixed;
400
+ z-index: 60;
401
+ min-width: 180px;
402
+ }
403
+ :where(.flx-ui-be-menu [role='menuitem']) {
404
+ width: 100%;
405
+ justify-content: flex-start;
406
+ text-align: left;
407
+ }
408
+
409
+ /* Bulk editor — column header select-all checkbox */
410
+ :where(.flx-ui-be-head-check) {
411
+ width: 14px;
412
+ height: 14px;
413
+ cursor: pointer;
414
+ accent-color: var(--flx-ui-color-primary);
415
+ flex-shrink: 0;
416
+ }
417
+ :where(.flx-ui-be-check:disabled) {
418
+ cursor: not-allowed;
419
+ }
420
+
421
+ /* Bulk editor — column resize grip */
422
+ :where(.flx-ui-be-col-resize) {
423
+ position: absolute;
424
+ top: 0;
425
+ right: 0;
426
+ width: 6px;
427
+ height: 100%;
428
+ cursor: col-resize;
429
+ z-index: 4;
430
+ user-select: none;
431
+ }
432
+ :where(.flx-ui-be-col-resize::after) {
433
+ content: '';
434
+ position: absolute;
435
+ top: 20%;
436
+ right: 2px;
437
+ height: 60%;
438
+ width: 2px;
439
+ border-radius: 1px;
440
+ background: transparent;
441
+ transition: background var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
442
+ }
443
+ :where(.flx-ui-be-colh:hover .flx-ui-be-col-resize::after),
444
+ :where(.flx-ui-be-col-resize:hover::after) {
445
+ background: var(--flx-ui-color-primary);
446
+ }
447
+
448
+ /* Bulk editor — reorder drop target */
449
+ :where(.flx-ui-be-colh[data-drop-target]) {
450
+ box-shadow: inset 2px 0 0 var(--flx-ui-color-primary);
451
+ }
452
+
453
+ /* Bulk editor — aggregation footer (sticky bottom) */
454
+ :where(.flx-ui-be-foot-corner, .flx-ui-be-foot-cell) {
455
+ position: sticky;
456
+ bottom: 0;
457
+ height: var(--flx-ui-be-cell-h);
458
+ background: var(--flx-ui-color-bg-muted);
459
+ border-top: var(--flx-ui-border-width-thick) solid var(--flx-ui-color-border);
460
+ border-right: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
461
+ padding: 0 var(--flx-ui-space-3);
462
+ box-sizing: border-box;
463
+ font-variant-numeric: tabular-nums;
464
+ font-weight: 600;
465
+ color: var(--flx-ui-color-fg);
466
+ vertical-align: middle;
467
+ }
468
+ :where(.flx-ui-be-foot-corner) {
469
+ left: 0;
470
+ z-index: 5;
471
+ text-align: left;
472
+ text-transform: uppercase;
473
+ letter-spacing: 0.05em;
474
+ font-size: var(--flx-ui-font-size-xs);
475
+ color: var(--flx-ui-color-fg-muted);
476
+ border-right-width: var(--flx-ui-border-width-thick);
477
+ }
478
+ }
@@ -0,0 +1,92 @@
1
+ @layer flx.components {
2
+ /* ----------------------------------------------------------------------------
3
+ * Button (and any [data-variant] control, e.g. dialog triggers)
4
+ * ------------------------------------------------------------------------- */
5
+ :where([data-variant]) {
6
+ box-sizing: border-box;
7
+ display: inline-flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ gap: var(--flx-ui-space-2);
11
+ font: inherit;
12
+ font-weight: var(--flx-ui-ctl-font);
13
+ letter-spacing: var(--flx-ui-letter-spacing-tight);
14
+ line-height: var(--flx-ui-line-height-none);
15
+ cursor: pointer;
16
+ user-select: none;
17
+ /* Transparent base so `ghost` (and any variant that sets no background) doesn't
18
+ fall back to the native button UA background — visible on dark surfaces. */
19
+ background: transparent;
20
+ border: var(--flx-ui-border-width-thin) solid transparent;
21
+ border-radius: var(--flx-ui-radius-md);
22
+ height: var(--flx-ui-size-md);
23
+ padding: 0 var(--flx-ui-space-4);
24
+ color: var(--flx-ui-color-fg);
25
+ transition:
26
+ background var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
27
+ border-color var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
28
+ box-shadow var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
29
+ }
30
+ :where([data-variant][data-size='sm']) {
31
+ height: var(--flx-ui-size-sm);
32
+ padding: 0 var(--flx-ui-space-3);
33
+ font-size: var(--flx-ui-font-size-sm);
34
+ }
35
+ :where([data-variant][data-size='lg']) {
36
+ height: var(--flx-ui-size-lg);
37
+ padding: 0 var(--flx-ui-space-5);
38
+ font-size: var(--flx-ui-font-size-lg);
39
+ }
40
+
41
+ /* Solid: the primary action — a flat, confident accent. Depth comes from the
42
+ color step change on interaction, not from shadow or sheen. */
43
+ :where([data-variant='solid']) {
44
+ background: var(--flx-ui-color-primary);
45
+ color: var(--flx-ui-color-primary-fg);
46
+ }
47
+ :where([data-variant='solid']:hover:not([data-disabled])) {
48
+ background: var(--flx-ui-color-primary-hover);
49
+ }
50
+ :where([data-variant='solid']:active:not([data-disabled])) {
51
+ background: var(--flx-ui-color-primary-active);
52
+ }
53
+
54
+ /* Soft: a tinted, low-key primary. */
55
+ :where([data-variant='soft']) {
56
+ background: var(--flx-ui-color-primary-subtle);
57
+ color: var(--flx-ui-color-primary-active);
58
+ }
59
+ :where([data-variant='soft']:hover:not([data-disabled])) {
60
+ background: color-mix(in oklab, var(--flx-ui-color-primary-subtle), var(--flx-ui-color-primary) 12%);
61
+ }
62
+
63
+ /* Outline: a flat hairline-bordered control. */
64
+ :where([data-variant='outline']) {
65
+ border-color: var(--flx-ui-color-border-strong);
66
+ background: var(--flx-ui-color-bg);
67
+ }
68
+ :where([data-variant='outline']:hover:not([data-disabled])) {
69
+ background: var(--flx-ui-color-bg-subtle);
70
+ border-color: var(--flx-ui-color-fg-muted);
71
+ }
72
+
73
+ /* Ghost: text-only until hovered. */
74
+ :where([data-variant='ghost']) {
75
+ color: var(--flx-ui-color-fg);
76
+ }
77
+ :where([data-variant='ghost']:hover:not([data-disabled])) {
78
+ background: var(--flx-ui-color-bg-muted);
79
+ }
80
+
81
+ :where([data-disabled]) {
82
+ opacity: var(--flx-ui-opacity-disabled);
83
+ cursor: not-allowed;
84
+ pointer-events: none;
85
+ }
86
+
87
+ /* The signature focus ring: a surface-colored gap then an accent halo. */
88
+ :where(:focus-visible) {
89
+ outline: none;
90
+ box-shadow: var(--flx-ui-ctl-ring);
91
+ }
92
+ }
@@ -0,0 +1,140 @@
1
+ @layer flx.components {
2
+ /* ----------------------------------------------------------------------------
3
+ * Calendar / RangeCalendar
4
+ * ------------------------------------------------------------------------- */
5
+ :where([data-calendar]) {
6
+ display: inline-flex;
7
+ flex-direction: column;
8
+ gap: var(--flx-ui-space-3);
9
+ width: max-content;
10
+ }
11
+ :where([data-calendar-header]) {
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: space-between;
15
+ gap: var(--flx-ui-space-2);
16
+ }
17
+ :where([data-calendar-heading]) {
18
+ flex: 1;
19
+ margin: 0;
20
+ text-align: center;
21
+ font-size: var(--flx-ui-font-size-sm);
22
+ font-weight: var(--flx-ui-font-weight-medium);
23
+ color: var(--flx-ui-color-fg);
24
+ }
25
+ :where([data-calendar-nav]) {
26
+ display: inline-flex;
27
+ align-items: center;
28
+ justify-content: center;
29
+ width: 1.75rem;
30
+ height: 1.75rem;
31
+ padding: 0;
32
+ border: 1px solid var(--flx-ui-color-border);
33
+ border-radius: var(--flx-ui-radius-md);
34
+ background: transparent;
35
+ color: var(--flx-ui-color-fg-muted);
36
+ cursor: pointer;
37
+ transition: background var(--flx-ui-duration-fast) var(--flx-ui-easing-standard),
38
+ color var(--flx-ui-duration-fast) var(--flx-ui-easing-standard);
39
+ }
40
+ :where([data-calendar-nav]:hover:not([disabled])) {
41
+ background: var(--flx-ui-color-bg-subtle);
42
+ color: var(--flx-ui-color-fg);
43
+ }
44
+ :where([data-calendar-nav]:focus-visible) {
45
+ outline: none;
46
+ box-shadow: var(--flx-ui-ctl-ring);
47
+ }
48
+ :where([data-calendar-nav][disabled]) {
49
+ color: var(--flx-ui-color-fg-subtle);
50
+ cursor: not-allowed;
51
+ opacity: 0.5;
52
+ }
53
+ :where([data-calendar-grid]) {
54
+ border-collapse: collapse;
55
+ user-select: none;
56
+ }
57
+ :where([data-calendar-weekday]) {
58
+ padding-bottom: var(--flx-ui-space-2);
59
+ font-size: var(--flx-ui-font-size-xs);
60
+ font-weight: var(--flx-ui-font-weight-medium);
61
+ color: var(--flx-ui-color-fg-subtle);
62
+ text-align: center;
63
+ }
64
+ :where([data-calendar-cell]) {
65
+ padding: 0;
66
+ text-align: center;
67
+ }
68
+ :where([data-calendar-day]) {
69
+ position: relative;
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: center;
73
+ width: 2.25rem;
74
+ height: 2.25rem;
75
+ margin: 1px auto;
76
+ border-radius: var(--flx-ui-radius-md);
77
+ font-size: var(--flx-ui-font-size-sm);
78
+ color: var(--flx-ui-color-fg);
79
+ cursor: pointer;
80
+ transition: background var(--flx-ui-duration-fast) var(--flx-ui-easing-standard),
81
+ color var(--flx-ui-duration-fast) var(--flx-ui-easing-standard);
82
+ }
83
+ :where([data-calendar-day]:hover:not([data-disabled]):not([data-unavailable])) {
84
+ background: var(--flx-ui-color-bg-subtle);
85
+ }
86
+ :where([data-calendar-day]:focus-visible) {
87
+ outline: none;
88
+ box-shadow: var(--flx-ui-ctl-ring);
89
+ }
90
+ :where([data-calendar-day][data-today]) {
91
+ font-weight: var(--flx-ui-font-weight-bold);
92
+ }
93
+ :where([data-calendar-day][data-today])::after {
94
+ content: '';
95
+ position: absolute;
96
+ transform: translateY(0.65rem);
97
+ width: 0.25rem;
98
+ height: 0.25rem;
99
+ border-radius: var(--flx-ui-radius-full);
100
+ background: var(--flx-ui-color-primary);
101
+ }
102
+ :where([data-calendar-day][data-selected]) {
103
+ background: var(--flx-ui-color-primary);
104
+ color: var(--flx-ui-color-primary-fg);
105
+ }
106
+ :where([data-calendar-day][data-selected][data-today])::after {
107
+ background: var(--flx-ui-color-primary-fg);
108
+ }
109
+ :where([data-calendar-day][data-outside-month]) {
110
+ color: var(--flx-ui-color-fg-subtle);
111
+ opacity: 0.5;
112
+ }
113
+ :where([data-calendar-day][data-disabled]),
114
+ :where([data-calendar-day][data-unavailable]) {
115
+ color: var(--flx-ui-color-fg-subtle);
116
+ cursor: not-allowed;
117
+ }
118
+ :where([data-calendar-day][data-unavailable]) {
119
+ text-decoration: line-through;
120
+ }
121
+ /* Range: fill the band between endpoints, round only the outer corners. */
122
+ :where([data-range] [data-calendar-day][data-selected]) {
123
+ border-radius: 0;
124
+ background: var(--flx-ui-color-primary-subtle);
125
+ color: var(--flx-ui-color-primary-active);
126
+ }
127
+ :where([data-range] [data-calendar-day][data-selection-start]) {
128
+ border-top-left-radius: var(--flx-ui-radius-md);
129
+ border-bottom-left-radius: var(--flx-ui-radius-md);
130
+ }
131
+ :where([data-range] [data-calendar-day][data-selection-end]) {
132
+ border-top-right-radius: var(--flx-ui-radius-md);
133
+ border-bottom-right-radius: var(--flx-ui-radius-md);
134
+ }
135
+ :where([data-range] [data-calendar-day][data-selection-start]),
136
+ :where([data-range] [data-calendar-day][data-selection-end]) {
137
+ background: var(--flx-ui-color-primary);
138
+ color: var(--flx-ui-color-primary-fg);
139
+ }
140
+ }