@slotted/styles 0.1.0-beta.7 → 0.1.0-beta.9

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 (128) hide show
  1. package/package.json +1 -1
  2. package/src/accordion/accordion.css +10 -10
  3. package/src/action-bar/action-bar.css +31 -32
  4. package/src/action-sheet/action-sheet.css +36 -36
  5. package/src/alert/alert.css +35 -35
  6. package/src/app-shell/app-shell.css +280 -299
  7. package/src/aspect-ratio/aspect-ratio.css +9 -9
  8. package/src/attachment/attachment.css +91 -99
  9. package/src/avatar/avatar.css +41 -41
  10. package/src/avatar-group/avatar-group.css +21 -22
  11. package/src/badge/badge.css +37 -37
  12. package/src/breadcrumb/breadcrumb.css +37 -37
  13. package/src/button/button.css +88 -69
  14. package/src/button-group/button-group.css +69 -73
  15. package/src/calendar/calendar.css +93 -103
  16. package/src/card/card.css +54 -61
  17. package/src/carousel/carousel.css +150 -161
  18. package/src/cascader/cascader.css +147 -151
  19. package/src/chart/chart.css +225 -240
  20. package/src/checkbox/checkbox.css +119 -124
  21. package/src/checkbox-group/checkbox-group.css +7 -7
  22. package/src/code-block/code-block.css +81 -85
  23. package/src/collapsible/collapsible.css +69 -76
  24. package/src/color-picker/color-picker.css +83 -91
  25. package/src/column-manager/column-manager.css +106 -114
  26. package/src/combobox/combobox.css +99 -101
  27. package/src/command-palette/command-palette.css +84 -90
  28. package/src/container/container.css +24 -24
  29. package/src/context-menu/context-menu.css +8 -8
  30. package/src/currency-field/currency-field.css +99 -104
  31. package/src/dashboard-grid/dashboard-grid.css +104 -107
  32. package/src/data-grid/data-grid.css +458 -456
  33. package/src/data-grid/data-grid.tokens.json +2 -0
  34. package/src/data-list/data-list.css +67 -69
  35. package/src/date-field/date-field.css +50 -50
  36. package/src/date-picker/date-picker.css +40 -42
  37. package/src/date-range-picker/date-range-picker.css +114 -118
  38. package/src/datetime-field/datetime-field.css +73 -78
  39. package/src/datetime-picker/datetime-picker.css +61 -63
  40. package/src/datetime-range-picker/datetime-range-picker.css +149 -156
  41. package/src/description-list/description-list.css +61 -64
  42. package/src/detail-panel/detail-panel.css +70 -70
  43. package/src/dialog/dialog.css +312 -148
  44. package/src/divider/divider.css +18 -18
  45. package/src/drawer/drawer.css +186 -209
  46. package/src/entity-picker/entity-picker.css +220 -239
  47. package/src/event-calendar/event-calendar.css +343 -385
  48. package/src/field/field.css +74 -78
  49. package/src/field-group/field-group.css +22 -25
  50. package/src/filter-bar/filter-bar.css +193 -209
  51. package/src/form/form.css +21 -24
  52. package/src/fullscreen/fullscreen.css +24 -25
  53. package/src/grid/grid.css +28 -28
  54. package/src/highlight/highlight.css +6 -6
  55. package/src/hover-card/hover-card.css +6 -6
  56. package/src/icon/icon.css +15 -15
  57. package/src/image/image.css +39 -39
  58. package/src/import-export-center/import-export-center.css +135 -156
  59. package/src/inline/inline.css +27 -27
  60. package/src/inline-message/inline-message.css +28 -28
  61. package/src/kbd/kbd.css +26 -26
  62. package/src/link/link.css +15 -15
  63. package/src/list/list.css +20 -20
  64. package/src/list-item/list-item.css +66 -66
  65. package/src/listbox/listbox.css +56 -59
  66. package/src/loading-overlay/loading-overlay.css +75 -92
  67. package/src/markdown/markdown.css +17 -17
  68. package/src/menu/menu.css +63 -65
  69. package/src/menubar/menubar.css +13 -13
  70. package/src/message/message.css +174 -202
  71. package/src/message-scroller/message-scroller.css +41 -42
  72. package/src/multi-select/multi-select.css +131 -137
  73. package/src/navigation-menu/navigation-menu.css +167 -188
  74. package/src/notification-center/notification-center.css +134 -148
  75. package/src/number-field/number-field.css +76 -81
  76. package/src/otp-input/otp-input.css +48 -48
  77. package/src/page/page.css +23 -23
  78. package/src/page-header/page-header.css +219 -280
  79. package/src/pagination/pagination.css +68 -72
  80. package/src/popover/popover.css +40 -49
  81. package/src/progress-indicator/progress-indicator.css +85 -90
  82. package/src/prompt-composer/prompt-composer.css +94 -99
  83. package/src/prose/prose.css +71 -75
  84. package/src/radio-group/radio-group.css +98 -103
  85. package/src/rating/rating.css +132 -132
  86. package/src/result-state/result-state.css +74 -77
  87. package/src/saved-views/saved-views.css +41 -47
  88. package/src/scroll-area/scroll-area.css +32 -35
  89. package/src/section/section.css +16 -16
  90. package/src/segmented-control/segmented-control.css +77 -79
  91. package/src/select/select.css +113 -115
  92. package/src/side-navigation/side-navigation.css +170 -180
  93. package/src/skeleton/skeleton.css +47 -48
  94. package/src/slider/slider.css +86 -88
  95. package/src/sparkline/sparkline.css +32 -32
  96. package/src/spinner/spinner.css +4 -4
  97. package/src/split-button/split-button.css +26 -31
  98. package/src/splitter/splitter.css +35 -35
  99. package/src/stack/stack.css +24 -24
  100. package/src/stat-card/stat-card.css +102 -103
  101. package/src/status-indicator/status-indicator.css +28 -28
  102. package/src/stepper/stepper.css +58 -62
  103. package/src/switch/switch.css +86 -92
  104. package/src/table/table.css +189 -198
  105. package/src/table-of-contents/table-of-contents.css +51 -54
  106. package/src/tabs/tabs.css +157 -172
  107. package/src/tag/tag.css +67 -71
  108. package/src/tags-input/tags-input.css +124 -74
  109. package/src/tags-input/tags-input.tokens.json +6 -1
  110. package/src/text-field/text-field.css +108 -126
  111. package/src/textarea/textarea.css +26 -26
  112. package/src/time-field/time-field.css +67 -67
  113. package/src/time-picker/time-picker.css +56 -58
  114. package/src/time-range-picker/time-range-picker.css +126 -133
  115. package/src/timeline/timeline.css +244 -266
  116. package/src/toast/toast.css +81 -90
  117. package/src/toggle/toggle.css +29 -33
  118. package/src/toggle-group/toggle-group.css +67 -71
  119. package/src/toolbar/toolbar.css +30 -35
  120. package/src/tooltip/tooltip.css +26 -26
  121. package/src/top-navigation/top-navigation.css +243 -259
  122. package/src/tour/tour.css +51 -60
  123. package/src/transfer/transfer.css +160 -164
  124. package/src/tree/tree.css +103 -111
  125. package/src/typography/typography.css +36 -36
  126. package/src/upload/upload.css +224 -224
  127. package/src/visually-hidden/visually-hidden.css +1 -1
  128. package/src/wizard/wizard.css +185 -197
@@ -16,7 +16,7 @@
16
16
  * indicator, the group and the filter row — is declared after the shared
17
17
  * set.
18
18
  */
19
- [data-ui='data-grid'][data-part='root'] {
19
+ [data-ui-data-grid][data-part-root] {
20
20
  /* Geometry. Every value is the control scale's, so one theme decision
21
21
  retunes the rows, the buttons and the fields together, and
22
22
  `@media (pointer: coarse)` grows all three at once. */
@@ -147,6 +147,13 @@
147
147
  var(--slotted-space-1, 0.125rem) * 2
148
148
  )
149
149
  );
150
+ /* The control scale as the theme states it, read here once: a body row
151
+ restates the scale for what its cells hold (below), and a property
152
+ cannot read its own inherited value. */
153
+ --_control-height-sm: var(--slotted-control-height-sm, 30px);
154
+ --_control-height-md: var(--slotted-control-height-md, 34px);
155
+ --_control-height-lg: var(--slotted-control-height-lg, 38px);
156
+ --_target-min: var(--slotted-target-min, 24px);
150
157
  /* Its glyph keeps two pixels of air inside the control's ground, so at
151
158
  dense — a 17-pixel control in a 25-pixel track — the ground reads as a
152
159
  button and not as a filled cell. */
@@ -183,7 +190,7 @@
183
190
  position: relative;
184
191
  }
185
192
 
186
- [data-ui='data-grid'][data-variant='framed'] {
193
+ [data-ui-data-grid][data-variant='framed'] {
187
194
  border: var(--_rule-width) solid var(--_rule);
188
195
  border-radius: var(--_radius);
189
196
  /* A box standing on the page takes the surface step, as table's frame does. */
@@ -199,7 +206,7 @@
199
206
  * Both axes. It is the window the virtualiser measures, so it takes the room
200
207
  * the frame leaves after the footer and scrolls what does not fit.
201
208
  */
202
- [data-ui='data-grid'] > [data-part='scroll'] {
209
+ [data-ui-data-grid] > [data-part-scroll] {
203
210
  /* The container a detail row, a group row and the empty state measure
204
211
  their width against: each spans every column of a template that may
205
212
  be wider than the frame, and `100cqi` is what holds it to the frame. */
@@ -223,7 +230,7 @@
223
230
  position: relative;
224
231
  }
225
232
 
226
- [data-ui='data-grid'][data-sticky-to='page'] > [data-part='scroll'] {
233
+ [data-ui-data-grid][data-sticky-to='page'] > [data-part-scroll] {
227
234
  overflow: visible;
228
235
  }
229
236
 
@@ -251,14 +258,14 @@
251
258
  other: a widget inside a cell may hold rows of its own — a multi-select's
252
259
  chips are a `row` of a grid pattern — and a descendant selector laid its
253
260
  chips out on this grid's column template. */
254
- [data-ui='data-grid']
255
- > [data-part='scroll']
261
+ [data-ui-data-grid]
262
+ > [data-part-scroll]
256
263
  > :is(
257
- [data-part='head'],
258
- [data-part='body'],
259
- [data-part='pinned-rows'],
260
- [data-part='summary'],
261
- [data-part='loader']
264
+ [data-part-head],
265
+ [data-part-body],
266
+ [data-part-pinned-rows],
267
+ [data-part-summary],
268
+ [data-part-loader]
262
269
  )
263
270
  > [role='row'] {
264
271
  box-sizing: border-box;
@@ -279,7 +286,7 @@
279
286
 
280
287
  /* The rules between rows are the rows' own: a row is a block box, unlike a
281
288
  table row, so its border runs the whole width, filler included. */
282
- [data-ui='data-grid'] [data-part='header-row'] {
289
+ [data-ui-data-grid] [data-part-header-row] {
283
290
  background-color: var(--_head-surface);
284
291
  border-block-end: var(--_rule-width) solid var(--_rule-strong);
285
292
  }
@@ -287,27 +294,27 @@
287
294
  /* A row of column groups stands above the row of names, and the rule
288
295
  between the two is the lighter one; the strong rule is the last header
289
296
  row's, over the values. */
290
- [data-ui='data-grid'] [data-part='header-row']:not(:last-of-type) {
297
+ [data-ui-data-grid] [data-part-header-row]:not(:last-of-type) {
291
298
  border-block-end-color: var(--_rule);
292
299
  }
293
300
 
294
- [data-ui='data-grid'][data-variant='plain'] [data-part='header-row'] {
301
+ [data-ui-data-grid][data-variant='plain'] [data-part-header-row] {
295
302
  background-color: transparent;
296
303
  }
297
304
 
298
- [data-ui='data-grid'] [data-part='filter-row'] {
305
+ [data-ui-data-grid] [data-part-filter-row] {
299
306
  background-color: var(--_band-surface);
300
307
  border-block-end: var(--_rule-width) solid var(--_rule);
301
308
  }
302
309
 
303
- [data-ui='data-grid']
304
- > [data-part='scroll']
310
+ [data-ui-data-grid]
311
+ > [data-part-scroll]
305
312
  > :is(
306
- [data-part='head'],
307
- [data-part='body'],
308
- [data-part='pinned-rows'],
309
- [data-part='summary'],
310
- [data-part='loader']
313
+ [data-part-head],
314
+ [data-part-body],
315
+ [data-part-pinned-rows],
316
+ [data-part-summary],
317
+ [data-part-loader]
311
318
  )
312
319
  > [role='row']
313
320
  > * {
@@ -318,14 +325,14 @@
318
325
  scroller's width with wider rows inside it is a box its own rows overflow,
319
326
  which the page audit reads as a defect and a reader never sees. Sized to
320
327
  the rows, the only thing that scrolls is the scroller. */
321
- [data-ui='data-grid']
322
- > [data-part='scroll']
328
+ [data-ui-data-grid]
329
+ > [data-part-scroll]
323
330
  > :is(
324
- [data-part='head'],
325
- [data-part='body'],
326
- [data-part='pinned-rows'],
327
- [data-part='summary'],
328
- [data-part='loader']
331
+ [data-part-head],
332
+ [data-part-body],
333
+ [data-part-pinned-rows],
334
+ [data-part-summary],
335
+ [data-part-loader]
329
336
  ) {
330
337
  inline-size: fit-content;
331
338
  min-inline-size: 100%;
@@ -342,23 +349,23 @@
342
349
  * `button` inside a `columnheader` would be a widget the cursor has to
343
350
  * enter.
344
351
  */
345
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='head'] {
352
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-head] {
346
353
  inset-block-start: var(--slotted-data-grid-sticky-offset, 0);
347
354
  position: sticky;
348
355
  z-index: calc(var(--slotted-z-index-sticky, 100) + 1);
349
356
  }
350
357
 
351
- [data-ui='data-grid']:not([data-sticky-header]) > [data-part='scroll'] > [data-part='head'] {
358
+ [data-ui-data-grid]:not([data-sticky-header]) > [data-part-scroll] > [data-part-head] {
352
359
  position: static;
353
360
  }
354
361
 
355
- [data-ui='data-grid'] [data-part='column-header'],
356
- [data-ui='data-grid'] [data-part='column-group'],
357
- [data-ui='data-grid']
358
- > [data-part='scroll']
359
- > [data-part='head']
362
+ [data-ui-data-grid] [data-part-column-header],
363
+ [data-ui-data-grid] [data-part-column-group],
364
+ [data-ui-data-grid]
365
+ > [data-part-scroll]
366
+ > [data-part-head]
360
367
  > [role='row']
361
- > [data-part='selection'] {
368
+ > [data-part-selection] {
362
369
  align-items: center;
363
370
  background-color: var(--_head-surface);
364
371
  box-sizing: border-box;
@@ -378,21 +385,21 @@
378
385
  transition: background-color var(--_transition);
379
386
  }
380
387
 
381
- [data-ui='data-grid'][data-variant='plain']
382
- :is([data-part='column-header'], [data-part='column-group']) {
388
+ [data-ui-data-grid][data-variant='plain']
389
+ :is([data-part-column-header], [data-part-column-group]) {
383
390
  background-color: transparent;
384
391
  }
385
392
 
386
393
  /* A group header is centred over the columns it spans and separated from
387
394
  the row of column names by the same rule that separates the names from
388
395
  the values, one step lighter. */
389
- [data-ui='data-grid'] [data-part='column-group'] {
396
+ [data-ui-data-grid] [data-part-column-group] {
390
397
  justify-content: center;
391
398
  }
392
399
 
393
400
  /* The name takes what is left and truncates: a column name is two or three
394
401
  words and its full text is the header's own accessible name. */
395
- [data-ui='data-grid'] [data-part='column-header'] > span:first-child {
402
+ [data-ui-data-grid] [data-part-column-header] > span:first-child {
396
403
  flex: 1 1 auto;
397
404
  min-inline-size: 0;
398
405
  overflow: hidden;
@@ -401,30 +408,30 @@
401
408
  }
402
409
 
403
410
  /* An aligned column keeps its name over its values. */
404
- [data-ui='data-grid'] [data-part='column-header'][data-align='center'] {
411
+ [data-ui-data-grid] [data-part-column-header][data-align='center'] {
405
412
  justify-content: center;
406
413
  }
407
414
 
408
- [data-ui='data-grid'] [data-part='column-header'][data-align='center'] > span:first-child {
415
+ [data-ui-data-grid] [data-part-column-header][data-align='center'] > span:first-child {
409
416
  flex: 0 1 auto;
410
417
  margin-inline-start: auto;
411
418
  }
412
419
 
413
- [data-ui='data-grid']
414
- [data-part='column-header']:is([data-align='end'], [data-numeric]:not([data-align]))
420
+ [data-ui-data-grid]
421
+ [data-part-column-header]:is([data-align='end'], [data-numeric]:not([data-align]))
415
422
  > span:first-child {
416
423
  text-align: end;
417
424
  }
418
425
 
419
426
  /* A sortable header is a control and takes the hand. */
420
- [data-ui='data-grid'] [data-part='column-header'][data-sortable] {
427
+ [data-ui-data-grid] [data-part-column-header][data-sortable] {
421
428
  cursor: pointer;
422
429
  }
423
430
 
424
431
  /* A header, a filter cell and a summary cell are controls, not prose: a
425
432
  Shift-press that appends a sort key must not also select its name. */
426
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='head'] > [role='row'] > *,
427
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='summary'] > [role='row'] > * {
433
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-head] > [role='row'] > *,
434
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-summary] > [role='row'] > * {
428
435
  user-select: none;
429
436
  }
430
437
 
@@ -432,12 +439,12 @@
432
439
  selection of the grid's own and not of text: the browser's selection is
433
440
  put out of the body for the two modes that press across cells. Ctrl+C
434
441
  copies the range; a grid with no selection keeps its text selectable. */
435
- [data-ui='data-grid']:is([data-selection='multiple'], [data-selection='range'])
436
- :is([data-part='body'], [data-part='pinned-rows']) {
442
+ [data-ui-data-grid]:is([data-selection='multiple'], [data-selection='range'])
443
+ :is([data-part-body], [data-part-pinned-rows]) {
437
444
  user-select: none;
438
445
  }
439
446
 
440
- [data-ui='data-grid'] [data-part='column-header'][data-sortable]:not([data-disabled]):hover {
447
+ [data-ui-data-grid] [data-part-column-header][data-sortable]:not([data-disabled]):hover {
441
448
  background-color: var(--_head-surface-hover);
442
449
  }
443
450
 
@@ -451,7 +458,7 @@
451
458
  * header can be sorted is the hand, the darker band and the menu it
452
459
  * reveals — the answer AG Grid gives.
453
460
  */
454
- [data-ui='data-grid'] [data-part='column-header'] > [data-part='sort'] {
461
+ [data-ui-data-grid] [data-part-column-header] > [data-part-sort] {
455
462
  --slotted-icon-size: var(--_icon-size);
456
463
  align-items: center;
457
464
  color: var(--_text);
@@ -463,29 +470,29 @@
463
470
  line-height: 1;
464
471
  }
465
472
 
466
- [data-ui='data-grid'] [data-part='column-header'] > [data-part='sort'] > [data-ui='icon'] {
473
+ [data-ui-data-grid] [data-part-column-header] > [data-part-sort] > [data-ui-icon] {
467
474
  transition: rotate var(--_transition);
468
475
  }
469
476
 
470
- [data-ui='data-grid'] [data-part='column-header'][data-sorted] > [data-part='sort'] {
477
+ [data-ui-data-grid] [data-part-column-header][data-sorted] > [data-part-sort] {
471
478
  display: inline-flex;
472
479
  }
473
480
 
474
- [data-ui='data-grid']
475
- [data-part='column-header'][data-sorted='ascending']
476
- > [data-part='sort']
477
- > [data-ui='icon'] {
481
+ [data-ui-data-grid]
482
+ [data-part-column-header][data-sorted='ascending']
483
+ > [data-part-sort]
484
+ > [data-ui-icon] {
478
485
  rotate: 180deg;
479
486
  }
480
487
 
481
488
  /* The index of a key past the first, drawn only then: `aria-sort` cannot say
482
489
  which key came first, and the number is what says it. */
483
- [data-ui='data-grid'] [data-part='column-header'] > [data-part='sort']::before {
490
+ [data-ui-data-grid] [data-part-column-header] > [data-part-sort]::before {
484
491
  content: attr(data-index);
485
492
  font-weight: var(--slotted-font-weight-medium, 500);
486
493
  }
487
494
 
488
- [data-ui='data-grid'] [data-part='column-header'] > [data-part='sort']:not([data-index])::before {
495
+ [data-ui-data-grid] [data-part-column-header] > [data-part-sort]:not([data-index])::before {
489
496
  content: none;
490
497
  }
491
498
 
@@ -505,7 +512,7 @@
505
512
  * filter row. Read on the first capture with both controls reserving room,
506
513
  * a 120-pixel column had 34 pixels left for its name.
507
514
  */
508
- [data-ui='data-grid'] [data-part='column-actions'] {
515
+ [data-ui-data-grid] [data-part-column-actions] {
509
516
  align-items: center;
510
517
  display: inline-flex;
511
518
  flex: none;
@@ -516,16 +523,16 @@
516
523
  margin-inline-start: auto;
517
524
  }
518
525
 
519
- [data-ui='data-grid'] [data-part='column-actions'] *:has([data-part='filter']) {
526
+ [data-ui-data-grid] [data-part-column-actions] *:has([data-part-filter]) {
520
527
  display: contents;
521
528
  }
522
529
 
523
- [data-ui='data-grid'] [data-part='column-help'],
524
- [data-ui='data-grid'] [data-part='column-menu'],
525
- [data-ui='data-grid'] [data-part='column-header'] [data-part='filter'],
526
- [data-ui='data-grid'] [data-part='expander'],
527
- [data-ui='data-grid'] [data-part='group-toggle'],
528
- [data-ui='data-grid'] [data-part='tree-toggle'] {
530
+ [data-ui-data-grid] [data-part-column-help],
531
+ [data-ui-data-grid] [data-part-column-menu],
532
+ [data-ui-data-grid] [data-part-column-header] [data-part-filter],
533
+ [data-ui-data-grid] [data-part-expander],
534
+ [data-ui-data-grid] [data-part-group-toggle],
535
+ [data-ui-data-grid] [data-part-tree-toggle] {
529
536
  /* The mark inside is the `Glyph` the binding draws, at the controls' own
530
537
  icon step rather than the box's. */
531
538
  --slotted-icon-size: var(--_control-icon);
@@ -547,44 +554,42 @@
547
554
  opacity var(--_transition);
548
555
  }
549
556
 
550
- [data-ui='data-grid'] [data-part='column-menu'] {
557
+ [data-ui-data-grid] [data-part-column-menu] {
551
558
  opacity: 0;
552
559
  }
553
560
 
554
- [data-ui='data-grid']
555
- [data-part='column-header']
556
- [data-part='filter']:not([data-filtered], [data-open]) {
561
+ [data-ui-data-grid]
562
+ [data-part-column-header]
563
+ [data-part-filter]:not([data-filtered], [data-open]) {
557
564
  display: none;
558
565
  }
559
566
 
560
- [data-ui='data-grid']
561
- [data-part='column-header']:not([data-disabled]):hover
562
- [data-part='column-menu'],
563
- [data-ui='data-grid'] [data-part='column-header']:focus-within [data-part='column-menu'],
564
- [data-ui='data-grid'] [data-part='column-header'][data-current] [data-part='column-menu'],
565
- [data-ui='data-grid'] [data-part='column-menu'][data-open] {
567
+ [data-ui-data-grid] [data-part-column-header]:not([data-disabled]):hover [data-part-column-menu],
568
+ [data-ui-data-grid] [data-part-column-header]:focus-within [data-part-column-menu],
569
+ [data-ui-data-grid] [data-part-column-header][data-current] [data-part-column-menu],
570
+ [data-ui-data-grid] [data-part-column-menu][data-open] {
566
571
  opacity: 1;
567
572
  }
568
573
 
569
- [data-ui='data-grid'] [data-part='column-help']:not(:disabled):hover,
570
- [data-ui='data-grid'] [data-part='column-help'][data-open],
571
- [data-ui='data-grid'] [data-part='column-menu']:not(:disabled):hover,
572
- [data-ui='data-grid'] [data-part='column-header'] [data-part='filter']:not(:disabled):hover,
573
- [data-ui='data-grid'] [data-part='group-toggle']:not(:disabled):hover {
574
+ [data-ui-data-grid] [data-part-column-help]:not(:disabled):hover,
575
+ [data-ui-data-grid] [data-part-column-help][data-open],
576
+ [data-ui-data-grid] [data-part-column-menu]:not(:disabled):hover,
577
+ [data-ui-data-grid] [data-part-column-header] [data-part-filter]:not(:disabled):hover,
578
+ [data-ui-data-grid] [data-part-group-toggle]:not(:disabled):hover {
574
579
  background-color: var(--_head-surface-hover);
575
580
  color: var(--_text);
576
581
  }
577
582
 
578
- [data-ui='data-grid'] [data-part='expander']:not(:disabled):hover {
583
+ [data-ui-data-grid] [data-part-expander]:not(:disabled):hover {
579
584
  background-color: var(--_hover);
580
585
  color: var(--_text);
581
586
  }
582
587
 
583
- [data-ui='data-grid'] [data-part='column-help']:focus-visible,
584
- [data-ui='data-grid'] [data-part='column-menu']:focus-visible,
585
- [data-ui='data-grid'] [data-part='column-header'] [data-part='filter']:focus-visible,
586
- [data-ui='data-grid'] [data-part='expander']:focus-visible,
587
- [data-ui='data-grid'] [data-part='group-toggle']:focus-visible {
588
+ [data-ui-data-grid] [data-part-column-help]:focus-visible,
589
+ [data-ui-data-grid] [data-part-column-menu]:focus-visible,
590
+ [data-ui-data-grid] [data-part-column-header] [data-part-filter]:focus-visible,
591
+ [data-ui-data-grid] [data-part-expander]:focus-visible,
592
+ [data-ui-data-grid] [data-part-group-toggle]:focus-visible {
588
593
  outline: var(--_ring-width) solid var(--slotted-focus-ring-color, Highlight);
589
594
  outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
590
595
  }
@@ -596,7 +601,7 @@
596
601
 
597
602
  /* The description is the header's `aria-describedby`: read, never drawn,
598
603
  and out of the header's flow so it asks for no room beside the name. */
599
- [data-ui='data-grid'] [data-part='column-description'] {
604
+ [data-ui-data-grid] [data-part-column-description] {
600
605
  block-size: 1px;
601
606
  border: 0;
602
607
  clip-path: inset(50%);
@@ -610,7 +615,7 @@
610
615
 
611
616
  /* The pop-in's column header names the pop-in for a reader: read, never
612
617
  drawn, and out of the row's flow so it takes no track of the template. */
613
- [data-ui='data-grid'] [data-part='popin-header'] {
618
+ [data-ui-data-grid] [data-part-popin-header] {
614
619
  block-size: 1px;
615
620
  border: 0;
616
621
  clip-path: inset(50%);
@@ -627,7 +632,7 @@
627
632
  is set as a caption over the items, in the muted ink, on the items' inset.
628
633
  The screen reader hears it once, through the menu's `aria-describedby`.
629
634
  The menu lays its items on a grid of tracks; the caption spans them all. */
630
- [data-ui='menu'] [data-part='column-menu-description'] {
635
+ [data-ui-menu] [data-part-column-menu-description] {
631
636
  grid-column: 1 / -1;
632
637
  border-block-end: var(--slotted-border-width-thin, 1px) solid
633
638
  var(--slotted-border-subtle, GrayText);
@@ -645,49 +650,47 @@
645
650
  glyph scale for this family: `table` takes the artwork from the consumer,
646
651
  and a control this family draws itself owes its glyph to the scale. */
647
652
 
648
- [data-ui='data-grid'] [data-part='column-header'] [data-part='filter'][data-filtered],
649
- [data-ui='data-grid'] [data-part='column-header'] [data-part='filter'][data-open] {
653
+ [data-ui-data-grid] [data-part-column-header] [data-part-filter][data-filtered],
654
+ [data-ui-data-grid] [data-part-column-header] [data-part-filter][data-open] {
650
655
  color: var(--slotted-tone-accent-text, CanvasText);
651
656
  }
652
657
 
653
- [data-ui='data-grid']
654
- [data-part='column-header']
655
- [data-part='filter'][data-filtered]:not(:disabled):hover {
658
+ [data-ui-data-grid]
659
+ [data-part-column-header]
660
+ [data-part-filter][data-filtered]:not(:disabled):hover {
656
661
  background-color: var(--slotted-tone-accent-surface, Canvas);
657
662
  }
658
663
 
659
664
  /* The expander and the group toggle are the `chevron-right` `Glyph` the
660
665
  binding draws, turned a quarter turn when open and mirrored in a
661
666
  right-to-left document. */
662
- [data-ui='data-grid'] [data-part='expander'] > [data-ui='icon'],
663
- [data-ui='data-grid'] [data-part='group-toggle'] > [data-ui='icon'],
664
- [data-ui='data-grid'] button[data-part='tree-toggle'] > [data-ui='icon'] {
667
+ [data-ui-data-grid] [data-part-expander] > [data-ui-icon],
668
+ [data-ui-data-grid] [data-part-group-toggle] > [data-ui-icon],
669
+ [data-ui-data-grid] button[data-part-tree-toggle] > [data-ui-icon] {
665
670
  transition: rotate var(--_transition);
666
671
  }
667
672
 
668
- [data-ui='data-grid'] [data-part='expander'][aria-expanded='true'] > [data-ui='icon'],
669
- [data-ui='data-grid'] button[data-part='tree-toggle'][aria-expanded='true'] > [data-ui='icon'],
670
- [data-ui='data-grid']
671
- [data-part='group-row'][aria-expanded='true']
672
- [data-part='group-toggle']
673
- > [data-ui='icon'] {
673
+ [data-ui-data-grid] [data-part-expander][aria-expanded='true'] > [data-ui-icon],
674
+ [data-ui-data-grid] button[data-part-tree-toggle][aria-expanded='true'] > [data-ui-icon],
675
+ [data-ui-data-grid]
676
+ [data-part-group-row][aria-expanded='true']
677
+ [data-part-group-toggle]
678
+ > [data-ui-icon] {
674
679
  rotate: 90deg;
675
680
  }
676
681
 
677
- [data-ui='data-grid']:dir(rtl) [data-part='expander'] > [data-ui='icon'],
678
- [data-ui='data-grid']:dir(rtl) [data-part='group-toggle'] > [data-ui='icon'],
679
- [data-ui='data-grid']:dir(rtl) button[data-part='tree-toggle'] > [data-ui='icon'] {
682
+ [data-ui-data-grid]:dir(rtl) [data-part-expander] > [data-ui-icon],
683
+ [data-ui-data-grid]:dir(rtl) [data-part-group-toggle] > [data-ui-icon],
684
+ [data-ui-data-grid]:dir(rtl) button[data-part-tree-toggle] > [data-ui-icon] {
680
685
  rotate: 180deg;
681
686
  }
682
687
 
683
- [data-ui='data-grid']:dir(rtl) [data-part='expander'][aria-expanded='true'] > [data-ui='icon'],
684
- [data-ui='data-grid']:dir(rtl)
685
- button[data-part='tree-toggle'][aria-expanded='true']
686
- > [data-ui='icon'],
687
- [data-ui='data-grid']:dir(rtl)
688
- [data-part='group-row'][aria-expanded='true']
689
- [data-part='group-toggle']
690
- > [data-ui='icon'] {
688
+ [data-ui-data-grid]:dir(rtl) [data-part-expander][aria-expanded='true'] > [data-ui-icon],
689
+ [data-ui-data-grid]:dir(rtl) button[data-part-tree-toggle][aria-expanded='true'] > [data-ui-icon],
690
+ [data-ui-data-grid]:dir(rtl)
691
+ [data-part-group-row][aria-expanded='true']
692
+ [data-part-group-toggle]
693
+ > [data-ui-icon] {
691
694
  rotate: 90deg;
692
695
  }
693
696
 
@@ -700,26 +703,26 @@
700
703
  * horizontal arrows there open and close. A row waiting for its children
701
704
  * turns the chevron into the loader's ring.
702
705
  */
703
- [data-ui='data-grid'] [data-part='cell'][data-tree],
704
- [data-ui='data-grid'] [data-part='row-header'][data-tree] {
706
+ [data-ui-data-grid] [data-part-cell][data-tree],
707
+ [data-ui-data-grid] [data-part-row-header][data-tree] {
705
708
  gap: var(--slotted-space-1, 0.125rem);
706
709
  padding-inline-start: calc(
707
710
  var(--_pad-inline) + var(--_indent) * (var(--slotted-data-grid-level, 1) - 1)
708
711
  );
709
712
  }
710
713
 
711
- [data-ui='data-grid'] [data-part='tree-toggle'][data-empty] {
714
+ [data-ui-data-grid] [data-part-tree-toggle][data-empty] {
712
715
  /* The room, and nothing in it. */
713
716
  cursor: default;
714
717
  }
715
718
 
716
- [data-ui='data-grid'] button[data-part='tree-toggle']:not(:disabled):hover {
719
+ [data-ui-data-grid] button[data-part-tree-toggle]:not(:disabled):hover {
717
720
  background-color: var(--_hover);
718
721
  color: var(--_text);
719
722
  }
720
723
 
721
724
  /* The binding draws the loader's ring in place of the chevron. */
722
- [data-ui='data-grid'] button[data-part='tree-toggle'][data-loading] > [data-ui='icon'] {
725
+ [data-ui-data-grid] button[data-part-tree-toggle][data-loading] > [data-ui-icon] {
723
726
  animation: slotted-data-grid-turn var(--slotted-duration-loop) linear infinite;
724
727
  rotate: 0deg;
725
728
  }
@@ -739,12 +742,12 @@
739
742
  * width and the reader hears why nothing moves. A row on its way is
740
743
  * dimmed, as a column is.
741
744
  */
742
- [data-ui='data-grid'] [data-part='cell'][data-kind='drag'] {
745
+ [data-ui-data-grid] [data-part-cell][data-kind='drag'] {
743
746
  justify-content: center;
744
747
  padding-inline: 0;
745
748
  }
746
749
 
747
- [data-ui='data-grid'] [data-part='row-handle'] {
750
+ [data-ui-data-grid] [data-part-row-handle] {
748
751
  /* The grip is the `Glyph` the binding draws, at the controls' icon step. */
749
752
  --slotted-icon-size: var(--_control-icon);
750
753
  align-items: center;
@@ -766,21 +769,21 @@
766
769
  opacity var(--_transition);
767
770
  }
768
771
 
769
- [data-ui='data-grid'] [data-part='row-handle']:not([data-disabled]):hover {
772
+ [data-ui-data-grid] [data-part-row-handle]:not([data-disabled]):hover {
770
773
  background-color: var(--_hover);
771
774
  color: var(--_text);
772
775
  }
773
776
 
774
- [data-ui='data-grid'] [data-part='row-handle'][data-disabled] {
777
+ [data-ui-data-grid] [data-part-row-handle][data-disabled] {
775
778
  cursor: default;
776
779
  opacity: 0.5;
777
780
  }
778
781
 
779
- [data-ui='data-grid'] [data-part='row'][data-dragging] {
782
+ [data-ui-data-grid] [data-part-row][data-dragging] {
780
783
  opacity: 0.5;
781
784
  }
782
785
 
783
- [data-ui='data-grid'] [data-part='row'][data-dragging] [data-part='row-handle'] {
786
+ [data-ui-data-grid] [data-part-row][data-dragging] [data-part-row-handle] {
784
787
  cursor: grabbing;
785
788
  }
786
789
 
@@ -794,7 +797,7 @@
794
797
  * resizes from the header cell itself, and a focusable handle inside a
795
798
  * composite widget would be a second tab stop.
796
799
  */
797
- [data-ui='data-grid'] [data-part='resizer'] {
800
+ [data-ui-data-grid] [data-part-resizer] {
798
801
  cursor: col-resize;
799
802
  inline-size: var(--slotted-target-min, 24px);
800
803
  inset-block: 0;
@@ -809,15 +812,15 @@
809
812
  /* The last column's handle stays inside the row: half a target hanging
810
813
  past the last cell was twelve pixels of overflow on a row nothing could
811
814
  scroll to. */
812
- [data-ui='data-grid']
813
- [data-part='header-row']
814
- > [data-part='column-header']:last-child
815
- > [data-part='resizer'] {
815
+ [data-ui-data-grid]
816
+ [data-part-header-row]
817
+ > [data-part-column-header]:last-child
818
+ > [data-part-resizer] {
816
819
  inline-size: calc(var(--slotted-target-min, 24px) / 2);
817
820
  inset-inline-end: 0;
818
821
  }
819
822
 
820
- [data-ui='data-grid'] [data-part='resizer']::after {
823
+ [data-ui-data-grid] [data-part-resizer]::after {
821
824
  background-color: transparent;
822
825
  block-size: 100%;
823
826
  content: '';
@@ -827,12 +830,12 @@
827
830
  transition: background-color var(--_transition);
828
831
  }
829
832
 
830
- [data-ui='data-grid'] [data-part='resizer']:not([data-disabled]):hover::after {
833
+ [data-ui-data-grid] [data-part-resizer]:not([data-disabled]):hover::after {
831
834
  background-color: var(--_rule-strong);
832
835
  }
833
836
 
834
- [data-ui='data-grid'] [data-part='resizer'][data-resizing]::after,
835
- [data-ui='data-grid'] [data-part='column-header'][data-resizing] > [data-part='resizer']::after {
837
+ [data-ui-data-grid] [data-part-resizer][data-resizing]::after,
838
+ [data-ui-data-grid] [data-part-column-header][data-resizing] > [data-part-resizer]::after {
836
839
  background-color: var(--_cursor);
837
840
  }
838
841
 
@@ -843,15 +846,15 @@
843
846
  * colour between two columns, positioned by the binding through
844
847
  * `--slotted-data-grid-drop-offset` from the scroller's start edge.
845
848
  */
846
- [data-ui='data-grid'] [data-part='column-header'][data-dragging] {
849
+ [data-ui-data-grid] [data-part-column-header][data-dragging] {
847
850
  opacity: 0.5;
848
851
  }
849
852
 
850
- [data-ui='data-grid'] [data-part='column-header'][data-drop-target] {
853
+ [data-ui-data-grid] [data-part-column-header][data-drop-target] {
851
854
  background-color: var(--_head-surface-hover);
852
855
  }
853
856
 
854
- [data-ui='data-grid'] [data-part='drop-indicator'] {
857
+ [data-ui-data-grid] [data-part-drop-indicator] {
855
858
  background-color: var(--_cursor);
856
859
  /* Absolute in the scroller: its box is the content's, so the line is
857
860
  moved down by the scrolled distance to span the viewport. */
@@ -868,7 +871,7 @@
868
871
 
869
872
  /* The same line for a row on its way: horizontal, in the gap the drop
870
873
  lands in, as wide as the viewport and moved by the sideways scroll. */
871
- [data-ui='data-grid'] [data-part='drop-indicator'][data-axis='row'] {
874
+ [data-ui-data-grid] [data-part-drop-indicator][data-axis='row'] {
872
875
  block-size: var(--slotted-border-width-thick, 2px);
873
876
  inline-size: 100cqi;
874
877
  inset-block-start: calc(
@@ -886,7 +889,7 @@
886
889
  * head. It is a row of the grid — `role="row"`, one `gridcell` per column —
887
890
  * so the cursor walks it.
888
891
  */
889
- [data-ui='data-grid'] [data-part='filter-row'] > [data-part='filter-cell'] {
892
+ [data-ui-data-grid] [data-part-filter-row] > [data-part-filter-cell] {
890
893
  /* The control inside draws no ring of its own: the cell draws the trace
891
894
  around the whole of it while anything inside has the focus, so a field
892
895
  in the row and the cell it fills are not two rings. The accent edge a
@@ -906,7 +909,7 @@
906
909
  position: relative;
907
910
  }
908
911
 
909
- [data-ui='data-grid'] [data-part='filter-row'] > [data-part='filter-cell']:focus-within {
912
+ [data-ui-data-grid] [data-part-filter-row] > [data-part-filter-cell]:focus-within {
910
913
  box-shadow: none;
911
914
  outline: var(--_ring-width) solid var(--slotted-focus-ring-color, Highlight);
912
915
  outline-offset: calc(var(--_ring-width) * -1);
@@ -923,11 +926,8 @@
923
926
  named there, and `A > :is(host > B)` asks B to be A's child and the
924
927
  host's at once. `data-grid.styles.test.mjs` holds the rule for every
925
928
  hosted part. */
926
- [data-ui='data-grid'] [data-part='filter-cell'] > [data-part='filter-operand'],
927
- [data-ui='data-grid']
928
- [data-part='filter-cell']
929
- > :not([data-part])
930
- > [data-part='filter-operand'] {
929
+ [data-ui-data-grid] [data-part-filter-cell] > [data-part-filter-operand],
930
+ [data-ui-data-grid] [data-part-filter-cell] > :not([data-part]) > [data-part-filter-operand] {
931
931
  align-items: center;
932
932
  display: flex;
933
933
  flex: 1 1 auto;
@@ -944,15 +944,15 @@
944
944
  /* The plain control inside takes what the trace leaves of the row's
945
945
  height and a short inset after the operator, the rule every cell
946
946
  holding a plain control applies. */
947
- [data-ui='data-grid']
948
- [data-part='filter-cell']
949
- [data-part='filter-operand']
950
- > [data-part='root'][data-variant='plain'],
951
- [data-ui='data-grid']
952
- [data-part='filter-cell']
953
- [data-part='filter-operand']
947
+ [data-ui-data-grid]
948
+ [data-part-filter-cell]
949
+ [data-part-filter-operand]
950
+ > [data-part-root][data-variant='plain'],
951
+ [data-ui-data-grid]
952
+ [data-part-filter-cell]
953
+ [data-part-filter-operand]
954
954
  > :not([data-part])
955
- > [data-part='root'][data-variant='plain'] {
955
+ > [data-part-root][data-variant='plain'] {
956
956
  --slotted-control-padding-inline-sm: var(--slotted-space-3, 0.375rem);
957
957
  --slotted-control-height-sm: calc(var(--_head-block) - var(--_ring-width) * 2);
958
958
 
@@ -963,34 +963,34 @@
963
963
  /* Both fields of a numeric `between` share the line, a dash between them;
964
964
  a date, a time or a date-time `between` is one range picker and carries
965
965
  no `data-range`. */
966
- [data-ui='data-grid']
967
- [data-part='filter-cell']
968
- [data-part='filter-operand'][data-range]
969
- > [data-part='root'],
970
- [data-ui='data-grid']
971
- [data-part='filter-cell']
972
- [data-part='filter-operand'][data-range]
966
+ [data-ui-data-grid]
967
+ [data-part-filter-cell]
968
+ [data-part-filter-operand][data-range]
969
+ > [data-part-root],
970
+ [data-ui-data-grid]
971
+ [data-part-filter-cell]
972
+ [data-part-filter-operand][data-range]
973
973
  > :not([data-part])
974
- > [data-part='root'] {
974
+ > [data-part-root] {
975
975
  flex: 1 1 0;
976
976
  inline-size: 0;
977
977
  }
978
978
 
979
- [data-ui='data-grid'] [data-part='filter-cell'] [data-part='filter-operand'][data-range]::before {
979
+ [data-ui-data-grid] [data-part-filter-cell] [data-part-filter-operand][data-range]::before {
980
980
  color: var(--_muted);
981
981
  content: '–';
982
982
  order: 2;
983
983
  }
984
984
 
985
- [data-ui='data-grid']
986
- [data-part='filter-cell']
987
- [data-part='filter-operand'][data-range]
988
- > [data-part='root']:last-child,
989
- [data-ui='data-grid']
990
- [data-part='filter-cell']
991
- [data-part='filter-operand'][data-range]
985
+ [data-ui-data-grid]
986
+ [data-part-filter-cell]
987
+ [data-part-filter-operand][data-range]
988
+ > [data-part-root]:last-child,
989
+ [data-ui-data-grid]
990
+ [data-part-filter-cell]
991
+ [data-part-filter-operand][data-range]
992
992
  > :not([data-part]):last-child
993
- > [data-part='root'] {
993
+ > [data-part-root] {
994
994
  order: 3;
995
995
  }
996
996
 
@@ -999,7 +999,7 @@
999
999
  * square target the height of the inner control; it opens a `menu` naming
1000
1000
  * every operator in full, and its accessible name is the operator in full.
1001
1001
  */
1002
- [data-ui='data-grid'] [data-part='filter-cell'] [data-part='filter-operator'] {
1002
+ [data-ui-data-grid] [data-part-filter-cell] [data-part-filter-operator] {
1003
1003
  display: inline-flex;
1004
1004
  flex: none;
1005
1005
  /* One space step off the cell's edge: glued to it, the symbol read as
@@ -1007,7 +1007,7 @@
1007
1007
  padding-inline-start: var(--slotted-space-3, 0.375rem);
1008
1008
  }
1009
1009
 
1010
- [data-ui='data-grid'] [data-part='filter-cell'] [data-part='filter-operator'] > button {
1010
+ [data-ui-data-grid] [data-part-filter-cell] [data-part-filter-operator] > button {
1011
1011
  align-items: center;
1012
1012
  background-color: transparent;
1013
1013
  block-size: var(--slotted-control-inner-size-sm, 22px);
@@ -1028,26 +1028,20 @@
1028
1028
  color var(--_transition);
1029
1029
  }
1030
1030
 
1031
- [data-ui='data-grid']
1032
- [data-part='filter-cell']
1033
- [data-part='filter-operator']
1031
+ [data-ui-data-grid]
1032
+ [data-part-filter-cell]
1033
+ [data-part-filter-operator]
1034
1034
  > button:not(:disabled):hover {
1035
1035
  background-color: var(--_head-surface-hover);
1036
1036
  color: var(--_text);
1037
1037
  }
1038
1038
 
1039
- [data-ui='data-grid']
1040
- [data-part='filter-cell']
1041
- [data-part='filter-operator']
1042
- > button:focus-visible {
1039
+ [data-ui-data-grid] [data-part-filter-cell] [data-part-filter-operator] > button:focus-visible {
1043
1040
  outline: var(--_ring-width) solid var(--slotted-focus-ring-color, Highlight);
1044
1041
  outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
1045
1042
  }
1046
1043
 
1047
- [data-ui='data-grid']
1048
- [data-part='filter-cell'][data-filtered]
1049
- [data-part='filter-operator']
1050
- > button {
1044
+ [data-ui-data-grid] [data-part-filter-cell][data-filtered] [data-part-filter-operator] > button {
1051
1045
  color: var(--slotted-tone-accent-text, CanvasText);
1052
1046
  }
1053
1047
 
@@ -1069,7 +1063,7 @@
1069
1063
  binding draws it inside a host element of its own (`display: contents`),
1070
1064
  and a child combinator here left that popover at sixteen rem with the
1071
1065
  panel standing out of it. */
1072
- [data-ui='popover']:has(> [data-part='content'] [data-ui='data-grid'][data-part='filter-panel']) {
1066
+ [data-ui-popover]:has(> [data-part-content] [data-ui-data-grid][data-part-filter-panel]) {
1073
1067
  --slotted-popover-measure-sm: calc(
1074
1068
  var(--slotted-data-grid-filter-panel-size, 24rem) + 2 *
1075
1069
  (var(--slotted-popover-gap, 0.5rem) + var(--slotted-border-width-thin, 1px))
@@ -1079,14 +1073,14 @@
1079
1073
  /* A date's `between` is two dates in one frame and a date-time's two
1080
1074
  date-times: the panel widens for the kinds whose operand is long, so the
1081
1075
  range is read whole rather than clipped. */
1082
- [data-ui='popover']:has(
1083
- > [data-part='content'] [data-ui='data-grid'][data-part='filter-panel'][data-kind='date']
1076
+ [data-ui-popover]:has(
1077
+ > [data-part-content] [data-ui-data-grid][data-part-filter-panel][data-kind='date']
1084
1078
  ) {
1085
1079
  --slotted-data-grid-filter-panel-size: var(--slotted-data-grid-filter-panel-size-date, 28rem);
1086
1080
  }
1087
1081
 
1088
- [data-ui='popover']:has(
1089
- > [data-part='content'] [data-ui='data-grid'][data-part='filter-panel'][data-kind='datetime']
1082
+ [data-ui-popover]:has(
1083
+ > [data-part-content] [data-ui-data-grid][data-part-filter-panel][data-kind='datetime']
1090
1084
  ) {
1091
1085
  --slotted-data-grid-filter-panel-size: var(
1092
1086
  --slotted-data-grid-filter-panel-size-datetime,
@@ -1094,7 +1088,7 @@
1094
1088
  );
1095
1089
  }
1096
1090
 
1097
- [data-ui='data-grid'][data-part='filter-panel'] {
1091
+ [data-ui-data-grid][data-part-filter-panel] {
1098
1092
  --_operator-size: var(--slotted-data-grid-filter-operator-size, 7rem);
1099
1093
  --_panel-gap: var(--slotted-space-3, 0.375rem);
1100
1094
 
@@ -1119,7 +1113,7 @@
1119
1113
  var(--slotted-popover-padding-inline-sm, var(--slotted-space-5, 0.75rem));
1120
1114
  }
1121
1115
 
1122
- [data-ui='data-grid'][data-part='filter-panel'] > [data-part='filter-condition'] {
1116
+ [data-ui-data-grid][data-part-filter-panel] > [data-part-filter-condition] {
1123
1117
  align-items: center;
1124
1118
  display: grid;
1125
1119
  gap: var(--_panel-gap);
@@ -1129,22 +1123,22 @@
1129
1123
 
1130
1124
  /* The first condition has no join: its operator starts in the second
1131
1125
  column. A set filter has one condition and no join at all. */
1132
- [data-ui='data-grid'][data-part='filter-panel']
1133
- > [data-part='filter-condition']:first-child
1134
- > [data-part='filter-operator'] {
1126
+ [data-ui-data-grid][data-part-filter-panel]
1127
+ > [data-part-filter-condition]:first-child
1128
+ > [data-part-filter-operator] {
1135
1129
  grid-column: 2;
1136
1130
  }
1137
1131
 
1138
- [data-ui='data-grid'][data-part='filter-panel'] [data-part='filter-join'] {
1132
+ [data-ui-data-grid][data-part-filter-panel] [data-part-filter-join] {
1139
1133
  grid-column: 1;
1140
1134
  }
1141
1135
 
1142
- [data-ui='data-grid'][data-part='filter-panel'] [data-part='filter-operator'] {
1136
+ [data-ui-data-grid][data-part-filter-panel] [data-part-filter-operator] {
1143
1137
  grid-column: 2;
1144
1138
  min-inline-size: 0;
1145
1139
  }
1146
1140
 
1147
- [data-ui='data-grid'][data-part='filter-panel'] [data-part='filter-operand'] {
1141
+ [data-ui-data-grid][data-part-filter-panel] [data-part-filter-operand] {
1148
1142
  align-items: center;
1149
1143
  display: flex;
1150
1144
  gap: var(--_panel-gap);
@@ -1154,46 +1148,44 @@
1154
1148
 
1155
1149
  /* An operator taking no operand leaves the operand column empty rather than
1156
1150
  drawing a disabled field. */
1157
- [data-ui='data-grid'][data-part='filter-panel']
1158
- [data-part='filter-condition'][data-operands='0']
1159
- > [data-part='filter-operand'] {
1151
+ [data-ui-data-grid][data-part-filter-panel]
1152
+ [data-part-filter-condition][data-operands='0']
1153
+ > [data-part-filter-operand] {
1160
1154
  display: none;
1161
1155
  }
1162
1156
 
1163
1157
  /* Both operands of a `between` stand on the line with a dash between them:
1164
1158
  the pair is one thought and one line says so. */
1165
- [data-ui='data-grid'][data-part='filter-panel'] [data-part='filter-operand'][data-range] > * {
1159
+ [data-ui-data-grid][data-part-filter-panel] [data-part-filter-operand][data-range] > * {
1166
1160
  flex: 1 1 0;
1167
1161
  inline-size: 0;
1168
1162
  min-inline-size: 0;
1169
1163
  }
1170
1164
 
1171
- [data-ui='data-grid'][data-part='filter-panel'] [data-part='filter-operand'][data-range]::before {
1165
+ [data-ui-data-grid][data-part-filter-panel] [data-part-filter-operand][data-range]::before {
1172
1166
  color: var(--slotted-text-muted);
1173
1167
  content: '–';
1174
1168
  order: 1;
1175
1169
  }
1176
1170
 
1177
- [data-ui='data-grid'][data-part='filter-panel']
1178
- [data-part='filter-operand'][data-range]
1179
- > :last-child {
1171
+ [data-ui-data-grid][data-part-filter-panel] [data-part-filter-operand][data-range] > :last-child {
1180
1172
  order: 2;
1181
1173
  }
1182
1174
 
1183
- [data-ui='data-grid'][data-part='filter-panel'] [data-part='filter-operand'] > [data-part='root'],
1184
- [data-ui='data-grid'][data-part='filter-panel']
1185
- [data-part='filter-operand']
1175
+ [data-ui-data-grid][data-part-filter-panel] [data-part-filter-operand] > [data-part-root],
1176
+ [data-ui-data-grid][data-part-filter-panel]
1177
+ [data-part-filter-operand]
1186
1178
  > :not([data-part])
1187
- > [data-part='root'] {
1179
+ > [data-part-root] {
1188
1180
  flex: 1 1 auto;
1189
1181
  min-inline-size: 0;
1190
1182
  }
1191
1183
 
1192
- [data-ui='data-grid'][data-part='filter-panel'] [data-part='filter-operand'] [data-part='input'] {
1184
+ [data-ui-data-grid][data-part-filter-panel] [data-part-filter-operand] [data-part-input] {
1193
1185
  min-inline-size: 0;
1194
1186
  }
1195
1187
 
1196
- [data-ui='data-grid'][data-part='filter-panel'] [data-part='filter-actions'] {
1188
+ [data-ui-data-grid][data-part-filter-panel] [data-part-filter-actions] {
1197
1189
  display: flex;
1198
1190
  gap: var(--_panel-gap);
1199
1191
  grid-column: 1 / -1;
@@ -1204,7 +1196,7 @@
1204
1196
  /**
1205
1197
  * ── Rows and cells ─────────────────────────────────────────────────────
1206
1198
  */
1207
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='body'] {
1199
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-body] {
1208
1200
  box-sizing: border-box;
1209
1201
  /* The virtual window: the body is as tall as every row and its padding is
1210
1202
  the offset of the first mounted one, so the mounted rows stand where the
@@ -1214,7 +1206,7 @@
1214
1206
  padding-block-start: var(--slotted-data-grid-window-start, 0);
1215
1207
  }
1216
1208
 
1217
- [data-ui='data-grid'] [data-part='row'] {
1209
+ [data-ui-data-grid] [data-part-row] {
1218
1210
  background-color: var(--_surface);
1219
1211
  transition: background-color var(--_transition);
1220
1212
  }
@@ -1234,28 +1226,28 @@
1234
1226
  * content grows a `minmax(row, cap)` track to the cap — read on the content
1235
1227
  * scene, every auto row was four rows tall, one line of text in each.
1236
1228
  */
1237
- [data-ui='data-grid'][data-rows='fixed']
1238
- > [data-part='scroll']
1239
- > :is([data-part='body'], [data-part='pinned-rows'])
1240
- > [data-part='row'] {
1229
+ [data-ui-data-grid][data-rows='fixed']
1230
+ > [data-part-scroll]
1231
+ > :is([data-part-body], [data-part-pinned-rows])
1232
+ > [data-part-row] {
1241
1233
  block-size: var(--_row-block);
1242
1234
  grid-auto-rows: var(--_track);
1243
1235
  }
1244
1236
 
1245
- [data-ui='data-grid'][data-rows='auto']
1246
- > [data-part='scroll']
1247
- > :is([data-part='body'], [data-part='pinned-rows'])
1248
- > [data-part='row'] {
1237
+ [data-ui-data-grid][data-rows='auto']
1238
+ > [data-part-scroll]
1239
+ > :is([data-part-body], [data-part-pinned-rows])
1240
+ > [data-part-row] {
1249
1241
  grid-auto-rows: minmax(var(--_track), auto);
1250
1242
  }
1251
1243
 
1252
1244
  /* A value taller than the cap is clipped at it, on the block axis only: a
1253
1245
  pinned cell's edge shadow is drawn past its inline end. The pop-in is not
1254
1246
  a value of the row and has no cap. */
1255
- [data-ui='data-grid'][data-rows='auto']
1256
- :is([data-part='body'], [data-part='pinned-rows'])
1257
- > [data-part='row']
1258
- > :is([role='gridcell'], [role='rowheader']):not([data-part='popin']) {
1247
+ [data-ui-data-grid][data-rows='auto']
1248
+ :is([data-part-body], [data-part-pinned-rows])
1249
+ > [data-part-row]
1250
+ > :is([role='gridcell'], [role='rowheader']):not([data-part-popin]) {
1259
1251
  max-block-size: var(--_row-max-block);
1260
1252
  overflow-y: clip;
1261
1253
  }
@@ -1263,37 +1255,56 @@
1263
1255
  /* A row that grows to its text aligns its cells to the top: a one-line
1264
1256
  value centred beside a four-line one floats in the middle of nothing,
1265
1257
  and the eye reads a row from its first line. Fixed rows stay centred. */
1266
- [data-ui='data-grid'][data-rows='auto']
1267
- :is([data-part='body'], [data-part='pinned-rows'])
1268
- > [data-part='row']
1258
+ [data-ui-data-grid][data-rows='auto']
1259
+ :is([data-part-body], [data-part-pinned-rows])
1260
+ > [data-part-row]
1269
1261
  > [role='gridcell'],
1270
- [data-ui='data-grid'][data-rows='auto']
1271
- :is([data-part='body'], [data-part='pinned-rows'])
1272
- > [data-part='row']
1262
+ [data-ui-data-grid][data-rows='auto']
1263
+ :is([data-part-body], [data-part-pinned-rows])
1264
+ > [data-part-row]
1273
1265
  > [role='rowheader'] {
1274
1266
  align-items: start;
1275
1267
  }
1276
1268
 
1277
- [data-ui='data-grid']:is([data-variant='ruled'], [data-variant='framed'])
1278
- > [data-part='scroll']
1279
- > :is([data-part='body'], [data-part='pinned-rows']) {
1269
+ [data-ui-data-grid]:is([data-variant='ruled'], [data-variant='framed'])
1270
+ > [data-part-scroll]
1271
+ > :is([data-part-body], [data-part-pinned-rows]) {
1280
1272
  --_track: calc(var(--_row-block) - var(--_rule-width));
1281
1273
  }
1282
1274
 
1283
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='head'] > [role='row'],
1284
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='summary'] > [role='row'],
1285
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='loader'] > [role='row'] {
1275
+ /**
1276
+ * A control a cell renderer draws — a `Button`, an `IconButton`, a `Select` —
1277
+ * stands inside the cursor's trace: the row restates the control scale as
1278
+ * the track less the ring and one space step on each side, so a hovered
1279
+ * ground never covers the trace, at every density. The restatement is on
1280
+ * the row and not on each cell, so a row of eight cells computes it once.
1281
+ * A cell in edit states its own, the track less the ring.
1282
+ */
1283
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-body] > [data-part-row],
1284
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-pinned-rows] > [data-part-row] {
1285
+ --_cell-control: calc(
1286
+ var(--_track) - var(--_ring-width) * 2 - var(--slotted-space-1, 0.125rem) * 2
1287
+ );
1288
+ --slotted-control-height-sm: min(var(--_control-height-sm), var(--_cell-control));
1289
+ --slotted-control-height-md: min(var(--_control-height-md), var(--_cell-control));
1290
+ --slotted-control-height-lg: min(var(--_control-height-lg), var(--_cell-control));
1291
+ --slotted-target-min: min(var(--_target-min), var(--_cell-control));
1292
+ }
1293
+
1294
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-head] > [role='row'],
1295
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-summary] > [role='row'],
1296
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-loader] > [role='row'] {
1286
1297
  grid-auto-rows: minmax(var(--_head-block), auto);
1287
1298
  }
1288
1299
 
1289
- [data-ui='data-grid'] [data-part='cell'],
1290
- [data-ui='data-grid'] [data-part='row-header'],
1291
- [data-ui='data-grid'] [data-part='summary-cell'],
1292
- [data-ui='data-grid']
1293
- > [data-part='scroll']
1294
- > :is([data-part='body'], [data-part='pinned-rows'])
1300
+ [data-ui-data-grid] [data-part-cell],
1301
+ [data-ui-data-grid] [data-part-row-header],
1302
+ [data-ui-data-grid] [data-part-summary-cell],
1303
+ [data-ui-data-grid]
1304
+ > [data-part-scroll]
1305
+ > :is([data-part-body], [data-part-pinned-rows])
1295
1306
  > [role='row']
1296
- > [data-part='selection'] {
1307
+ > [data-part-selection] {
1297
1308
  align-items: center;
1298
1309
  box-sizing: border-box;
1299
1310
  display: flex;
@@ -1305,7 +1316,7 @@
1305
1316
 
1306
1317
  /* Every cell but a pinned one is a containing block, for the range edges
1307
1318
  and the invalid mark; a pinned cell is already positioned by `sticky`. */
1308
- [data-ui='data-grid'] [data-part='cell']:not([data-pinned]) {
1319
+ [data-ui-data-grid] [data-part-cell]:not([data-pinned]) {
1309
1320
  position: relative;
1310
1321
  }
1311
1322
 
@@ -1313,9 +1324,9 @@
1313
1324
  keeps its own direction: an identifier, an email or a price in a
1314
1325
  right-to-left document is left-to-right text, and read in `dir="rtl"`
1315
1326
  "Bloom & Co." had its full stop moved to the front. */
1316
- [data-ui='data-grid'] [data-part='cell'] > span:not([data-ui], [data-part]),
1317
- [data-ui='data-grid'] [data-part='row-header'] > span:not([data-ui], [data-part]),
1318
- [data-ui='data-grid'] [data-part='summary-cell'] > span:not([data-ui], [data-part]) {
1327
+ [data-ui-data-grid] [data-part-cell] > span:not([data-ui], [data-part]),
1328
+ [data-ui-data-grid] [data-part-row-header] > span:not([data-ui], [data-part]),
1329
+ [data-ui-data-grid] [data-part-summary-cell] > span:not([data-ui], [data-part]) {
1319
1330
  flex: 1 1 auto;
1320
1331
  min-inline-size: 0;
1321
1332
  unicode-bidi: plaintext;
@@ -1324,35 +1335,35 @@
1324
1335
  /* A family drawn in a cell by a renderer — a badge, a tag — keeps its own
1325
1336
  size: read on the status column, a badge filled the cell's whole width
1326
1337
  because it was a span standing where the value stands. */
1327
- [data-ui='data-grid'] [data-part='cell'] > [data-ui]:not([data-part]) {
1338
+ [data-ui-data-grid] [data-part-cell] > [data-ui]:not([data-part]) {
1328
1339
  flex: 0 0 auto;
1329
1340
  max-inline-size: 100%;
1330
1341
  }
1331
1342
 
1332
1343
  /* A row header names the record and carries one step of weight. */
1333
- [data-ui='data-grid'] [data-part='row-header'] {
1344
+ [data-ui-data-grid] [data-part-row-header] {
1334
1345
  font-weight: var(--slotted-font-weight-medium, 500);
1335
1346
  }
1336
1347
 
1337
1348
  /* The rule between two rows, on the row; the last gives its rule up so a
1338
1349
  ruled grid does not end in a line with nothing under it. */
1339
- [data-ui='data-grid']:is([data-variant='ruled'], [data-variant='framed'])
1340
- :is([data-part='body'], [data-part='pinned-rows'])
1350
+ [data-ui-data-grid]:is([data-variant='ruled'], [data-variant='framed'])
1351
+ :is([data-part-body], [data-part-pinned-rows])
1341
1352
  > [role='row'] {
1342
1353
  border-block-end: var(--_rule-width) solid var(--_rule);
1343
1354
  }
1344
1355
 
1345
- [data-ui='data-grid']:is([data-variant='ruled'], [data-variant='framed'])
1346
- :is([data-part='body'], [data-part='pinned-rows'])
1356
+ [data-ui-data-grid]:is([data-variant='ruled'], [data-variant='framed'])
1357
+ :is([data-part-body], [data-part-pinned-rows])
1347
1358
  > [role='row']:last-child {
1348
1359
  border-block-end-color: transparent;
1349
1360
  }
1350
1361
 
1351
1362
  /* The stripe, declared before every state. */
1352
- [data-ui='data-grid'][data-striped]
1353
- > [data-part='scroll']
1354
- > :is([data-part='body'], [data-part='pinned-rows'])
1355
- > [data-part='row']:nth-child(even) {
1363
+ [data-ui-data-grid][data-striped]
1364
+ > [data-part-scroll]
1365
+ > :is([data-part-body], [data-part-pinned-rows])
1366
+ > [data-part-row]:nth-child(even) {
1356
1367
  background-color: var(--_stripe);
1357
1368
  }
1358
1369
 
@@ -1361,28 +1372,28 @@
1361
1372
  *
1362
1373
  * In the order `STATE_PRECEDENCE` declares them, weakest last.
1363
1374
  */
1364
- [data-ui='data-grid']
1365
- > [data-part='scroll']
1366
- > :is([data-part='body'], [data-part='pinned-rows'])
1367
- > [data-part='row']:not([data-disabled]):hover {
1375
+ [data-ui-data-grid]
1376
+ > [data-part-scroll]
1377
+ > :is([data-part-body], [data-part-pinned-rows])
1378
+ > [data-part-row]:not([data-disabled]):hover {
1368
1379
  background-color: var(--_hover);
1369
1380
  }
1370
1381
 
1371
- [data-ui='data-grid']
1372
- > [data-part='scroll']
1373
- > :is([data-part='body'], [data-part='pinned-rows'])
1374
- > [data-part='row'][data-selected] {
1382
+ [data-ui-data-grid]
1383
+ > [data-part-scroll]
1384
+ > :is([data-part-body], [data-part-pinned-rows])
1385
+ > [data-part-row][data-selected] {
1375
1386
  background-color: var(--_selected);
1376
1387
  color: var(--_selected-text);
1377
1388
  }
1378
1389
 
1379
- [data-ui='data-grid']
1380
- :is([data-part='body'], [data-part='pinned-rows'])
1381
- > [data-part='row'][data-selected]:not([data-disabled]):hover {
1390
+ [data-ui-data-grid]
1391
+ :is([data-part-body], [data-part-pinned-rows])
1392
+ > [data-part-row][data-selected]:not([data-disabled]):hover {
1382
1393
  background-color: var(--_selected-hover);
1383
1394
  }
1384
1395
 
1385
- [data-ui='data-grid'] [data-part='row'][data-disabled] {
1396
+ [data-ui-data-grid] [data-part-row][data-disabled] {
1386
1397
  color: var(--slotted-disabled-foreground, GrayText);
1387
1398
  }
1388
1399
 
@@ -1395,9 +1406,9 @@
1395
1406
  * cell has no margin for an outer ring and the row below would cover it.
1396
1407
  * A cell in edit draws nothing: its control draws the inner ring.
1397
1408
  */
1398
- [data-ui='data-grid'] [role='gridcell'][data-current]:not([data-editing]),
1399
- [data-ui='data-grid'] [role='rowheader'][data-current]:not([data-editing]),
1400
- [data-ui='data-grid'] [role='columnheader'][data-current] {
1409
+ [data-ui-data-grid] [role='gridcell'][data-current]:not([data-editing]),
1410
+ [data-ui-data-grid] [role='rowheader'][data-current]:not([data-editing]),
1411
+ [data-ui-data-grid] [role='columnheader'][data-current] {
1401
1412
  /* An inset shadow rather than an outline: an outline is a focus ring by
1402
1413
  the library's rule and is drawn in the ring colour whole; this is the
1403
1414
  place the reader left, at rest. */
@@ -1407,9 +1418,9 @@
1407
1418
  /* The grid's own cells, the children of its rows: a chip in a multi-select
1408
1419
  is a `gridcell` too, of the grid pattern the chips row is, and must keep
1409
1420
  its own ring rather than take this one. */
1410
- [data-ui='data-grid'] [role='row'] > [role='gridcell']:focus-visible:not([data-editing]),
1411
- [data-ui='data-grid'] [role='row'] > [role='rowheader']:focus-visible:not([data-editing]),
1412
- [data-ui='data-grid'] [role='row'] > [role='columnheader']:focus-visible {
1421
+ [data-ui-data-grid] [role='row'] > [role='gridcell']:focus-visible:not([data-editing]),
1422
+ [data-ui-data-grid] [role='row'] > [role='rowheader']:focus-visible:not([data-editing]),
1423
+ [data-ui-data-grid] [role='row'] > [role='columnheader']:focus-visible {
1413
1424
  box-shadow: none;
1414
1425
  outline: var(--_ring-width) solid var(--slotted-focus-ring-color, Highlight);
1415
1426
  outline-offset: calc(var(--_ring-width) * -1);
@@ -1419,8 +1430,8 @@
1419
1430
  draws none, so there are not two. A cell in edit and a filter cell are
1420
1431
  the other way round — the control inside is silenced and the cell draws
1421
1432
  the trace — so they are left out. */
1422
- [data-ui='data-grid']
1423
- [role='gridcell'][data-current]:not([data-editing], [data-part='filter-cell']):focus-within:not(
1433
+ [data-ui-data-grid]
1434
+ [role='gridcell'][data-current]:not([data-editing], [data-part-filter-cell]):focus-within:not(
1424
1435
  :focus
1425
1436
  ) {
1426
1437
  outline: none;
@@ -1435,11 +1446,11 @@
1435
1446
  * pseudo-element rather than a border, because the cell's own bottom border
1436
1447
  * is the rule between rows.
1437
1448
  */
1438
- [data-ui='data-grid'] [data-part='cell'][data-in-range] {
1449
+ [data-ui-data-grid] [data-part-cell][data-in-range] {
1439
1450
  background-color: var(--_range);
1440
1451
  }
1441
1452
 
1442
- [data-ui='data-grid'] [data-part='cell'][data-range-edge]::before {
1453
+ [data-ui-data-grid] [data-part-cell][data-range-edge]::before {
1443
1454
  border: 0 solid var(--_cursor);
1444
1455
  content: '';
1445
1456
  /* Past the cell's own bottom border, so a vertical edge runs unbroken
@@ -1449,22 +1460,22 @@
1449
1460
  position: absolute;
1450
1461
  }
1451
1462
 
1452
- [data-ui='data-grid'] [data-part='cell'][data-range-edge~='top']::before {
1463
+ [data-ui-data-grid] [data-part-cell][data-range-edge~='top']::before {
1453
1464
  border-block-start-width: var(--_ring-width);
1454
1465
  }
1455
1466
 
1456
1467
  /* The bottom edge ends at the cell: run past it, over the row's rule, it
1457
1468
  read one pixel thicker than the other three. */
1458
- [data-ui='data-grid'] [data-part='cell'][data-range-edge~='bottom']::before {
1469
+ [data-ui-data-grid] [data-part-cell][data-range-edge~='bottom']::before {
1459
1470
  border-block-end-width: var(--_ring-width);
1460
1471
  inset-block-end: 0;
1461
1472
  }
1462
1473
 
1463
- [data-ui='data-grid'] [data-part='cell'][data-range-edge~='start']::before {
1474
+ [data-ui-data-grid] [data-part-cell][data-range-edge~='start']::before {
1464
1475
  border-inline-start-width: var(--_ring-width);
1465
1476
  }
1466
1477
 
1467
- [data-ui='data-grid'] [data-part='cell'][data-range-edge~='end']::before {
1478
+ [data-ui-data-grid] [data-part-cell][data-range-edge~='end']::before {
1468
1479
  border-inline-end-width: var(--_ring-width);
1469
1480
  }
1470
1481
 
@@ -1476,7 +1487,7 @@
1476
1487
  * The control is the row's height, so a row in edit is as tall as one that
1477
1488
  * is not.
1478
1489
  */
1479
- [data-ui='data-grid'] [data-part='cell'][data-editing] {
1490
+ [data-ui-data-grid] [data-part-cell][data-editing] {
1480
1491
  --slotted-control-padding-inline-sm: var(--_pad-inline);
1481
1492
  --slotted-control-padding-inline-md: var(--_pad-inline);
1482
1493
  --slotted-control-padding-inline-lg: var(--_pad-inline);
@@ -1507,7 +1518,7 @@
1507
1518
  padding: 0;
1508
1519
  }
1509
1520
 
1510
- [data-ui='data-grid'] [data-part='cell'][data-editing][data-current] {
1521
+ [data-ui-data-grid] [data-part-cell][data-editing][data-current] {
1511
1522
  box-shadow: none;
1512
1523
  outline: var(--_ring-width) solid var(--slotted-focus-ring-color, Highlight);
1513
1524
  outline-offset: calc(var(--_ring-width) * -1);
@@ -1517,7 +1528,7 @@
1517
1528
  does — by pointing the ring at the invalid step: `invalid` does not erase
1518
1529
  focus. The descendants' ring width is already zero, so the token moves
1519
1530
  only this cell's own trace. */
1520
- [data-ui='data-grid'] [data-part='cell'][data-editing][data-invalid] {
1531
+ [data-ui-data-grid] [data-part-cell][data-editing][data-invalid] {
1521
1532
  --slotted-focus-ring-color: var(--slotted-focus-ring-color-invalid);
1522
1533
  /* Width as well as colour (WCAG 1.4.1): in `high-contrast` the invalid ring
1523
1534
  is the valid ring's black, and the corner mark is withdrawn while the
@@ -1532,11 +1543,11 @@
1532
1543
 
1533
1544
  /* The editor of a numeric column keeps the digits at the end, where the
1534
1545
  read value stood. */
1535
- [data-ui='data-grid'] [data-numeric][data-editing] [data-part='input'] {
1546
+ [data-ui-data-grid] [data-numeric][data-editing] [data-part-input] {
1536
1547
  text-align: end;
1537
1548
  }
1538
1549
 
1539
- [data-ui='data-grid'] [data-part='cell'] > [data-part='editor'] {
1550
+ [data-ui-data-grid] [data-part-cell] > [data-part-editor] {
1540
1551
  display: flex;
1541
1552
  flex: 1 1 auto;
1542
1553
  /* Inside the cell's trace, at every density. */
@@ -1544,12 +1555,8 @@
1544
1555
  min-inline-size: 0;
1545
1556
  }
1546
1557
 
1547
- [data-ui='data-grid'] [data-part='cell'] > [data-part='editor'] > [data-part='root'],
1548
- [data-ui='data-grid']
1549
- [data-part='cell']
1550
- > [data-part='editor']
1551
- > :not([data-part])
1552
- > [data-part='root'] {
1558
+ [data-ui-data-grid] [data-part-cell] > [data-part-editor] > [data-part-root],
1559
+ [data-ui-data-grid] [data-part-cell] > [data-part-editor] > :not([data-part]) > [data-part-root] {
1553
1560
  flex: 1 1 auto;
1554
1561
  min-inline-size: 0;
1555
1562
  }
@@ -1563,13 +1570,13 @@
1563
1570
  * outside the motion scale; under reduced motion the ground stays flat and
1564
1571
  * leaves when the mark does.
1565
1572
  */
1566
- [data-ui='data-grid'] [data-part='cell'][data-changed='a'] {
1573
+ [data-ui-data-grid] [data-part-cell][data-changed='a'] {
1567
1574
  animation: slotted-data-grid-changed-a
1568
1575
  var(--slotted-data-grid-changed-duration, var(--slotted-duration-long))
1569
1576
  var(--slotted-easing-standard, ease-out) forwards;
1570
1577
  }
1571
1578
 
1572
- [data-ui='data-grid'] [data-part='cell'][data-changed='b'] {
1579
+ [data-ui-data-grid] [data-part-cell][data-changed='b'] {
1573
1580
  animation: slotted-data-grid-changed-b
1574
1581
  var(--slotted-data-grid-changed-duration, var(--slotted-duration-long))
1575
1582
  var(--slotted-easing-standard, ease-out) forwards;
@@ -1600,12 +1607,12 @@
1600
1607
  }
1601
1608
 
1602
1609
  @media (prefers-reduced-motion: reduce) {
1603
- [data-ui='data-grid'] [data-part='cell'][data-changed] {
1610
+ [data-ui-data-grid] [data-part-cell][data-changed] {
1604
1611
  animation: none;
1605
1612
  background-color: var(--_changed);
1606
1613
  }
1607
1614
 
1608
- [data-ui='data-grid'] button[data-part='tree-toggle'][data-loading] > [data-ui='icon'] {
1615
+ [data-ui-data-grid] button[data-part-tree-toggle][data-loading] > [data-ui-icon] {
1609
1616
  animation: none;
1610
1617
  }
1611
1618
  }
@@ -1613,7 +1620,7 @@
1613
1620
  /* A cell whose draft failed, or whose value changed under the reader. The
1614
1621
  mark is a corner in the danger ink, and the message is the control's own
1615
1622
  `aria-errormessage`; the cell keeps the draft. */
1616
- [data-ui='data-grid'] [data-part='cell'][data-invalid]:not([data-editing])::after {
1623
+ [data-ui-data-grid] [data-part-cell][data-invalid]:not([data-editing])::after {
1617
1624
  border-block-start: var(--slotted-space-3, 0.375rem) solid var(--slotted-tone-danger-border);
1618
1625
  border-inline-start: var(--slotted-space-3, 0.375rem) solid transparent;
1619
1626
  content: '';
@@ -1626,39 +1633,39 @@
1626
1633
  }
1627
1634
 
1628
1635
  /* A cell whose commit is pending dims its value; nothing moves. */
1629
- [data-ui='data-grid'] [data-part='cell'][data-loading] {
1636
+ [data-ui-data-grid] [data-part-cell][data-loading] {
1630
1637
  color: var(--_muted);
1631
1638
  }
1632
1639
 
1633
1640
  /* A cell that does not edit in a grid that does: no mark, no hand. It is a
1634
1641
  fact the reader hears, not one the eye needs. */
1635
- [data-ui='data-grid'] [data-part='cell'][data-readonly] {
1642
+ [data-ui-data-grid] [data-part-cell][data-readonly] {
1636
1643
  cursor: default;
1637
1644
  }
1638
1645
 
1639
1646
  /**
1640
1647
  * ── Alignment, numerals and the text treatment ─────────────────────────
1641
1648
  */
1642
- [data-ui='data-grid'] [data-align='start'] {
1649
+ [data-ui-data-grid] [data-align='start'] {
1643
1650
  justify-content: start;
1644
1651
  text-align: start;
1645
1652
  }
1646
1653
 
1647
- [data-ui='data-grid'] [data-align='center'] {
1654
+ [data-ui-data-grid] [data-align='center'] {
1648
1655
  justify-content: center;
1649
1656
  text-align: center;
1650
1657
  }
1651
1658
 
1652
- [data-ui='data-grid'] [data-align='end'] {
1659
+ [data-ui-data-grid] [data-align='end'] {
1653
1660
  justify-content: end;
1654
1661
  text-align: end;
1655
1662
  }
1656
1663
 
1657
- [data-ui='data-grid'] [data-numeric] {
1664
+ [data-ui-data-grid] [data-numeric] {
1658
1665
  font-variant-numeric: tabular-nums;
1659
1666
  }
1660
1667
 
1661
- [data-ui='data-grid'] [data-numeric]:not([data-align]) {
1668
+ [data-ui-data-grid] [data-numeric]:not([data-align]) {
1662
1669
  justify-content: end;
1663
1670
  text-align: end;
1664
1671
  }
@@ -1668,7 +1675,7 @@
1668
1675
  is the span with no part of its own — in a tree column the toggle comes
1669
1676
  first, and a rule on `:first-child` left "Barcelona" drawn over the next
1670
1677
  column once the column was narrower than the name. */
1671
- [data-ui='data-grid'] [data-text='truncate'] > span:not([data-ui], [data-part]) {
1678
+ [data-ui-data-grid] [data-text='truncate'] > span:not([data-ui], [data-part]) {
1672
1679
  overflow: hidden;
1673
1680
  text-overflow: ellipsis;
1674
1681
  white-space: nowrap;
@@ -1677,12 +1684,12 @@
1677
1684
  /* A value that is never broken is clipped at its cell rather than drawn over
1678
1685
  the next one: a grid's columns are its layout, and a value crossing one is
1679
1686
  a value in the wrong column. */
1680
- [data-ui='data-grid'] [data-text='nowrap'] > span:not([data-ui], [data-part]) {
1687
+ [data-ui-data-grid] [data-text='nowrap'] > span:not([data-ui], [data-part]) {
1681
1688
  overflow: hidden;
1682
1689
  white-space: nowrap;
1683
1690
  }
1684
1691
 
1685
- [data-ui='data-grid'] [data-text='wrap'] > span:not([data-ui], [data-part]) {
1692
+ [data-ui-data-grid] [data-text='wrap'] > span:not([data-ui], [data-part]) {
1686
1693
  overflow-wrap: anywhere;
1687
1694
  }
1688
1695
 
@@ -1696,14 +1703,14 @@
1696
1703
  * the rules rather than as a border, for the reason `table` records: two
1697
1704
  * borders of one box are mitred at the corner.
1698
1705
  */
1699
- [data-ui='data-grid'] [data-pinned='start'] {
1706
+ [data-ui-data-grid] [data-pinned='start'] {
1700
1707
  background-color: inherit;
1701
1708
  inset-inline-start: var(--slotted-data-grid-pin-offset, 0);
1702
1709
  position: sticky;
1703
1710
  z-index: var(--slotted-z-index-sticky, 100);
1704
1711
  }
1705
1712
 
1706
- [data-ui='data-grid'] [data-pinned='end'] {
1713
+ [data-ui-data-grid] [data-pinned='end'] {
1707
1714
  background-color: inherit;
1708
1715
  inset-inline-end: var(--slotted-data-grid-pin-offset, 0);
1709
1716
  position: sticky;
@@ -1711,7 +1718,7 @@
1711
1718
  }
1712
1719
 
1713
1720
  /* The corner: a header cell that is also pinned takes the step above both. */
1714
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='head'] [data-pinned] {
1721
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-head] [data-pinned] {
1715
1722
  background-color: var(--_head-surface);
1716
1723
  z-index: calc(var(--slotted-z-index-sticky, 100) + 2);
1717
1724
  }
@@ -1719,33 +1726,30 @@
1719
1726
  /* A plain header has no band: a pinned header cell takes the page's ground,
1720
1727
  opaque over the names sliding under it, and not the band it would be the
1721
1728
  only piece of — read on the pop-in scene, a grey block behind one name. */
1722
- [data-ui='data-grid'][data-variant='plain']
1723
- > [data-part='scroll']
1724
- > [data-part='head']
1725
- [data-pinned],
1726
- [data-ui='data-grid'][data-variant='plain']
1727
- > [data-part='scroll']
1728
- > [data-part='head']
1729
+ [data-ui-data-grid][data-variant='plain'] > [data-part-scroll] > [data-part-head] [data-pinned],
1730
+ [data-ui-data-grid][data-variant='plain']
1731
+ > [data-part-scroll]
1732
+ > [data-part-head]
1729
1733
  > [role='row']
1730
- > [data-part='selection'] {
1734
+ > [data-part-selection] {
1731
1735
  background-color: var(--_surface);
1732
1736
  }
1733
1737
 
1734
- [data-ui='data-grid'] [data-part='filter-row'] > [data-pinned] {
1738
+ [data-ui-data-grid] [data-part-filter-row] > [data-pinned] {
1735
1739
  background-color: var(--_band-surface);
1736
1740
  }
1737
1741
 
1738
- [data-ui='data-grid']
1739
- > [data-part='scroll']
1740
- > :is([data-part='body'], [data-part='pinned-rows'])
1741
- > [data-part='row'][data-selected]
1742
+ [data-ui-data-grid]
1743
+ > [data-part-scroll]
1744
+ > :is([data-part-body], [data-part-pinned-rows])
1745
+ > [data-part-row][data-selected]
1742
1746
  > [data-pinned] {
1743
1747
  background-color: var(--_selected);
1744
1748
  }
1745
1749
 
1746
1750
  /* The last pinned cell of each zone draws the edge: the same hairline as
1747
1751
  the rules between rows, and no more. */
1748
- [data-ui='data-grid'] [data-pinned][data-pin-edge]::after {
1752
+ [data-ui-data-grid] [data-pinned][data-pin-edge]::after {
1749
1753
  background-color: var(--_rule);
1750
1754
  content: '';
1751
1755
  inline-size: var(--_rule-width);
@@ -1756,19 +1760,19 @@
1756
1760
  z-index: 1;
1757
1761
  }
1758
1762
 
1759
- [data-ui='data-grid']
1760
- > [data-part='scroll']
1761
- > :is([data-part='body'], [data-part='pinned-rows'])
1763
+ [data-ui-data-grid]
1764
+ > [data-part-scroll]
1765
+ > :is([data-part-body], [data-part-pinned-rows])
1762
1766
  > [role='row']:last-child
1763
1767
  > [data-pin-edge]::after {
1764
1768
  inset-block-end: 0;
1765
1769
  }
1766
1770
 
1767
- [data-ui='data-grid'] [data-pinned='start'][data-pin-edge]::after {
1771
+ [data-ui-data-grid] [data-pinned='start'][data-pin-edge]::after {
1768
1772
  inset-inline-end: 0;
1769
1773
  }
1770
1774
 
1771
- [data-ui='data-grid'] [data-pinned='end'][data-pin-edge]::after {
1775
+ [data-ui-data-grid] [data-pinned='end'][data-pin-edge]::after {
1772
1776
  inset-inline-start: 0;
1773
1777
  }
1774
1778
 
@@ -1776,7 +1780,7 @@
1776
1780
  run down the body: it stood as a stub beside each values' line. At rest
1777
1781
  a grid with a pop-in draws no edge; the shadow below still marks what
1778
1782
  slides under a zone. */
1779
- [data-ui='data-grid'][data-popin] [data-pinned][data-pin-edge]::after {
1783
+ [data-ui-data-grid][data-popin] [data-pinned][data-pin-edge]::after {
1780
1784
  background-color: transparent;
1781
1785
  }
1782
1786
 
@@ -1786,11 +1790,11 @@
1786
1790
  mid-word is not always there to be seen. A shadow and not a stronger
1787
1791
  line: read on the pinning scene, a dark rule down the body read as a
1788
1792
  frame inside the frame. */
1789
- [data-ui='data-grid']
1790
- [data-part='scroll'][data-overflowing]:not([data-at-start])
1793
+ [data-ui-data-grid]
1794
+ [data-part-scroll][data-overflowing]:not([data-at-start])
1791
1795
  [data-pinned='start'][data-pin-edge]::after,
1792
- [data-ui='data-grid']
1793
- [data-part='scroll'][data-overflowing]:not([data-at-end])
1796
+ [data-ui-data-grid]
1797
+ [data-part-scroll][data-overflowing]:not([data-at-end])
1794
1798
  [data-pinned='end'][data-pin-edge]::after {
1795
1799
  /* The colour is the gradient's alone: with the hairline's colour still
1796
1800
  under the widened box, the shadow read as a solid grey band. */
@@ -1798,8 +1802,8 @@
1798
1802
  inline-size: calc(var(--_rule-width) + var(--_edge-shadow-size));
1799
1803
  }
1800
1804
 
1801
- [data-ui='data-grid']
1802
- [data-part='scroll'][data-overflowing]:not([data-at-start])
1805
+ [data-ui-data-grid]
1806
+ [data-part-scroll][data-overflowing]:not([data-at-start])
1803
1807
  [data-pinned='start'][data-pin-edge]::after {
1804
1808
  background-image: linear-gradient(
1805
1809
  to right,
@@ -1810,8 +1814,8 @@
1810
1814
  inset-inline-end: calc(var(--_edge-shadow-size) * -1);
1811
1815
  }
1812
1816
 
1813
- [data-ui='data-grid']
1814
- [data-part='scroll'][data-overflowing]:not([data-at-end])
1817
+ [data-ui-data-grid]
1818
+ [data-part-scroll][data-overflowing]:not([data-at-end])
1815
1819
  [data-pinned='end'][data-pin-edge]::after {
1816
1820
  background-image: linear-gradient(
1817
1821
  to left,
@@ -1822,8 +1826,8 @@
1822
1826
  inset-inline-start: calc(var(--_edge-shadow-size) * -1);
1823
1827
  }
1824
1828
 
1825
- [data-ui='data-grid']:dir(rtl)
1826
- [data-part='scroll'][data-overflowing]:not([data-at-start])
1829
+ [data-ui-data-grid]:dir(rtl)
1830
+ [data-part-scroll][data-overflowing]:not([data-at-start])
1827
1831
  [data-pinned='start'][data-pin-edge]::after {
1828
1832
  background-image: linear-gradient(
1829
1833
  to left,
@@ -1833,8 +1837,8 @@
1833
1837
  );
1834
1838
  }
1835
1839
 
1836
- [data-ui='data-grid']:dir(rtl)
1837
- [data-part='scroll'][data-overflowing]:not([data-at-end])
1840
+ [data-ui-data-grid]:dir(rtl)
1841
+ [data-part-scroll][data-overflowing]:not([data-at-end])
1838
1842
  [data-pinned='end'][data-pin-edge]::after {
1839
1843
  background-image: linear-gradient(
1840
1844
  to right,
@@ -1850,7 +1854,7 @@
1850
1854
  * The cell is the family's and the control is `checkbox`'s. The width is
1851
1855
  * stated so a column pinned beside it has a length to state.
1852
1856
  */
1853
- [data-ui='data-grid'] [role='row'] > [data-part='selection'] {
1857
+ [data-ui-data-grid] [role='row'] > [data-part-selection] {
1854
1858
  --slotted-selection-halo-opacity: 0;
1855
1859
 
1856
1860
  justify-content: center;
@@ -1865,7 +1869,7 @@
1865
1869
  * X both pin it with the first pinned column; here it is pinned always, so a
1866
1870
  * consumer never has to say it.
1867
1871
  */
1868
- [data-ui='data-grid'] [role='row'] > [data-part='selection'] {
1872
+ [data-ui-data-grid] [role='row'] > [data-part-selection] {
1869
1873
  background-color: inherit;
1870
1874
  inset-inline-start: 0;
1871
1875
  position: sticky;
@@ -1875,25 +1879,25 @@
1875
1879
  /* Restated for the head's chooser, whose header rule above made it
1876
1880
  `relative` at a higher specificity: read scrolled, the select-all left
1877
1881
  with the columns while every row's chooser stayed. */
1878
- [data-ui='data-grid']
1879
- > [data-part='scroll']
1880
- > [data-part='head']
1882
+ [data-ui-data-grid]
1883
+ > [data-part-scroll]
1884
+ > [data-part-head]
1881
1885
  > [role='row']
1882
- > [data-part='selection'] {
1886
+ > [data-part-selection] {
1883
1887
  background-color: var(--_head-surface);
1884
1888
  inset-inline-start: 0;
1885
1889
  position: sticky;
1886
1890
  z-index: calc(var(--slotted-z-index-sticky, 100) + 2);
1887
1891
  }
1888
1892
 
1889
- [data-ui='data-grid']
1890
- :is([data-part='body'], [data-part='pinned-rows'])
1891
- > [data-part='row'][data-selected]
1892
- > [data-part='selection'] {
1893
+ [data-ui-data-grid]
1894
+ :is([data-part-body], [data-part-pinned-rows])
1895
+ > [data-part-row][data-selected]
1896
+ > [data-part-selection] {
1893
1897
  background-color: var(--_selected);
1894
1898
  }
1895
1899
 
1896
- [data-ui='data-grid'] [role='row'] > [data-part='selection'] > [data-ui='checkbox'] {
1900
+ [data-ui-data-grid] [role='row'] > [data-part-selection] > [data-ui-checkbox] {
1897
1901
  block-size: var(--_line);
1898
1902
  }
1899
1903
 
@@ -1901,7 +1905,7 @@
1901
1905
  it rather than the stylesheet asking every cell what it holds: `:has()`
1902
1906
  on every cell of a windowed body is a question asked a thousand times per
1903
1907
  style pass. */
1904
- [data-ui='data-grid'] [data-part='cell'][data-kind='expander'] {
1908
+ [data-ui-data-grid] [data-part-cell][data-kind='expander'] {
1905
1909
  justify-content: center;
1906
1910
  padding-inline: 0;
1907
1911
  }
@@ -1912,11 +1916,11 @@
1912
1916
  * One cell spanning every column, on the sunken ground, with the record's
1913
1917
  * own inset so what is inside reads as belonging to the row above.
1914
1918
  */
1915
- [data-ui='data-grid'] [data-part='detail'] {
1919
+ [data-ui-data-grid] [data-part-detail] {
1916
1920
  background-color: var(--slotted-surface-sunken, Canvas);
1917
1921
  }
1918
1922
 
1919
- [data-ui='data-grid'] [data-part='detail'] > * {
1923
+ [data-ui-data-grid] [data-part-detail] > * {
1920
1924
  background-color: var(--slotted-surface-sunken, Canvas);
1921
1925
  box-sizing: border-box;
1922
1926
  grid-column: 1 / -1;
@@ -1946,28 +1950,28 @@
1946
1950
  */
1947
1951
  /* The values' line is the density's row, grown to its content; the
1948
1952
  pop-in's line is as tall as its fields. */
1949
- [data-ui='data-grid'][data-popin]
1950
- > [data-part='scroll']
1951
- > :is([data-part='body'], [data-part='pinned-rows'])
1952
- > [data-part='row'] {
1953
+ [data-ui-data-grid][data-popin]
1954
+ > [data-part-scroll]
1955
+ > :is([data-part-body], [data-part-pinned-rows])
1956
+ > [data-part-row] {
1953
1957
  grid-template-rows: minmax(var(--_track), auto) auto;
1954
1958
  }
1955
1959
 
1956
- [data-ui='data-grid'][data-popin] > [data-part='scroll'] > [data-part='summary'] > [role='row'] {
1960
+ [data-ui-data-grid][data-popin] > [data-part-scroll] > [data-part-summary] > [role='row'] {
1957
1961
  grid-template-rows: minmax(var(--_head-block), auto) auto;
1958
1962
  }
1959
1963
 
1960
1964
  /* The chooser, the expander, the values and the actions stand on the
1961
1965
  values' line centred, as in a fixed row: the line is the row's own
1962
1966
  height, and a wrapped value is the only thing that grows it. */
1963
- [data-ui='data-grid'][data-popin]
1964
- :is([data-part='body'], [data-part='pinned-rows'])
1965
- > [data-part='row']
1966
- > :is([role='gridcell'], [role='rowheader']):not([data-part='popin']) {
1967
+ [data-ui-data-grid][data-popin]
1968
+ :is([data-part-body], [data-part-pinned-rows])
1969
+ > [data-part-row]
1970
+ > :is([role='gridcell'], [role='rowheader']):not([data-part-popin]) {
1967
1971
  align-items: center;
1968
1972
  }
1969
1973
 
1970
- [data-ui='data-grid'] [data-part='popin'] {
1974
+ [data-ui-data-grid] [data-part-popin] {
1971
1975
  align-content: start;
1972
1976
  box-sizing: border-box;
1973
1977
  column-gap: var(--slotted-space-4, 0.5rem);
@@ -1991,14 +1995,14 @@
1991
1995
  column of fields where the row's whole width holds two. The fields start
1992
1996
  at the row's own padding, under the chooser. */
1993
1997
  @container slotted-data-grid (width < 600px) {
1994
- [data-ui='data-grid'] [data-part='popin'] {
1998
+ [data-ui-data-grid] [data-part-popin] {
1995
1999
  padding-inline-start: var(--_pad-inline);
1996
2000
  }
1997
2001
  }
1998
2002
 
1999
2003
  /* The label above the value, as a form reads, so a narrow field keeps the
2000
2004
  value's whole width. */
2001
- [data-ui='data-grid'] [data-part='popin-field'] {
2005
+ [data-ui-data-grid] [data-part-popin-field] {
2002
2006
  display: flex;
2003
2007
  flex-direction: column;
2004
2008
  min-inline-size: 0;
@@ -2007,7 +2011,7 @@
2007
2011
  /* Room for one column of fields only (two need 2 × 9rem and the gap): the
2008
2012
  label goes beside its value, so each field takes one line instead of two. */
2009
2013
  @container slotted-data-grid-popin (width < 19rem) {
2010
- [data-ui='data-grid'] [data-part='popin-field'] {
2014
+ [data-ui-data-grid] [data-part-popin-field] {
2011
2015
  align-items: baseline;
2012
2016
  column-gap: var(--slotted-space-3, 0.375rem);
2013
2017
  display: grid;
@@ -2015,7 +2019,7 @@
2015
2019
  }
2016
2020
  }
2017
2021
 
2018
- [data-ui='data-grid'] [data-part='popin-label'] {
2022
+ [data-ui-data-grid] [data-part-popin-label] {
2019
2023
  color: var(--_muted);
2020
2024
  font-size: var(--slotted-font-size-xs, 0.75rem);
2021
2025
  font-weight: var(--slotted-font-weight-regular, 400);
@@ -2026,7 +2030,7 @@
2026
2030
  field under a label at its start reads as the next field's. One line tall
2027
2031
  when empty, so an empty value keeps its place under its label, as the
2028
2032
  empty cell keeps its row. */
2029
- [data-ui='data-grid'] [data-part='popin-value'] {
2033
+ [data-ui-data-grid] [data-part-popin-value] {
2030
2034
  align-items: center;
2031
2035
  display: flex;
2032
2036
  gap: var(--_gap);
@@ -2042,8 +2046,8 @@
2042
2046
  aligns its lines to the grid's start, under its label: read in `rtl`, a
2043
2047
  company name set by its own direction ran from the far edge of the field,
2044
2048
  and `match-parent` did not move it. */
2045
- [data-ui='data-grid'] [data-part='popin-value'][data-text] > span:not([data-ui], [data-part]),
2046
- [data-ui='data-grid'] [data-part='popin-value'] > span:not([data-ui], [data-part]) {
2049
+ [data-ui-data-grid] [data-part-popin-value][data-text] > span:not([data-ui], [data-part]),
2050
+ [data-ui-data-grid] [data-part-popin-value] > span:not([data-ui], [data-part]) {
2047
2051
  flex: 0 1 auto;
2048
2052
  min-inline-size: 0;
2049
2053
  overflow: visible;
@@ -2055,11 +2059,11 @@
2055
2059
  }
2056
2060
 
2057
2061
  /* Physical, because `start` under `plaintext` is the value's own start. */
2058
- [data-ui='data-grid']:dir(rtl) [data-part='popin-value'] > span:not([data-ui], [data-part]) {
2062
+ [data-ui-data-grid]:dir(rtl) [data-part-popin-value] > span:not([data-ui], [data-part]) {
2059
2063
  text-align: right;
2060
2064
  }
2061
2065
 
2062
- [data-ui='data-grid'] [data-part='popin-value'] > [data-ui]:not([data-part]) {
2066
+ [data-ui-data-grid] [data-part-popin-value] > [data-ui]:not([data-part]) {
2063
2067
  flex: 0 0 auto;
2064
2068
  max-inline-size: 100%;
2065
2069
  }
@@ -2071,13 +2075,13 @@
2071
2075
  * indented by its level. The ground is the band at 4%, and the text is
2072
2076
  * semibold, so a reader scanning for a group finds it without reading.
2073
2077
  */
2074
- [data-ui='data-grid'] [data-part='group-row'] {
2078
+ [data-ui-data-grid] [data-part-group-row] {
2075
2079
  background-color: var(--_band-surface);
2076
2080
  color: var(--_text);
2077
2081
  font-weight: var(--slotted-font-weight-semibold, 600);
2078
2082
  }
2079
2083
 
2080
- [data-ui='data-grid'] [data-part='group-row'] > [role='gridcell'] {
2084
+ [data-ui-data-grid] [data-part-group-row] > [role='gridcell'] {
2081
2085
  align-items: center;
2082
2086
  box-sizing: border-box;
2083
2087
  display: flex;
@@ -2090,7 +2094,7 @@
2090
2094
 
2091
2095
  /* The first cell of a group row spans to the first aggregate, indented by
2092
2096
  its level; the aggregates stand in their own columns. */
2093
- [data-ui='data-grid'] [data-part='group-row'] > [role='gridcell']:first-child {
2097
+ [data-ui-data-grid] [data-part-group-row] > [role='gridcell']:first-child {
2094
2098
  padding-inline-start: calc(
2095
2099
  var(--_pad-inline) + var(--_indent) * (var(--slotted-data-grid-level, 1) - 1)
2096
2100
  );
@@ -2098,25 +2102,25 @@
2098
2102
  inset-inline-start: 0;
2099
2103
  }
2100
2104
 
2101
- [data-ui='data-grid'] [data-part='group-row'] > [role='gridcell']:first-child > span {
2105
+ [data-ui-data-grid] [data-part-group-row] > [role='gridcell']:first-child > span {
2102
2106
  overflow: hidden;
2103
2107
  text-overflow: ellipsis;
2104
2108
  white-space: nowrap;
2105
2109
  }
2106
2110
 
2107
2111
  /* The count, one step lighter than the value. */
2108
- [data-ui='data-grid'] [data-part='group-row'] [data-count] {
2112
+ [data-ui-data-grid] [data-part-group-row] [data-count] {
2109
2113
  color: var(--_muted);
2110
2114
  font-weight: var(--slotted-font-weight-regular, 400);
2111
2115
  }
2112
2116
 
2113
- [data-ui='data-grid'] [data-part='group-row'] [data-aggregate] {
2117
+ [data-ui-data-grid] [data-part-group-row] [data-aggregate] {
2114
2118
  color: var(--_muted);
2115
2119
  font-variant-numeric: tabular-nums;
2116
2120
  font-weight: var(--slotted-font-weight-medium, 500);
2117
2121
  }
2118
2122
 
2119
- [data-ui='data-grid'] [data-part='group-toggle'] {
2123
+ [data-ui-data-grid] [data-part-group-toggle] {
2120
2124
  margin-block: calc((var(--_line) - var(--slotted-target-min, 24px)) / 2);
2121
2125
  margin-inline-start: calc(var(--slotted-space-2, 0.25rem) * -1);
2122
2126
  }
@@ -2127,13 +2131,13 @@
2127
2131
  * The aggregates of the whole query, pinned to the end of the scroller, on
2128
2132
  * the band with a strong rule above — the header of the other end.
2129
2133
  */
2130
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='summary'] {
2134
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-summary] {
2131
2135
  inset-block-end: var(--slotted-data-grid-sticky-offset-end, 0);
2132
2136
  position: sticky;
2133
2137
  z-index: calc(var(--slotted-z-index-sticky, 100) + 1);
2134
2138
  }
2135
2139
 
2136
- [data-ui='data-grid']:not([data-sticky-header]) > [data-part='scroll'] > [data-part='summary'] {
2140
+ [data-ui-data-grid]:not([data-sticky-header]) > [data-part-scroll] > [data-part-summary] {
2137
2141
  position: static;
2138
2142
  }
2139
2143
 
@@ -2145,20 +2149,20 @@
2145
2149
  * surface so the body scrolls under it, with a rule on the side it faces
2146
2150
  * the body. Their rows are the body's rows.
2147
2151
  */
2148
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='pinned-rows'] {
2152
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-pinned-rows] {
2149
2153
  background-color: var(--_surface);
2150
2154
  position: sticky;
2151
2155
  z-index: calc(var(--slotted-z-index-sticky, 100) + 1);
2152
2156
  }
2153
2157
 
2154
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='pinned-rows'][data-edge='top'] {
2158
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-pinned-rows][data-edge='top'] {
2155
2159
  border-block-end: var(--_rule-width) solid var(--_rule-strong);
2156
2160
  inset-block-start: calc(
2157
2161
  var(--slotted-data-grid-sticky-offset, 0px) + var(--slotted-data-grid-pinned-top-offset, 0px)
2158
2162
  );
2159
2163
  }
2160
2164
 
2161
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='pinned-rows'][data-edge='bottom'] {
2165
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-pinned-rows][data-edge='bottom'] {
2162
2166
  border-block-start: var(--_rule-width) solid var(--_rule-strong);
2163
2167
  inset-block-end: calc(
2164
2168
  var(--slotted-data-grid-sticky-offset-end, 0px) +
@@ -2166,36 +2170,34 @@
2166
2170
  );
2167
2171
  }
2168
2172
 
2169
- [data-ui='data-grid']:not([data-sticky-header])
2170
- > [data-part='scroll']
2171
- > [data-part='pinned-rows'] {
2173
+ [data-ui-data-grid]:not([data-sticky-header]) > [data-part-scroll] > [data-part-pinned-rows] {
2172
2174
  position: static;
2173
2175
  }
2174
2176
 
2175
2177
  /* A pinned cell inside a held row stands over the row's own ground. */
2176
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='pinned-rows'] [data-pinned] {
2178
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-pinned-rows] [data-pinned] {
2177
2179
  background-color: var(--_surface);
2178
2180
  }
2179
2181
 
2180
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='summary'] > [role='row'] {
2182
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-summary] > [role='row'] {
2181
2183
  background-color: var(--_head-surface);
2182
2184
  border-block-start: var(--_rule-width) solid var(--_rule-strong);
2183
2185
  }
2184
2186
 
2185
- [data-ui='data-grid'] [data-part='summary-cell'] {
2187
+ [data-ui-data-grid] [data-part-summary-cell] {
2186
2188
  background-color: var(--_head-surface);
2187
2189
  font-weight: var(--slotted-font-weight-semibold, 600);
2188
2190
  min-block-size: var(--_head-block);
2189
2191
  }
2190
2192
 
2191
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='summary'] [data-pinned] {
2193
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-summary] [data-pinned] {
2192
2194
  background-color: var(--_head-surface);
2193
2195
  z-index: calc(var(--slotted-z-index-sticky, 100) + 2);
2194
2196
  }
2195
2197
 
2196
2198
  /* The label of an aggregate — "Total", "Average" — one step lighter than
2197
2199
  the number beside it. */
2198
- [data-ui='data-grid'] [data-part='summary-cell'] [data-label] {
2200
+ [data-ui-data-grid] [data-part-summary-cell] [data-label] {
2199
2201
  color: var(--_muted);
2200
2202
  font-weight: var(--slotted-font-weight-regular, 400);
2201
2203
  margin-inline-end: var(--slotted-space-2, 0.25rem);
@@ -2211,7 +2213,7 @@
2211
2213
  /* Scoped to the cell's own child: `result-state` in the empty part has an
2212
2214
  `actions` part of the same name, and a rule naming the part alone hid
2213
2215
  its buttons. */
2214
- [data-ui='data-grid'] [data-part='cell'] > [data-part='actions'] {
2216
+ [data-ui-data-grid] [data-part-cell] > [data-part-actions] {
2215
2217
  align-items: center;
2216
2218
  /* One line tall, whatever stands inside: the buttons are taller than the
2217
2219
  line and overflow it evenly, so the row is still measured by its text
@@ -2231,7 +2233,7 @@
2231
2233
  * scene, two of them stood five pixels proud of the row on both sides and
2232
2234
  * grew its track. The consumer keeps the behaviour and the artwork.
2233
2235
  */
2234
- [data-ui='data-grid'] [data-part='cell'] > [data-part='actions'] > button {
2236
+ [data-ui-data-grid] [data-part-cell] > [data-part-actions] > button {
2235
2237
  align-items: center;
2236
2238
  background-color: transparent;
2237
2239
  block-size: var(--_control);
@@ -2249,42 +2251,42 @@
2249
2251
  color var(--_transition);
2250
2252
  }
2251
2253
 
2252
- [data-ui='data-grid'] [data-part='cell'] > [data-part='actions'] > button :is(svg, img) {
2254
+ [data-ui-data-grid] [data-part-cell] > [data-part-actions] > button :is(svg, img) {
2253
2255
  block-size: var(--_control-icon);
2254
2256
  inline-size: var(--_control-icon);
2255
2257
  }
2256
2258
 
2257
- [data-ui='data-grid'] [data-part='cell'] > [data-part='actions'] > button:not(:disabled):hover {
2259
+ [data-ui-data-grid] [data-part-cell] > [data-part-actions] > button:not(:disabled):hover {
2258
2260
  background-color: color-mix(in oklab, var(--slotted-text, CanvasText) 7%, transparent);
2259
2261
  color: var(--_text);
2260
2262
  }
2261
2263
 
2262
- [data-ui='data-grid'] [data-part='cell'] > [data-part='actions'] > button:focus-visible {
2264
+ [data-ui-data-grid] [data-part-cell] > [data-part-actions] > button:focus-visible {
2263
2265
  outline: var(--_ring-width) solid var(--slotted-focus-ring-color, Highlight);
2264
2266
  outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
2265
2267
  }
2266
2268
 
2267
- [data-ui='data-grid']
2268
- [data-part='row']:not([data-disabled]):hover
2269
- [data-part='cell']
2270
- > [data-part='actions'],
2271
- [data-ui='data-grid'] [data-part='row']:focus-within [data-part='cell'] > [data-part='actions'],
2272
- [data-ui='data-grid'] [data-part='row'][data-current] [data-part='cell'] > [data-part='actions'],
2273
- [data-ui='data-grid'] [data-part='row'][data-editing] [data-part='cell'] > [data-part='actions'] {
2269
+ [data-ui-data-grid]
2270
+ [data-part-row]:not([data-disabled]):hover
2271
+ [data-part-cell]
2272
+ > [data-part-actions],
2273
+ [data-ui-data-grid] [data-part-row]:focus-within [data-part-cell] > [data-part-actions],
2274
+ [data-ui-data-grid] [data-part-row][data-current] [data-part-cell] > [data-part-actions],
2275
+ [data-ui-data-grid] [data-part-row][data-editing] [data-part-cell] > [data-part-actions] {
2274
2276
  opacity: 1;
2275
2277
  }
2276
2278
 
2277
2279
  @media (pointer: coarse) {
2278
- [data-ui='data-grid'] [data-part='cell'] > [data-part='actions'],
2279
- [data-ui='data-grid'] [data-part='column-menu'],
2280
- [data-ui='data-grid'] [data-part='column-header'] [data-part='filter'] {
2280
+ [data-ui-data-grid] [data-part-cell] > [data-part-actions],
2281
+ [data-ui-data-grid] [data-part-column-menu],
2282
+ [data-ui-data-grid] [data-part-column-header] [data-part-filter] {
2281
2283
  opacity: 1;
2282
2284
  }
2283
2285
 
2284
2286
  /* The row grew to the comfortable target through the control scale; the
2285
2287
  family's own controls grow with it, to the row less the cursor's ring.
2286
2288
  A 24-pixel button in a 44-pixel row is a target a thumb misses. */
2287
- [data-ui='data-grid'][data-part='root'] {
2289
+ [data-ui-data-grid][data-part-root] {
2288
2290
  --_control: min(
2289
2291
  var(--slotted-target-comfortable, 44px),
2290
2292
  calc(min(var(--_row-block), var(--_head-block)) - var(--_ring-width) * 2)
@@ -2297,13 +2299,13 @@
2297
2299
  shows round it; the box reaches the full target by a padding the ground
2298
2300
  does not paint, and gives it back as a negative margin, so no row, no
2299
2301
  header and no column name moves. Neighbours overlap by the gap. */
2300
- [data-ui='data-grid'] [data-part='column-help'],
2301
- [data-ui='data-grid'] [data-part='column-menu'],
2302
- [data-ui='data-grid'] [data-part='column-header'] [data-part='filter'],
2303
- [data-ui='data-grid'] [data-part='expander'],
2304
- [data-ui='data-grid'] [data-part='group-toggle'],
2305
- [data-ui='data-grid'] [data-part='tree-toggle'],
2306
- [data-ui='data-grid'] [data-part='row-handle'] {
2302
+ [data-ui-data-grid] [data-part-column-help],
2303
+ [data-ui-data-grid] [data-part-column-menu],
2304
+ [data-ui-data-grid] [data-part-column-header] [data-part-filter],
2305
+ [data-ui-data-grid] [data-part-expander],
2306
+ [data-ui-data-grid] [data-part-group-toggle],
2307
+ [data-ui-data-grid] [data-part-tree-toggle],
2308
+ [data-ui-data-grid] [data-part-row-handle] {
2307
2309
  background-clip: content-box;
2308
2310
  box-sizing: content-box;
2309
2311
  margin: calc(var(--_reach) * -1);
@@ -2314,7 +2316,7 @@
2314
2316
  /**
2315
2317
  * ── Empty, and loading ─────────────────────────────────────────────────
2316
2318
  */
2317
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='empty'] {
2319
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-empty] {
2318
2320
  align-items: center;
2319
2321
  /* The padding stands inside the viewport's width. Without it the box was
2320
2322
  its own padding wider than the frame, and a grid whose columns all fit
@@ -2333,7 +2335,7 @@
2333
2335
  position: sticky;
2334
2336
  }
2335
2337
 
2336
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='loader'] > [data-part='row'] > * {
2338
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-loader] > [data-part-row] > * {
2337
2339
  align-items: center;
2338
2340
  box-sizing: border-box;
2339
2341
  display: flex;
@@ -2348,7 +2350,7 @@
2348
2350
  padding-inline: var(--_pad-inline);
2349
2351
  }
2350
2352
 
2351
- [data-ui='data-grid'][aria-busy='true'] > [data-part='scroll'] > [data-part='body'] {
2353
+ [data-ui-data-grid][aria-busy='true'] > [data-part-scroll] > [data-part-body] {
2352
2354
  opacity: 0.55;
2353
2355
  pointer-events: none;
2354
2356
  transition: opacity var(--_transition);
@@ -2365,7 +2367,7 @@
2365
2367
  * its own content to the end: `pagination` is an inline-size container and
2366
2368
  * contributes no intrinsic width, so it cannot be sized by its content.
2367
2369
  */
2368
- [data-ui='data-grid'] > [data-part='footer'] {
2370
+ [data-ui-data-grid] > [data-part-footer] {
2369
2371
  align-items: center;
2370
2372
  border-block-start: var(--_rule-width) solid var(--_rule);
2371
2373
  box-sizing: border-box;
@@ -2380,14 +2382,14 @@
2380
2382
  padding-inline: var(--_pad-inline);
2381
2383
  }
2382
2384
 
2383
- [data-ui='data-grid'] > [data-part='footer'] > :last-child {
2385
+ [data-ui-data-grid] > [data-part-footer] > :last-child {
2384
2386
  display: flex;
2385
2387
  flex: 1 1 auto;
2386
2388
  justify-content: flex-end;
2387
2389
  min-inline-size: 0;
2388
2390
  }
2389
2391
 
2390
- [data-ui='data-grid'] > [data-part='footer'] [data-range] {
2392
+ [data-ui-data-grid] > [data-part-footer] [data-range] {
2391
2393
  color: var(--_muted);
2392
2394
  flex: none;
2393
2395
  font-variant-numeric: tabular-nums;
@@ -2398,21 +2400,21 @@
2398
2400
  * ── Scheme and platform ────────────────────────────────────────────────
2399
2401
  */
2400
2402
  @media (forced-colors: active) {
2401
- [data-ui='data-grid'] [role='gridcell'][data-current],
2402
- [data-ui='data-grid'] [role='columnheader'][data-current] {
2403
+ [data-ui-data-grid] [role='gridcell'][data-current],
2404
+ [data-ui-data-grid] [role='columnheader'][data-current] {
2403
2405
  box-shadow: inset 0 0 0 var(--_ring-width) Highlight;
2404
2406
  }
2405
2407
 
2406
- [data-ui='data-grid'] [data-part='cell'][data-in-range] {
2408
+ [data-ui-data-grid] [data-part-cell][data-in-range] {
2407
2409
  background-color: Highlight;
2408
2410
  color: HighlightText;
2409
2411
  }
2410
2412
 
2411
- [data-ui='data-grid'] [data-part='drop-indicator'] {
2413
+ [data-ui-data-grid] [data-part-drop-indicator] {
2412
2414
  background-color: Highlight;
2413
2415
  }
2414
2416
 
2415
- [data-ui='data-grid'] [data-part='cell'][data-changed] {
2417
+ [data-ui-data-grid] [data-part-cell][data-changed] {
2416
2418
  animation: none;
2417
2419
  background-color: Highlight;
2418
2420
  color: HighlightText;
@@ -2420,7 +2422,7 @@
2420
2422
 
2421
2423
  /* The resizer's line is a painted background, which the adjustment
2422
2424
  would otherwise replace, leaving the target with no line to show. */
2423
- [data-ui='data-grid'] [data-part='resizer']::after {
2425
+ [data-ui-data-grid] [data-part-resizer]::after {
2424
2426
  forced-color-adjust: none;
2425
2427
  }
2426
2428
  }
@@ -2435,49 +2437,49 @@
2435
2437
  * consumer who prints ten thousand turns the window off first.
2436
2438
  */
2437
2439
  @media print {
2438
- [data-ui='data-grid'][data-part='root'] {
2440
+ [data-ui-data-grid][data-part-root] {
2439
2441
  block-size: auto;
2440
2442
  break-inside: auto;
2441
2443
  }
2442
2444
 
2443
- [data-ui='data-grid'] > [data-part='scroll'] {
2445
+ [data-ui-data-grid] > [data-part-scroll] {
2444
2446
  overflow: visible;
2445
2447
  }
2446
2448
 
2447
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='head'],
2448
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='summary'],
2449
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='empty'],
2450
- [data-ui='data-grid'] > [data-part='scroll'] > [data-part='pinned-rows'],
2451
- [data-ui='data-grid'] [data-pinned] {
2449
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-head],
2450
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-summary],
2451
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-empty],
2452
+ [data-ui-data-grid] > [data-part-scroll] > [data-part-pinned-rows],
2453
+ [data-ui-data-grid] [data-pinned] {
2452
2454
  position: static;
2453
2455
  }
2454
2456
 
2455
- [data-ui='data-grid'] [data-pinned] {
2457
+ [data-ui-data-grid] [data-pinned] {
2456
2458
  box-shadow: none;
2457
2459
  }
2458
2460
 
2459
- [data-ui='data-grid'] [data-part='column-actions'],
2460
- [data-ui='data-grid'] [data-part='row-handle'],
2461
- [data-ui='data-grid'] [data-part='resizer'],
2462
- [data-ui='data-grid'] [data-part='drop-indicator'],
2463
- [data-ui='data-grid'] [data-part='loader'] {
2461
+ [data-ui-data-grid] [data-part-column-actions],
2462
+ [data-ui-data-grid] [data-part-row-handle],
2463
+ [data-ui-data-grid] [data-part-resizer],
2464
+ [data-ui-data-grid] [data-part-drop-indicator],
2465
+ [data-ui-data-grid] [data-part-loader] {
2464
2466
  display: none;
2465
2467
  }
2466
2468
 
2467
- [data-ui='data-grid'] [role='gridcell'][data-current],
2468
- [data-ui='data-grid'] [role='rowheader'][data-current],
2469
- [data-ui='data-grid'] [role='columnheader'][data-current] {
2469
+ [data-ui-data-grid] [role='gridcell'][data-current],
2470
+ [data-ui-data-grid] [role='rowheader'][data-current],
2471
+ [data-ui-data-grid] [role='columnheader'][data-current] {
2470
2472
  box-shadow: none;
2471
2473
  }
2472
2474
 
2473
- [data-ui='data-grid'] :is([data-part='body'], [data-part='pinned-rows']) > [data-part='row'] {
2475
+ [data-ui-data-grid] :is([data-part-body], [data-part-pinned-rows]) > [data-part-row] {
2474
2476
  break-inside: avoid;
2475
2477
  }
2476
2478
 
2477
- [data-ui='data-grid']
2478
- > [data-part='scroll']
2479
- > :is([data-part='body'], [data-part='pinned-rows'])
2480
- > [data-part='row'] {
2479
+ [data-ui-data-grid]
2480
+ > [data-part-scroll]
2481
+ > :is([data-part-body], [data-part-pinned-rows])
2482
+ > [data-part-row] {
2481
2483
  --_hover: transparent;
2482
2484
  }
2483
2485
  }