@x12i/data 0.0.0-stage → 1.1.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.
@@ -0,0 +1,1169 @@
1
+ /*
2
+ * @x12i/data styles.
3
+ *
4
+ * Tokens only: no hard-coded colors, lengths or font sizes (a test enforces
5
+ * this). Requires the kit variables, for example:
6
+ *
7
+ * @import "@x12i/themes/themes.css";
8
+ * @import "@x12i/ui/styles.css";
9
+ * @import "@x12i/data/styles.css";
10
+ *
11
+ * Every selector sits inside :where(), so it has zero specificity and any app
12
+ * class overrides it without a specificity fight. The grid exposes styling
13
+ * hooks as data attributes: data-kit="data-grid-*" for parts and data-* for
14
+ * state (data-selected, data-sorted, data-pinned, data-editing, ...).
15
+ * Layout uses logical properties, so right-to-left works without extra CSS.
16
+ *
17
+ * Row height follows the density: it is the --kit-grid-row-height token, which
18
+ * the grid also reads at runtime to size its virtual rows. Set data-density on
19
+ * the grid, or wrap it in a DensityProvider, to change it.
20
+ */
21
+
22
+ /* ------------------------------------------------------------------ Frame */
23
+
24
+ :where([data-kit="data-grid"]) {
25
+ /* Resolved here, not on :root, so a density set on the grid itself applies. */
26
+ --kit-grid-row-height: var(--kit-size-control-lg);
27
+ --_row-height: var(--kit-grid-row-height);
28
+ --_cell-pad: var(--kit-space-control-inline-md);
29
+ --_indent: var(--kit-space-4);
30
+ --_surface: var(--kit-color-bg-surface);
31
+ --_header-bg: color-mix(in srgb, var(--kit-color-text-primary) 4%, var(--kit-color-bg-surface));
32
+ --_hover-bg: color-mix(in srgb, var(--kit-color-text-primary) 4%, var(--kit-color-bg-surface));
33
+ --_group-bg: color-mix(in srgb, var(--kit-color-text-primary) 6%, var(--kit-color-bg-surface));
34
+ --_selected-bg: color-mix(in srgb, var(--kit-color-selection) 16%, var(--kit-color-bg-surface));
35
+ --_focus-ring: var(--kit-border-width-focus) solid var(--kit-color-border-focus);
36
+
37
+ position: relative;
38
+ box-sizing: border-box;
39
+ display: flex;
40
+ flex-direction: column;
41
+ min-inline-size: 0;
42
+ overflow: hidden;
43
+ border: var(--kit-border-width-default) solid var(--kit-color-border-default);
44
+ border-radius: var(--kit-radius-panel);
45
+ background-color: var(--_surface);
46
+ color: var(--kit-color-text-primary);
47
+ font-family: var(--kit-font-family-sans);
48
+ font-size: var(--kit-text-body-size);
49
+ font-weight: var(--kit-text-body-weight);
50
+ line-height: var(--kit-text-body-line-height);
51
+ }
52
+
53
+ :where([data-kit="data-grid"] *, [data-kit="data-grid-popover"] *) {
54
+ box-sizing: border-box;
55
+ }
56
+
57
+ :where([data-kit="data-grid-viewport"]) {
58
+ position: relative;
59
+ display: flex;
60
+ flex: 1 1 auto;
61
+ flex-direction: column;
62
+ min-block-size: 0;
63
+ }
64
+
65
+ :where([data-kit="data-grid-scroller"]) {
66
+ position: relative;
67
+ flex: 1 1 auto;
68
+ min-block-size: 0;
69
+ overflow: auto;
70
+ overscroll-behavior: contain;
71
+ scroll-padding-block-start: var(--_row-height);
72
+ }
73
+
74
+ /* The three groups are as wide as the columns, so pinned cells can stick. */
75
+ :where([data-kit="data-grid-header-group"], [data-kit="data-grid-footer-group"]) {
76
+ position: sticky;
77
+ z-index: var(--kit-z-sticky);
78
+ inline-size: max-content;
79
+ min-inline-size: 100%;
80
+ background-color: var(--_header-bg);
81
+ }
82
+
83
+ /* The separators are shadows, not borders, so the header is exactly row-height tall per row. */
84
+ :where([data-kit="data-grid-header-group"]) {
85
+ inset-block-start: 0;
86
+ box-shadow: 0 var(--kit-border-width-default) 0 0 var(--kit-color-border-default);
87
+ }
88
+
89
+ :where([data-kit="data-grid-footer-group"]) {
90
+ inset-block-end: 0;
91
+ box-shadow: 0 calc(var(--kit-border-width-default) * -1) 0 0 var(--kit-color-border-default);
92
+ font-weight: var(--kit-font-weight-semibold);
93
+ }
94
+
95
+ :where([data-kit="data-grid-body"]) {
96
+ position: relative;
97
+ min-inline-size: 100%;
98
+ }
99
+
100
+ /* ------------------------------------------------------------------- Rows */
101
+
102
+ :where([data-kit="data-grid-header"], [data-kit="data-grid-group-header"], [data-kit="data-grid-footer"]) {
103
+ display: flex;
104
+ align-items: stretch;
105
+ block-size: var(--_row-height);
106
+ --_row-bg: var(--_header-bg);
107
+ }
108
+
109
+ :where([data-kit="data-grid-group-header"]) {
110
+ border-block-end: var(--kit-border-width-default) solid var(--kit-color-border-subtle);
111
+ }
112
+
113
+ :where([data-kit="data-grid-row"]) {
114
+ --_row-bg: var(--_surface);
115
+
116
+ position: absolute;
117
+ inset-block-start: 0;
118
+ inset-inline-start: 0;
119
+ display: flex;
120
+ align-items: stretch;
121
+ background-color: var(--_row-bg);
122
+ }
123
+
124
+ :where([data-kit="data-grid-row"][data-kind="data"]:hover) {
125
+ --_row-bg: var(--_hover-bg);
126
+ }
127
+
128
+ :where([data-kit="data-grid-row"][data-selected]) {
129
+ --_row-bg: var(--_selected-bg);
130
+ }
131
+
132
+ :where([data-kit="data-grid-row"][data-selected]:hover) {
133
+ --_row-bg: color-mix(in srgb, var(--kit-color-selection) 22%, var(--kit-color-bg-surface));
134
+ }
135
+
136
+ :where([data-kit="data-grid-row"][data-kind="group"]) {
137
+ --_row-bg: var(--_group-bg);
138
+
139
+ font-weight: var(--kit-font-weight-semibold);
140
+ }
141
+
142
+ :where([data-kit="data-grid-row"][data-kind="detail"]) {
143
+ display: block;
144
+ border-block-end: var(--kit-border-width-default) solid var(--kit-color-border-subtle);
145
+ }
146
+
147
+ :where([data-kit="data-grid-spacer"]) {
148
+ flex: none;
149
+ border-block-end: var(--kit-border-width-default) solid var(--kit-color-border-subtle);
150
+ }
151
+
152
+ :where([data-kit="data-grid-header"] > [data-kit="data-grid-spacer"], [data-kit="data-grid-footer"] > [data-kit="data-grid-spacer"]) {
153
+ border-block-end: 0;
154
+ }
155
+
156
+ /* ------------------------------------------------------------------ Cells */
157
+
158
+ :where([data-kit="data-grid-cell"], [data-kit="data-grid-header-cell"], [data-kit="data-grid-group-header-cell"]) {
159
+ position: relative;
160
+ flex: none;
161
+ display: flex;
162
+ align-items: center;
163
+ min-inline-size: 0;
164
+ padding-inline: var(--_cell-pad);
165
+ overflow: hidden;
166
+ white-space: nowrap;
167
+ background-color: var(--_cell-bg, transparent);
168
+ }
169
+
170
+ :where([data-kit="data-grid-cell"]) {
171
+ border-block-end: var(--kit-border-width-default) solid var(--kit-color-border-subtle);
172
+ }
173
+
174
+ :where([data-kit="data-grid-footer"] > [data-kit="data-grid-cell"]) {
175
+ border-block-end: 0;
176
+ }
177
+
178
+ /* Pinned cells stay put while the rest scrolls, so they need their own background. */
179
+ :where([data-pinned="start"], [data-pinned="end"]) {
180
+ position: sticky;
181
+ z-index: calc(var(--kit-z-base) + 1);
182
+ --_cell-bg: var(--_row-bg);
183
+ }
184
+
185
+ :where([data-pinned="start"][data-pinned-edge]) {
186
+ border-inline-end: var(--kit-border-width-default) solid var(--kit-color-border-default);
187
+ }
188
+
189
+ :where([data-pinned="end"][data-pinned-edge]) {
190
+ border-inline-start: var(--kit-border-width-default) solid var(--kit-color-border-default);
191
+ }
192
+
193
+ :where([data-kit="data-grid-cell"][data-type="select"], [data-kit="data-grid-header-cell"][data-type="select"], [data-kit="data-grid-cell"][data-type="expand"], [data-kit="data-grid-header-cell"][data-type="expand"]) {
194
+ justify-content: center;
195
+ padding-inline: 0;
196
+ }
197
+
198
+ :where([data-align="center"]) {
199
+ justify-content: center;
200
+ text-align: center;
201
+ }
202
+
203
+ :where([data-align="end"]) {
204
+ justify-content: flex-end;
205
+ text-align: end;
206
+ }
207
+
208
+ :where([data-kit="data-grid-cell"][data-type="number"], [data-kit="data-grid-cell"][data-type="currency"], [data-kit="data-grid-cell"][data-type="percent"], [data-kit="data-grid-cell"][data-type="total"]) {
209
+ font-variant-numeric: tabular-nums;
210
+ }
211
+
212
+ :where([data-kit-slot="cell-content"]) {
213
+ display: flex;
214
+ align-items: center;
215
+ gap: var(--kit-space-2);
216
+ min-inline-size: 0;
217
+ max-inline-size: 100%;
218
+ }
219
+
220
+ :where([data-align="center"] > [data-kit-slot="cell-content"]) {
221
+ justify-content: center;
222
+ }
223
+
224
+ :where([data-align="end"] > [data-kit-slot="cell-content"]) {
225
+ justify-content: flex-end;
226
+ }
227
+
228
+ :where([data-kit="data-grid-text"]) {
229
+ min-inline-size: 0;
230
+ overflow: hidden;
231
+ text-overflow: ellipsis;
232
+ white-space: nowrap;
233
+ }
234
+
235
+ /* Rows below a group, and group rows themselves, indent by depth. */
236
+ :where([data-kit="data-grid-cell"][data-first]) {
237
+ padding-inline-start: calc(var(--_cell-pad) + var(--_depth, 0) * var(--_indent));
238
+ }
239
+
240
+ :where([data-kit="data-grid-row"][data-kind="group"] [data-kit="data-grid-cell"][data-first]) {
241
+ padding-inline-start: calc(var(--_cell-pad) / 2 + var(--_depth, 0) * var(--_indent));
242
+ }
243
+
244
+ :where([data-kit="data-grid-row"][data-kind="group"] [data-kit-slot="aggregate"]) {
245
+ color: var(--kit-color-text-secondary);
246
+ font-variant-numeric: tabular-nums;
247
+ }
248
+
249
+ /* Focus: one ring for every navigable cell, drawn inside so it is never clipped. */
250
+ :where([data-kit="data-grid-cell"], [data-kit="data-grid-header-cell"]):focus-visible {
251
+ outline: var(--_focus-ring);
252
+ outline-offset: calc(var(--kit-border-width-focus) * -1);
253
+ }
254
+
255
+ /* ---------------------------------------------------------- Header cells */
256
+
257
+ :where([data-kit="data-grid-header-cell"]) {
258
+ font-size: var(--kit-text-label-size);
259
+ font-weight: var(--kit-text-label-weight);
260
+ line-height: var(--kit-text-label-line-height);
261
+ user-select: none;
262
+ }
263
+
264
+ :where([data-kit="data-grid-group-header-cell"]) {
265
+ justify-content: center;
266
+ border-inline-end: var(--kit-border-width-default) solid var(--kit-color-border-subtle);
267
+ color: var(--kit-color-text-secondary);
268
+ font-size: var(--kit-text-caption-size);
269
+ font-weight: var(--kit-font-weight-semibold);
270
+ line-height: var(--kit-text-caption-line-height);
271
+ }
272
+
273
+ :where([data-kit="data-grid-group-header-cell"][data-blank]) {
274
+ padding-inline: 0;
275
+ }
276
+
277
+ :where([data-kit="data-grid-header-content"]) {
278
+ display: flex;
279
+ align-items: center;
280
+ gap: var(--kit-space-1);
281
+ inline-size: 100%;
282
+ min-inline-size: 0;
283
+ }
284
+
285
+ :where([data-align="end"] > [data-kit="data-grid-header-content"]) {
286
+ justify-content: flex-end;
287
+ }
288
+
289
+ :where([data-align="center"] > [data-kit="data-grid-header-content"]) {
290
+ justify-content: center;
291
+ }
292
+
293
+ :where([data-kit-slot="header-label"]) {
294
+ min-inline-size: 0;
295
+ overflow: hidden;
296
+ text-overflow: ellipsis;
297
+ }
298
+
299
+ :where([data-kit="data-grid-header-content"] > [data-kit-slot="header-label"]) {
300
+ flex: 0 1 auto;
301
+ }
302
+
303
+ /* The sort control is a real button, so it works with a mouse, touch and a screen reader. */
304
+ :where([data-kit="data-grid-sort"], [data-kit="data-grid-group-toggle"], [data-kit="data-grid-menu-item"]) {
305
+ margin: 0;
306
+ padding: 0;
307
+ border: 0;
308
+ border-radius: var(--kit-radius-control);
309
+ background: transparent;
310
+ color: inherit;
311
+ font: inherit;
312
+ text-align: start;
313
+ cursor: pointer;
314
+ appearance: none;
315
+ }
316
+
317
+ :where([data-kit="data-grid-sort"]) {
318
+ display: inline-flex;
319
+ align-items: center;
320
+ gap: var(--kit-space-1);
321
+ flex: 0 1 auto;
322
+ min-inline-size: 0;
323
+ min-block-size: var(--kit-size-target-min);
324
+ padding-inline: var(--kit-space-1);
325
+ margin-inline: calc(var(--kit-space-1) * -1);
326
+ }
327
+
328
+ :where([data-kit="data-grid-sort"]:hover) {
329
+ background-color: color-mix(in srgb, var(--kit-color-text-primary) 8%, transparent);
330
+ }
331
+
332
+ :where([data-kit="data-grid-sort"], [data-kit="data-grid-group-toggle"], [data-kit="data-grid-menu-item"]):focus-visible {
333
+ outline: var(--_focus-ring);
334
+ outline-offset: calc(var(--kit-border-width-focus) * -1);
335
+ }
336
+
337
+ :where([data-kit-slot="sort-icon"]) {
338
+ display: inline-flex;
339
+ flex: none;
340
+ opacity: 0;
341
+ transition: opacity var(--kit-duration-instant) var(--kit-easing-standard);
342
+ }
343
+
344
+ :where([data-kit="data-grid-sort"]:hover [data-kit-slot="sort-icon"]) {
345
+ opacity: 0.5;
346
+ }
347
+
348
+ :where([data-kit="data-grid-header-cell"][data-sorted] [data-kit-slot="sort-icon"]) {
349
+ opacity: 1;
350
+ }
351
+
352
+ :where([data-kit-slot="sort-rank"]) {
353
+ flex: none;
354
+ color: var(--kit-color-text-secondary);
355
+ font-size: var(--kit-text-caption-size);
356
+ font-variant-numeric: tabular-nums;
357
+ }
358
+
359
+ :where([data-kit-slot="filter-trigger"], [data-kit-slot="menu-trigger"]) {
360
+ flex: none;
361
+ }
362
+
363
+ /* ---------------------------------------------------------- Column resize */
364
+
365
+ :where([data-kit="data-grid-resizer"]) {
366
+ position: absolute;
367
+ inset-block: 0;
368
+ inset-inline-end: 0;
369
+ inline-size: var(--kit-space-2);
370
+ cursor: col-resize;
371
+ touch-action: none;
372
+ }
373
+
374
+ :where([data-kit="data-grid-resizer"])::after {
375
+ content: "";
376
+ position: absolute;
377
+ inset-block: var(--kit-space-1);
378
+ inset-inline-end: 0;
379
+ inline-size: var(--kit-border-width-default);
380
+ background-color: var(--kit-color-border-default);
381
+ transition: background-color var(--kit-duration-instant) var(--kit-easing-standard);
382
+ }
383
+
384
+ :where([data-kit="data-grid-resizer"]:hover, [data-kit="data-grid-resizer"][data-active])::after {
385
+ inline-size: var(--kit-border-width-emphasis);
386
+ background-color: var(--kit-color-border-focus);
387
+ }
388
+
389
+ :where([data-kit="data-grid-resizer"]):focus-visible {
390
+ outline: var(--_focus-ring);
391
+ outline-offset: calc(var(--kit-border-width-focus) * -1);
392
+ }
393
+
394
+ /* ------------------------------------------------------ Column drag reorder */
395
+
396
+ :where([data-kit="data-grid-header-cell"][draggable="true"]) {
397
+ cursor: grab;
398
+ }
399
+
400
+ :where([data-kit="data-grid-header-cell"][data-dragging]) {
401
+ opacity: 0.5;
402
+ }
403
+
404
+ /* A bar on the side the dragged column would land on. It follows the reading direction. */
405
+ :where([data-kit="data-grid-header-cell"][data-drop])::before {
406
+ content: "";
407
+ position: absolute;
408
+ inset-block: 0;
409
+ inline-size: var(--kit-border-width-emphasis);
410
+ background-color: var(--kit-color-accent-default);
411
+ z-index: var(--kit-z-sticky);
412
+ }
413
+
414
+ :where([data-kit="data-grid-header-cell"][data-drop="before"])::before {
415
+ inset-inline-start: 0;
416
+ }
417
+
418
+ :where([data-kit="data-grid-header-cell"][data-drop="after"])::before {
419
+ inset-inline-end: 0;
420
+ }
421
+
422
+ /* ------------------------------------------------------------- Cell types */
423
+
424
+ :where([data-kit="data-grid-boolean"]) {
425
+ display: inline-flex;
426
+ align-items: center;
427
+ }
428
+
429
+ :where([data-kit="data-grid-boolean"][data-value="true"]) {
430
+ color: var(--kit-color-chart-good);
431
+ }
432
+
433
+ :where([data-kit="data-grid-boolean"][data-value="false"]) {
434
+ color: var(--kit-color-text-tertiary);
435
+ }
436
+
437
+ :where([data-kit="data-grid-link"]) {
438
+ min-inline-size: 0;
439
+ overflow: hidden;
440
+ color: var(--kit-color-text-link);
441
+ text-decoration: underline;
442
+ text-overflow: ellipsis;
443
+ text-underline-offset: var(--kit-space-0-5);
444
+ }
445
+
446
+ :where([data-kit="data-grid-link"]:hover) {
447
+ text-decoration-thickness: var(--kit-border-width-emphasis);
448
+ }
449
+
450
+ :where([data-kit="data-grid-link"]):focus-visible {
451
+ outline: var(--_focus-ring);
452
+ outline-offset: var(--kit-space-0-5);
453
+ }
454
+
455
+ :where([data-kit="data-grid-tags"]) {
456
+ display: inline-flex;
457
+ align-items: center;
458
+ gap: var(--kit-space-1);
459
+ min-inline-size: 0;
460
+ overflow: hidden;
461
+ }
462
+
463
+ :where([data-kit="data-grid-progress"]) {
464
+ display: flex;
465
+ align-items: center;
466
+ gap: var(--kit-space-2);
467
+ inline-size: 100%;
468
+ min-inline-size: 0;
469
+ }
470
+
471
+ :where([data-kit="data-grid-progress-track"]) {
472
+ flex: 1 1 auto;
473
+ min-inline-size: var(--kit-size-24);
474
+ block-size: var(--kit-space-2);
475
+ overflow: hidden;
476
+ border-radius: var(--kit-radius-pill);
477
+ background-color: color-mix(in srgb, var(--kit-color-text-primary) 12%, transparent);
478
+ }
479
+
480
+ :where([data-kit="data-grid-progress-fill"]) {
481
+ display: block;
482
+ block-size: 100%;
483
+ border-radius: inherit;
484
+ background-color: var(--kit-color-accent-default);
485
+ }
486
+
487
+ :where([data-kit="data-grid-progress-text"]) {
488
+ flex: none;
489
+ color: var(--kit-color-text-secondary);
490
+ font-size: var(--kit-text-caption-size);
491
+ font-variant-numeric: tabular-nums;
492
+ }
493
+
494
+ :where([data-kit="data-grid-avatar-cell"]) {
495
+ display: inline-flex;
496
+ align-items: center;
497
+ gap: var(--kit-space-2);
498
+ min-inline-size: 0;
499
+ }
500
+
501
+ :where([data-kit="data-grid-avatar"]) {
502
+ display: inline-flex;
503
+ flex: none;
504
+ align-items: center;
505
+ justify-content: center;
506
+ inline-size: var(--kit-size-24);
507
+ block-size: var(--kit-size-24);
508
+ border-radius: var(--kit-radius-full);
509
+ background-color: var(--kit-color-accent-subtle);
510
+ color: var(--kit-color-text-primary);
511
+ font-size: var(--kit-text-caption-size);
512
+ font-weight: var(--kit-font-weight-semibold);
513
+ line-height: 1;
514
+ }
515
+
516
+ :where([data-kit="data-grid-sparkline"]) {
517
+ inline-size: 100%;
518
+ block-size: var(--kit-size-20);
519
+ overflow: visible;
520
+ }
521
+
522
+ :where([data-kit="data-grid-sparkline"] polyline) {
523
+ stroke: var(--kit-color-accent-default);
524
+ stroke-width: var(--kit-border-width-emphasis);
525
+ stroke-linecap: round;
526
+ stroke-linejoin: round;
527
+ vector-effect: non-scaling-stroke;
528
+ }
529
+
530
+ /* Group toggle and row expander: the chevron mirrors in right-to-left. */
531
+ :where([data-kit="data-grid-group-toggle"]) {
532
+ display: inline-flex;
533
+ align-items: center;
534
+ gap: var(--kit-space-1);
535
+ min-block-size: var(--kit-size-target-min);
536
+ min-inline-size: 0;
537
+ font-weight: var(--kit-font-weight-semibold);
538
+ }
539
+
540
+ :where([data-kit-slot="group-label"]) {
541
+ min-inline-size: 0;
542
+ overflow: hidden;
543
+ text-overflow: ellipsis;
544
+ }
545
+
546
+ :where([data-flip]) {
547
+ display: inline-flex;
548
+ }
549
+
550
+ :where([data-flip]):dir(rtl) {
551
+ transform: scaleX(-1);
552
+ }
553
+
554
+ /* ------------------------------------------------------- Detail and totals */
555
+
556
+ :where([data-kit="data-grid-detail"]) {
557
+ display: block;
558
+ inline-size: 100%;
559
+ }
560
+
561
+ :where([data-kit-slot="detail-content"]) {
562
+ position: sticky;
563
+ inset-inline-start: 0;
564
+ padding-block: var(--kit-space-3);
565
+ padding-inline: var(--kit-space-4);
566
+ background-color: var(--_surface);
567
+ white-space: normal;
568
+ }
569
+
570
+ /* ----------------------------------------------------------------- Editing */
571
+
572
+ :where([data-kit="data-grid-cell"][data-editable]) {
573
+ cursor: cell;
574
+ }
575
+
576
+ :where([data-kit="data-grid-cell"][data-editing]) {
577
+ padding-inline: 0;
578
+ overflow: visible;
579
+ --_cell-bg: var(--_surface);
580
+ }
581
+
582
+ :where([data-kit="data-grid-cell"][data-editing] > :is([data-kit="data-grid-input"], [data-kit="data-grid-select"])) {
583
+ inline-size: 100%;
584
+ block-size: 100%;
585
+ border-radius: 0;
586
+ }
587
+
588
+ :where([data-kit="data-grid-edit-error"]) {
589
+ position: absolute;
590
+ inset-block-start: 100%;
591
+ inset-inline-start: 0;
592
+ z-index: var(--kit-z-dropdown);
593
+ max-inline-size: 100%;
594
+ padding-block: var(--kit-space-1);
595
+ padding-inline: var(--kit-space-2);
596
+ border: var(--kit-border-width-default) solid var(--kit-color-status-danger-border);
597
+ border-radius: var(--kit-radius-control);
598
+ background-color: var(--kit-color-status-danger-background);
599
+ color: var(--kit-color-status-danger-foreground);
600
+ font-size: var(--kit-text-caption-size);
601
+ line-height: var(--kit-text-caption-line-height);
602
+ white-space: normal;
603
+ box-shadow: var(--kit-shadow-raised);
604
+ }
605
+
606
+ /* An edit that has been made but not yet confirmed shows a corner dot. */
607
+ :where([data-kit="data-grid-cell"][data-dirty])::after {
608
+ content: "";
609
+ position: absolute;
610
+ inset-block-start: var(--kit-space-0-5);
611
+ inset-inline-start: var(--kit-space-0-5);
612
+ inline-size: var(--kit-space-1);
613
+ block-size: var(--kit-space-1);
614
+ border-radius: var(--kit-radius-full);
615
+ background-color: var(--kit-color-status-info-border);
616
+ }
617
+
618
+ :where([data-kit="data-grid-cell"][data-pending]) {
619
+ opacity: 0.6;
620
+ }
621
+
622
+ :where([data-kit="data-grid-cell"][data-error]) {
623
+ --_cell-bg: var(--kit-color-status-danger-background);
624
+
625
+ box-shadow: inset 0 0 0 var(--kit-border-width-default) var(--kit-color-status-danger-border);
626
+ }
627
+
628
+ /* ------------------------------------------------------------ Loading rows */
629
+
630
+ :where([data-kit="data-grid-skeleton"]) {
631
+ display: block;
632
+ inline-size: 60%;
633
+ block-size: var(--kit-space-3);
634
+ border-radius: var(--kit-radius-pill);
635
+ background-color: color-mix(in srgb, var(--kit-color-text-primary) 10%, transparent);
636
+ animation: data-grid-pulse var(--kit-duration-slow) var(--kit-easing-standard) infinite alternate;
637
+ }
638
+
639
+ /* A block that failed to load: the bar stops pulsing, since nothing is coming. */
640
+ :where([data-kit="data-grid-row"][data-failed] [data-kit="data-grid-skeleton"]) {
641
+ background-color: color-mix(in srgb, var(--kit-color-status-danger-border) 45%, transparent);
642
+ animation: none;
643
+ }
644
+
645
+ @keyframes data-grid-pulse {
646
+ from {
647
+ opacity: 1;
648
+ }
649
+
650
+ to {
651
+ opacity: 0.45;
652
+ }
653
+ }
654
+
655
+ /* Rows kept while fresh data loads stay readable but look provisional. */
656
+ :where([data-kit="data-grid"][data-stale] [data-kit="data-grid-body"]) {
657
+ opacity: 0.6;
658
+ transition: opacity var(--kit-duration-fast) var(--kit-easing-standard);
659
+ }
660
+
661
+ :where([data-kit="data-grid-progressbar"]) {
662
+ position: absolute;
663
+ inset-block-start: 0;
664
+ inset-inline: 0;
665
+ z-index: var(--kit-z-overlay);
666
+ block-size: var(--kit-space-0-5);
667
+ overflow: hidden;
668
+ background-color: color-mix(in srgb, var(--kit-color-accent-default) 20%, transparent);
669
+ pointer-events: none;
670
+ }
671
+
672
+ :where([data-kit="data-grid-progressbar"])::after {
673
+ content: "";
674
+ position: absolute;
675
+ inset-block: 0;
676
+ inline-size: 40%;
677
+ background-color: var(--kit-color-accent-default);
678
+ animation: data-grid-progress var(--kit-duration-slow) var(--kit-easing-standard) infinite alternate;
679
+ }
680
+
681
+ @keyframes data-grid-progress {
682
+ from {
683
+ inset-inline-start: 0;
684
+ }
685
+
686
+ to {
687
+ inset-inline-start: 60%;
688
+ }
689
+ }
690
+
691
+ /* ---------------------------------------------------------------- Overlays */
692
+
693
+ :where([data-kit="data-grid-overlay"]) {
694
+ position: absolute;
695
+ inset-inline: 0;
696
+ inset-block-end: 0;
697
+ z-index: var(--kit-z-sticky);
698
+ display: flex;
699
+ align-items: center;
700
+ justify-content: center;
701
+ padding: var(--kit-space-4);
702
+ pointer-events: none;
703
+ }
704
+
705
+ :where([data-kit="data-grid-overlay"] > *) {
706
+ pointer-events: auto;
707
+ }
708
+
709
+ :where([data-kit="data-grid-overlay"][data-state="loading"]) {
710
+ background-color: color-mix(in srgb, var(--_surface) 70%, transparent);
711
+ }
712
+
713
+ :where([data-kit="data-grid-overlay"][data-state="error"][data-placement="banner"]) {
714
+ inset-block-start: auto;
715
+ justify-content: stretch;
716
+ padding: var(--kit-space-2);
717
+ }
718
+
719
+ :where([data-kit="data-grid-loading"], [data-kit="data-grid-empty"], [data-kit="data-grid-error"]) {
720
+ display: flex;
721
+ flex-direction: column;
722
+ align-items: center;
723
+ gap: var(--kit-space-3);
724
+ padding: var(--kit-space-4);
725
+ color: var(--kit-color-text-secondary);
726
+ text-align: center;
727
+ }
728
+
729
+ :where([data-kit="data-grid-error"]) {
730
+ border: var(--kit-border-width-default) solid var(--kit-color-status-danger-border);
731
+ border-radius: var(--kit-radius-panel);
732
+ background-color: var(--kit-color-status-danger-background);
733
+ color: var(--kit-color-status-danger-foreground);
734
+ }
735
+
736
+ :where([data-kit="data-grid-overlay"][data-placement="banner"] [data-kit="data-grid-error"]) {
737
+ flex: 1 1 auto;
738
+ flex-direction: row;
739
+ justify-content: space-between;
740
+ box-shadow: var(--kit-shadow-raised);
741
+ text-align: start;
742
+ }
743
+
744
+ /* ------------------------------------------------------------- Form fields */
745
+
746
+ :where([data-kit="data-grid-input"], [data-kit="data-grid-select"]) {
747
+ min-inline-size: 0;
748
+ min-block-size: var(--kit-size-control-sm);
749
+ padding-block: 0;
750
+ padding-inline: var(--kit-space-2);
751
+ border: var(--kit-border-width-default) solid var(--kit-color-border-default);
752
+ border-radius: var(--kit-radius-control);
753
+ background-color: var(--kit-color-bg-surface);
754
+ color: var(--kit-color-text-primary);
755
+ font-family: inherit;
756
+ font-size: var(--kit-text-body-size);
757
+ line-height: var(--kit-text-body-line-height);
758
+ }
759
+
760
+ :where([data-kit="data-grid-input"]:hover, [data-kit="data-grid-select"]:hover) {
761
+ border-color: var(--kit-color-border-strong);
762
+ }
763
+
764
+ :where([data-kit="data-grid-input"], [data-kit="data-grid-select"]):focus-visible {
765
+ outline: var(--_focus-ring);
766
+ outline-offset: calc(var(--kit-border-width-focus) * -1);
767
+ }
768
+
769
+ :where([data-kit="data-grid-input"][aria-invalid="true"], [data-kit="data-grid-select"][aria-invalid="true"]) {
770
+ border-color: var(--kit-color-status-danger-border);
771
+ }
772
+
773
+ :where([data-kit="data-grid-input"])::placeholder {
774
+ color: var(--kit-color-text-tertiary);
775
+ }
776
+
777
+ :where([data-kit="data-grid-input"])::-webkit-search-cancel-button {
778
+ appearance: none;
779
+ }
780
+
781
+ :where([data-kit="data-grid-checkbox"]) {
782
+ flex: none;
783
+ inline-size: var(--kit-size-icon-md);
784
+ block-size: var(--kit-size-icon-md);
785
+ /* Margin brings the hit area to the minimum target size. */
786
+ margin: var(--kit-space-0-5);
787
+ accent-color: var(--kit-color-accent-default);
788
+ cursor: pointer;
789
+ }
790
+
791
+ :where([data-kit="data-grid-checkbox"]):focus-visible {
792
+ outline: var(--_focus-ring);
793
+ outline-offset: var(--kit-space-0-5);
794
+ }
795
+
796
+ /* ----------------------------------------------------------------- Toolbar */
797
+
798
+ :where([data-kit="data-grid-toolbar"]) {
799
+ display: flex;
800
+ flex-wrap: wrap;
801
+ align-items: center;
802
+ gap: var(--kit-space-2);
803
+ padding-block: var(--kit-space-2);
804
+ padding-inline: var(--kit-space-3);
805
+ border-block-end: var(--kit-border-width-default) solid var(--kit-color-border-subtle);
806
+ }
807
+
808
+ :where([data-kit-slot="search"]) {
809
+ position: relative;
810
+ display: flex;
811
+ flex: 1 1 auto;
812
+ align-items: center;
813
+ min-inline-size: calc(var(--kit-size-56) * 3);
814
+ max-inline-size: calc(var(--kit-size-56) * 6);
815
+ }
816
+
817
+ :where([data-kit-slot="search"] > [data-kit="data-grid-input"]) {
818
+ flex: 1 1 auto;
819
+ min-block-size: var(--kit-size-control-md);
820
+ padding-inline-start: calc(var(--kit-space-2) + var(--kit-size-icon-sm) + var(--kit-space-2));
821
+ padding-inline-end: calc(var(--kit-size-control-xs) + var(--kit-space-1));
822
+ }
823
+
824
+ :where([data-kit-slot="search-icon"]) {
825
+ position: absolute;
826
+ inset-inline-start: var(--kit-space-2);
827
+ display: inline-flex;
828
+ color: var(--kit-color-text-tertiary);
829
+ pointer-events: none;
830
+ }
831
+
832
+ :where([data-kit-slot="search"] > [data-kit="button"], [data-kit-slot="search"] > button) {
833
+ position: absolute;
834
+ inset-inline-end: var(--kit-space-0-5);
835
+ }
836
+
837
+ :where([data-kit-slot="selection"], [data-kit-slot="toolbar-start"], [data-kit-slot="toolbar-end"]) {
838
+ display: inline-flex;
839
+ align-items: center;
840
+ gap: var(--kit-space-2);
841
+ }
842
+
843
+ :where([data-kit-slot="selection-count"]) {
844
+ color: var(--kit-color-text-secondary);
845
+ font-size: var(--kit-text-label-size);
846
+ font-weight: var(--kit-text-label-weight);
847
+ }
848
+
849
+ :where([data-kit-slot="toolbar-actions"]) {
850
+ display: flex;
851
+ flex-wrap: wrap;
852
+ align-items: center;
853
+ gap: var(--kit-space-2);
854
+ margin-inline-start: auto;
855
+ }
856
+
857
+ /* ------------------------------------------------------------ Filter chips */
858
+
859
+ :where([data-kit="data-grid-chips"]) {
860
+ display: flex;
861
+ flex-wrap: wrap;
862
+ align-items: center;
863
+ gap: var(--kit-space-2);
864
+ margin: 0;
865
+ padding-block: var(--kit-space-2);
866
+ padding-inline: var(--kit-space-3);
867
+ border-block-end: var(--kit-border-width-default) solid var(--kit-color-border-subtle);
868
+ list-style: none;
869
+ }
870
+
871
+ :where([data-kit="data-grid-chip"]) {
872
+ display: inline-flex;
873
+ align-items: center;
874
+ gap: var(--kit-space-1);
875
+ min-block-size: var(--kit-size-control-xs);
876
+ padding-inline: var(--kit-space-2) var(--kit-space-0-5);
877
+ border: var(--kit-border-width-default) solid var(--kit-color-border-default);
878
+ border-radius: var(--kit-radius-pill);
879
+ background-color: var(--kit-color-accent-subtle);
880
+ color: var(--kit-color-text-primary);
881
+ font-size: var(--kit-text-label-size);
882
+ line-height: var(--kit-text-label-line-height);
883
+ }
884
+
885
+ :where([data-kit="data-grid-chip"][data-kind="group"]) {
886
+ background-color: color-mix(in srgb, var(--kit-color-text-primary) 6%, transparent);
887
+ }
888
+
889
+ /* -------------------------------------------------------------- Pagination */
890
+
891
+ :where([data-kit="data-grid-pagination"]) {
892
+ display: flex;
893
+ flex-wrap: wrap;
894
+ align-items: center;
895
+ gap: var(--kit-space-3);
896
+ padding-block: var(--kit-space-2);
897
+ padding-inline: var(--kit-space-3);
898
+ border-block-start: var(--kit-border-width-default) solid var(--kit-color-border-subtle);
899
+ color: var(--kit-color-text-secondary);
900
+ font-size: var(--kit-text-label-size);
901
+ line-height: var(--kit-text-label-line-height);
902
+ }
903
+
904
+ :where([data-kit-slot="page-size"]) {
905
+ display: inline-flex;
906
+ align-items: center;
907
+ gap: var(--kit-space-2);
908
+ }
909
+
910
+ :where([data-kit-slot="range"]) {
911
+ font-variant-numeric: tabular-nums;
912
+ }
913
+
914
+ :where([data-kit-slot="buttons"]) {
915
+ display: inline-flex;
916
+ align-items: center;
917
+ gap: var(--kit-space-1);
918
+ margin-inline-start: auto;
919
+ }
920
+
921
+ :where([data-kit-slot="status"]) {
922
+ padding-inline: var(--kit-space-2);
923
+ font-variant-numeric: tabular-nums;
924
+ }
925
+
926
+ /* ------------------------------------------------- Popover, menu, filter UI */
927
+
928
+ :where([data-kit="data-grid-popover"]) {
929
+ position: fixed;
930
+ inset: auto;
931
+ z-index: var(--kit-z-dropdown);
932
+ inline-size: max-content;
933
+ min-inline-size: calc(var(--kit-size-56) * 3);
934
+ max-inline-size: 100%;
935
+ margin: 0;
936
+ padding: var(--kit-space-3);
937
+ overflow: auto;
938
+ border: var(--kit-border-width-default) solid var(--kit-color-border-default);
939
+ border-radius: var(--kit-radius-overlay);
940
+ background-color: var(--kit-color-bg-overlay);
941
+ color: var(--kit-color-text-primary);
942
+ font-family: var(--kit-font-family-sans);
943
+ font-size: var(--kit-text-body-size);
944
+ line-height: var(--kit-text-body-line-height);
945
+ box-shadow: var(--kit-shadow-overlay);
946
+ }
947
+
948
+ :where([data-kit="data-grid-popover"][data-role="menu"]) {
949
+ padding: var(--kit-space-1);
950
+ }
951
+
952
+ :where([data-kit="data-grid-popover"]):focus-visible {
953
+ outline: var(--_focus-ring);
954
+ }
955
+
956
+ :where([data-kit="data-grid-menu"]) {
957
+ display: flex;
958
+ flex-direction: column;
959
+ }
960
+
961
+ :where([data-kit="data-grid-menu-entry"][data-separator]) {
962
+ margin-block-start: var(--kit-space-1);
963
+ padding-block-start: var(--kit-space-1);
964
+ border-block-start: var(--kit-border-width-default) solid var(--kit-color-border-subtle);
965
+ }
966
+
967
+ :where([data-kit="data-grid-menu-item"]) {
968
+ display: flex;
969
+ align-items: center;
970
+ gap: var(--kit-space-2);
971
+ inline-size: 100%;
972
+ min-block-size: var(--kit-size-control-md);
973
+ padding-inline: var(--kit-space-2);
974
+ white-space: nowrap;
975
+ }
976
+
977
+ :where([data-kit="data-grid-menu-item"]:hover:not([aria-disabled="true"])) {
978
+ background-color: color-mix(in srgb, var(--kit-color-text-primary) 8%, transparent);
979
+ }
980
+
981
+ :where([data-kit="data-grid-menu-item"][aria-disabled="true"]) {
982
+ color: var(--kit-color-text-disabled);
983
+ cursor: not-allowed;
984
+ }
985
+
986
+ :where([data-kit="data-grid-menu-item"][data-danger]) {
987
+ color: var(--kit-color-status-danger-foreground);
988
+ }
989
+
990
+ :where([data-kit-slot="menu-check"]) {
991
+ display: inline-flex;
992
+ flex: none;
993
+ inline-size: var(--kit-size-icon-sm);
994
+ block-size: var(--kit-size-icon-sm);
995
+ }
996
+
997
+ :where([data-kit-slot="menu-label"]) {
998
+ min-inline-size: 0;
999
+ overflow: hidden;
1000
+ text-overflow: ellipsis;
1001
+ }
1002
+
1003
+ :where([data-kit="data-grid-filter"]) {
1004
+ display: flex;
1005
+ flex-direction: column;
1006
+ gap: var(--kit-space-3);
1007
+ min-inline-size: calc(var(--kit-size-56) * 4);
1008
+ }
1009
+
1010
+ :where([data-kit="data-grid-field"]) {
1011
+ display: flex;
1012
+ flex: 1 1 auto;
1013
+ flex-direction: column;
1014
+ gap: var(--kit-space-1);
1015
+ }
1016
+
1017
+ :where([data-kit-slot="field-label"]) {
1018
+ color: var(--kit-color-text-secondary);
1019
+ font-size: var(--kit-text-caption-size);
1020
+ font-weight: var(--kit-text-label-weight);
1021
+ line-height: var(--kit-text-caption-line-height);
1022
+ }
1023
+
1024
+ :where([data-kit="data-grid-range"]) {
1025
+ display: flex;
1026
+ gap: var(--kit-space-2);
1027
+ }
1028
+
1029
+ :where([data-kit="data-grid-choices"]) {
1030
+ display: flex;
1031
+ flex-direction: column;
1032
+ gap: var(--kit-space-1);
1033
+ max-block-size: calc(var(--kit-size-56) * 3);
1034
+ overflow: auto;
1035
+ }
1036
+
1037
+ :where([data-kit="data-grid-choice"]) {
1038
+ display: flex;
1039
+ align-items: center;
1040
+ gap: var(--kit-space-2);
1041
+ min-block-size: var(--kit-size-target-min);
1042
+ cursor: pointer;
1043
+ }
1044
+
1045
+ :where([data-kit="data-grid-hint"]) {
1046
+ color: var(--kit-color-text-tertiary);
1047
+ font-size: var(--kit-text-caption-size);
1048
+ }
1049
+
1050
+ :where([data-kit="data-grid-filter-actions"]) {
1051
+ display: flex;
1052
+ justify-content: flex-end;
1053
+ gap: var(--kit-space-2);
1054
+ }
1055
+
1056
+ /* --------------------------------------------------------- Reduced motion */
1057
+
1058
+ @media (prefers-reduced-motion: reduce) {
1059
+ :where([data-kit="data-grid"] *, [data-kit="data-grid-popover"] *) {
1060
+ transition: none;
1061
+ }
1062
+
1063
+ :where([data-kit="data-grid-skeleton"]) {
1064
+ animation: none;
1065
+ }
1066
+
1067
+ /* A still bar says "busy" just as well as a moving one. */
1068
+ :where([data-kit="data-grid-progressbar"])::after {
1069
+ inline-size: 100%;
1070
+ animation: none;
1071
+ opacity: 0.6;
1072
+ }
1073
+ }
1074
+
1075
+ /* ----------------------------------------------------------- Forced colors */
1076
+
1077
+ @media (forced-colors: active) {
1078
+ :where([data-kit="data-grid"]) {
1079
+ border-color: CanvasText;
1080
+ --_surface: Canvas;
1081
+ --_header-bg: Canvas;
1082
+ --_hover-bg: Canvas;
1083
+ --_group-bg: Canvas;
1084
+ --_selected-bg: Highlight;
1085
+ --_focus-ring: var(--kit-border-width-focus) solid Highlight;
1086
+ }
1087
+
1088
+ /* Shadows are dropped in forced colors, so the separators become borders. */
1089
+ :where([data-kit="data-grid-header-group"]) {
1090
+ border-block-end: var(--kit-border-width-default) solid CanvasText;
1091
+ }
1092
+
1093
+ :where([data-kit="data-grid-footer-group"]) {
1094
+ border-block-start: var(--kit-border-width-default) solid CanvasText;
1095
+ }
1096
+
1097
+ :where([data-kit="data-grid-cell"], [data-kit="data-grid-spacer"], [data-kit="data-grid-group-header"], [data-kit="data-grid-toolbar"], [data-kit="data-grid-chips"], [data-kit="data-grid-pagination"]) {
1098
+ border-color: GrayText;
1099
+ }
1100
+
1101
+ :where([data-pinned][data-pinned-edge]) {
1102
+ border-color: CanvasText;
1103
+ }
1104
+
1105
+ :where([data-kit="data-grid-row"][data-selected]) {
1106
+ color: HighlightText;
1107
+ }
1108
+
1109
+ :where([data-kit="data-grid-row"][data-selected] [data-kit="data-grid-link"]) {
1110
+ color: HighlightText;
1111
+ }
1112
+
1113
+ :where([data-kit="data-grid-row"][data-selected]:hover) {
1114
+ --_row-bg: Highlight;
1115
+ }
1116
+
1117
+ :where([data-kit="data-grid-cell"][data-error]) {
1118
+ --_cell-bg: Canvas;
1119
+
1120
+ box-shadow: inset 0 0 0 var(--kit-border-width-emphasis) Mark;
1121
+ }
1122
+
1123
+ :where([data-kit="data-grid-cell"][data-dirty])::after {
1124
+ background-color: CanvasText;
1125
+ }
1126
+
1127
+ :where([data-kit="data-grid-skeleton"]) {
1128
+ background-color: GrayText;
1129
+ }
1130
+
1131
+ :where([data-kit="data-grid-progress-track"]) {
1132
+ border: var(--kit-border-width-default) solid CanvasText;
1133
+ background-color: Canvas;
1134
+ }
1135
+
1136
+ :where([data-kit="data-grid-progress-fill"]) {
1137
+ background-color: Highlight;
1138
+ }
1139
+
1140
+ :where([data-kit="data-grid-progressbar"])::after {
1141
+ background-color: Highlight;
1142
+ }
1143
+
1144
+ :where([data-kit="data-grid-resizer"])::after {
1145
+ background-color: CanvasText;
1146
+ }
1147
+
1148
+ :where([data-kit="data-grid-header-cell"][data-drop])::before {
1149
+ background-color: Highlight;
1150
+ }
1151
+
1152
+ :where([data-kit="data-grid-sparkline"] polyline) {
1153
+ stroke: CanvasText;
1154
+ }
1155
+
1156
+ :where([data-kit="data-grid-popover"], [data-kit="data-grid-error"], [data-kit="data-grid-chip"], [data-kit="data-grid-edit-error"]) {
1157
+ border-color: CanvasText;
1158
+ box-shadow: none;
1159
+ }
1160
+
1161
+ :where([data-kit="data-grid-menu-item"]:hover:not([aria-disabled="true"])) {
1162
+ background-color: Highlight;
1163
+ color: HighlightText;
1164
+ }
1165
+
1166
+ :where([data-kit="data-grid-menu-item"][aria-disabled="true"]) {
1167
+ color: GrayText;
1168
+ }
1169
+ }