@slotted/styles 0.1.0-beta.1 → 0.1.0-beta.11

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 (180) hide show
  1. package/package.json +1 -1
  2. package/src/accordion/accordion.css +10 -10
  3. package/src/action-bar/action-bar.css +35 -42
  4. package/src/action-sheet/action-sheet.css +36 -36
  5. package/src/alert/alert.css +43 -35
  6. package/src/alert/alert.tokens.json +5 -0
  7. package/src/app-shell/app-shell.css +356 -301
  8. package/src/aspect-ratio/aspect-ratio.css +9 -9
  9. package/src/attachment/attachment.css +91 -99
  10. package/src/avatar/avatar.css +71 -41
  11. package/src/avatar/avatar.tokens.json +7 -0
  12. package/src/avatar-group/avatar-group.css +21 -22
  13. package/src/badge/badge.css +45 -37
  14. package/src/badge/badge.tokens.json +5 -0
  15. package/src/breadcrumb/breadcrumb.css +37 -37
  16. package/src/button/button.css +149 -68
  17. package/src/button/button.tokens.json +10 -0
  18. package/src/button-group/button-group.css +79 -74
  19. package/src/button-group/button-group.tokens.json +2 -0
  20. package/src/calendar/calendar.css +93 -103
  21. package/src/card/card.css +54 -61
  22. package/src/carousel/carousel.css +150 -161
  23. package/src/cascader/cascader.css +152 -153
  24. package/src/cascader/cascader.tokens.json +1 -0
  25. package/src/chart/chart.css +242 -239
  26. package/src/chart/chart.tokens.json +1 -0
  27. package/src/checkbox/checkbox.css +119 -124
  28. package/src/checkbox-group/checkbox-group.css +7 -7
  29. package/src/code-block/code-block.css +81 -85
  30. package/src/collapsible/collapsible.css +69 -76
  31. package/src/color-picker/color-picker.css +83 -91
  32. package/src/column-manager/column-manager.css +106 -114
  33. package/src/combobox/combobox.css +132 -107
  34. package/src/combobox/combobox.tokens.json +1 -0
  35. package/src/command-palette/command-palette.css +103 -90
  36. package/src/command-palette/command-palette.tokens.json +1 -0
  37. package/src/container/container.css +24 -24
  38. package/src/context-menu/context-menu.css +8 -8
  39. package/src/currency-field/currency-field.css +210 -88
  40. package/src/currency-field/currency-field.tokens.json +13 -0
  41. package/src/dashboard-grid/dashboard-grid.css +148 -116
  42. package/src/data-grid/data-grid.css +535 -470
  43. package/src/data-grid/data-grid.tokens.json +4 -0
  44. package/src/data-list/data-list.css +81 -70
  45. package/src/data-list/data-list.tokens.json +2 -1
  46. package/src/date-field/date-field.css +55 -52
  47. package/src/date-field/date-field.tokens.json +1 -0
  48. package/src/date-picker/date-picker.css +40 -42
  49. package/src/date-range-picker/date-range-picker.css +114 -118
  50. package/src/datetime-field/datetime-field.css +78 -80
  51. package/src/datetime-field/datetime-field.tokens.json +1 -0
  52. package/src/datetime-picker/datetime-picker.css +61 -63
  53. package/src/datetime-range-picker/datetime-range-picker.css +149 -156
  54. package/src/description-list/description-list.css +61 -64
  55. package/src/detail-panel/detail-panel.css +86 -71
  56. package/src/detail-panel/detail-panel.tokens.json +2 -0
  57. package/src/dialog/dialog.css +372 -153
  58. package/src/dialog/dialog.tokens.json +6 -0
  59. package/src/divider/divider.css +18 -18
  60. package/src/drawer/drawer.css +205 -210
  61. package/src/drawer/drawer.tokens.json +1 -0
  62. package/src/entity-picker/entity-picker.css +238 -241
  63. package/src/entity-picker/entity-picker.tokens.json +1 -0
  64. package/src/event-calendar/event-calendar.css +343 -385
  65. package/src/field/field.css +74 -78
  66. package/src/field-group/field-group.css +22 -25
  67. package/src/filter-bar/filter-bar.css +193 -209
  68. package/src/form/form.css +34 -24
  69. package/src/form/form.tokens.json +1 -0
  70. package/src/fullscreen/fullscreen.css +24 -25
  71. package/src/grid/grid.css +28 -28
  72. package/src/highlight/highlight.css +6 -6
  73. package/src/hover-card/hover-card.css +6 -6
  74. package/src/icon/icon.css +19 -15
  75. package/src/icon/icon.tokens.json +1 -0
  76. package/src/image/image.css +39 -39
  77. package/src/import-export-center/import-export-center.css +135 -156
  78. package/src/inline/inline.css +27 -27
  79. package/src/inline-message/inline-message.css +52 -28
  80. package/src/inline-message/inline-message.tokens.json +4 -0
  81. package/src/kbd/kbd.css +30 -26
  82. package/src/link/link.css +15 -15
  83. package/src/list/list.css +44 -17
  84. package/src/list/list.tokens.json +4 -0
  85. package/src/list-item/list-item.css +80 -66
  86. package/src/list-item/list-item.tokens.json +7 -0
  87. package/src/listbox/listbox.css +56 -59
  88. package/src/loading-overlay/loading-overlay.css +75 -92
  89. package/src/markdown/markdown.css +17 -17
  90. package/src/menu/menu.css +83 -63
  91. package/src/menubar/menubar.css +13 -13
  92. package/src/message/message.css +182 -202
  93. package/src/message/message.tokens.json +5 -0
  94. package/src/message-scroller/message-scroller.css +41 -42
  95. package/src/multi-select/multi-select.css +152 -145
  96. package/src/multi-select/multi-select.tokens.json +1 -0
  97. package/src/navigation-menu/navigation-menu.css +167 -188
  98. package/src/notification-center/notification-center.css +140 -148
  99. package/src/notification-center/notification-center.tokens.json +3 -0
  100. package/src/number-field/number-field.css +84 -83
  101. package/src/number-field/number-field.tokens.json +1 -0
  102. package/src/otp-input/otp-input.css +67 -57
  103. package/src/otp-input/otp-input.tokens.json +1 -0
  104. package/src/page/page.css +39 -23
  105. package/src/page/page.tokens.json +1 -0
  106. package/src/page-header/page-header.css +323 -283
  107. package/src/page-header/page-header.tokens.json +5 -0
  108. package/src/pagination/pagination.css +68 -72
  109. package/src/popover/popover.css +40 -49
  110. package/src/progress-indicator/progress-indicator.css +177 -120
  111. package/src/progress-indicator/progress-indicator.tokens.json +1 -1
  112. package/src/prompt-composer/prompt-composer.css +221 -102
  113. package/src/prompt-composer/prompt-composer.tokens.json +15 -0
  114. package/src/prose/prose.css +71 -75
  115. package/src/radio-group/radio-group.css +98 -103
  116. package/src/rating/rating.css +136 -132
  117. package/src/rating/rating.tokens.json +1 -0
  118. package/src/result-state/result-state.css +74 -77
  119. package/src/runtime-properties.mjs +2 -0
  120. package/src/saved-views/saved-views.css +41 -47
  121. package/src/scroll-area/scroll-area.css +39 -32
  122. package/src/section/section.css +161 -41
  123. package/src/section/section.tokens.json +7 -2
  124. package/src/segmented-control/segmented-control.css +254 -97
  125. package/src/segmented-control/segmented-control.tokens.json +15 -11
  126. package/src/select/select.css +118 -117
  127. package/src/select/select.tokens.json +1 -0
  128. package/src/side-navigation/side-navigation.css +179 -182
  129. package/src/side-navigation/side-navigation.tokens.json +1 -0
  130. package/src/skeleton/skeleton.css +47 -48
  131. package/src/slider/slider.css +86 -88
  132. package/src/sparkline/sparkline.css +62 -40
  133. package/src/sparkline/sparkline.tokens.json +2 -0
  134. package/src/spinner/spinner.css +83 -180
  135. package/src/spinner/spinner.tokens.json +0 -1
  136. package/src/split-button/split-button.css +30 -31
  137. package/src/split-button/split-button.tokens.json +1 -0
  138. package/src/splitter/splitter.css +35 -35
  139. package/src/stack/stack.css +24 -24
  140. package/src/stat-card/stat-card.css +341 -224
  141. package/src/stat-card/stat-card.tokens.json +3 -0
  142. package/src/status-indicator/status-indicator.css +28 -28
  143. package/src/stepper/stepper.css +58 -62
  144. package/src/switch/switch.css +86 -92
  145. package/src/table/table.css +310 -165
  146. package/src/table/table.tokens.json +6 -0
  147. package/src/table-of-contents/table-of-contents.css +51 -54
  148. package/src/tabs/tabs.css +337 -302
  149. package/src/tabs/tabs.tokens.json +8 -5
  150. package/src/tag/tag.css +79 -71
  151. package/src/tag/tag.tokens.json +9 -0
  152. package/src/tags-input/tags-input.css +145 -82
  153. package/src/tags-input/tags-input.tokens.json +7 -1
  154. package/src/text-field/text-field.css +132 -136
  155. package/src/text-field/text-field.tokens.json +1 -0
  156. package/src/textarea/textarea.css +31 -28
  157. package/src/textarea/textarea.tokens.json +1 -0
  158. package/src/time-field/time-field.css +72 -69
  159. package/src/time-field/time-field.tokens.json +1 -0
  160. package/src/time-picker/time-picker.css +56 -58
  161. package/src/time-range-picker/time-range-picker.css +126 -133
  162. package/src/timeline/timeline.css +254 -266
  163. package/src/timeline/timeline.tokens.json +5 -0
  164. package/src/toast/toast.css +108 -90
  165. package/src/toast/toast.tokens.json +6 -0
  166. package/src/toggle/toggle.css +62 -25
  167. package/src/toggle/toggle.tokens.json +8 -0
  168. package/src/toggle-group/toggle-group.css +106 -60
  169. package/src/toggle-group/toggle-group.tokens.json +10 -0
  170. package/src/toolbar/toolbar.css +30 -35
  171. package/src/tooltip/tooltip.css +26 -26
  172. package/src/top-navigation/top-navigation.css +243 -259
  173. package/src/tour/tour.css +51 -60
  174. package/src/transfer/transfer.css +160 -164
  175. package/src/tree/tree.css +103 -111
  176. package/src/typography/typography.css +40 -36
  177. package/src/typography/typography.tokens.json +1 -0
  178. package/src/upload/upload.css +224 -224
  179. package/src/visually-hidden/visually-hidden.css +1 -1
  180. package/src/wizard/wizard.css +185 -197
@@ -19,7 +19,7 @@
19
19
  * a field in a 240-pixel drawer has to stack while the same field in a page
20
20
  * grid stays beside its control.
21
21
  */
22
- [data-ui='field'][data-part='root'] {
22
+ [data-ui-field][data-part-root] {
23
23
  /**
24
24
  * Type, control height and glyph come from the control scales, the only
25
25
  * ones the theme restates per density, so a field in a dense table shrinks
@@ -79,7 +79,7 @@
79
79
  }
80
80
 
81
81
  /* Every child spans the field, and the two that do not say so below. */
82
- [data-ui='field'][data-part='root'] > * {
82
+ [data-ui-field][data-part-root] > * {
83
83
  grid-column: 1 / -1;
84
84
  }
85
85
 
@@ -90,7 +90,7 @@
90
90
  * rather than the control. Nothing here paints the control, sizes its type or
91
91
  * touches its border: `text-field` owns all three.
92
92
  */
93
- [data-ui='field'] > [data-part='control'] {
93
+ [data-ui-field] > [data-part-control] {
94
94
  min-inline-size: 0;
95
95
  }
96
96
 
@@ -101,7 +101,7 @@
101
101
  * inside it, which makes a field with no control an unsized box.
102
102
  */
103
103
 
104
- [data-ui='field'][data-part='root'][data-size='sm'] {
104
+ [data-ui-field][data-part-root][data-size='sm'] {
105
105
  --_help-glyph: max(
106
106
  var(--slotted-field-icon-size-min, 14px),
107
107
  var(--slotted-control-icon-size-sm, 14px)
@@ -111,7 +111,7 @@
111
111
  --_control-block-size: var(--slotted-control-height-sm, 30px);
112
112
  }
113
113
 
114
- [data-ui='field'][data-part='root'][data-size='md'] {
114
+ [data-ui-field][data-part-root][data-size='md'] {
115
115
  --_help-glyph: max(
116
116
  var(--slotted-field-icon-size-min, 14px),
117
117
  var(--slotted-control-icon-size-sm, 14px)
@@ -121,7 +121,7 @@
121
121
  --_control-block-size: var(--slotted-control-height-md, 34px);
122
122
  }
123
123
 
124
- [data-ui='field'][data-part='root'][data-size='lg'] {
124
+ [data-ui-field][data-part-root][data-size='lg'] {
125
125
  --_help-glyph: max(
126
126
  var(--slotted-field-icon-size-min, 14px),
127
127
  var(--slotted-control-icon-size-md, 16px)
@@ -142,8 +142,8 @@
142
142
  * line height is for a box holding one line, and a label of twelve words
143
143
  * beside a narrow control holds three.
144
144
  */
145
- [data-ui='field'] > [data-part='label'],
146
- [data-ui='field'] > [data-part='header'] > [data-part='label'] {
145
+ [data-ui-field] > [data-part-label],
146
+ [data-ui-field] > [data-part-header] > [data-part-label] {
147
147
  color: var(--slotted-field-label-color, var(--slotted-text));
148
148
  font-size: var(--_font-size);
149
149
  font-weight: var(--slotted-field-label-font-weight, var(--slotted-font-weight-medium, 500));
@@ -163,8 +163,8 @@
163
163
  * The first row is the label's, or the header's when the label has company.
164
164
  * Either spans the field when the label sits above the control.
165
165
  */
166
- [data-ui='field'] > [data-part='label'],
167
- [data-ui='field'] > [data-part='header'] {
166
+ [data-ui-field] > [data-part-label],
167
+ [data-ui-field] > [data-part-header] {
168
168
  grid-column: 1 / -1;
169
169
  grid-row: 1;
170
170
  }
@@ -175,7 +175,7 @@
175
175
  * label under it; a field without one would otherwise lose the counter's track
176
176
  * from the label's width for a part that is not there.
177
177
  */
178
- [data-ui='field'][data-part='root']:has(> [data-part='counter']) > [data-part='label'] {
178
+ [data-ui-field][data-part-root]:has(> [data-part-counter]) > [data-part-label] {
179
179
  grid-column: 1 / 3;
180
180
  }
181
181
 
@@ -191,8 +191,8 @@
191
191
  * red marker on a red label is a marker nobody can see, and the error already
192
192
  * says the same thing in words, in colour and in a glyph.
193
193
  */
194
- [data-ui='field'] > [data-part='label'] > [data-part='mark'],
195
- [data-ui='field'] > [data-part='header'] > [data-part='label'] > [data-part='mark'] {
194
+ [data-ui-field] > [data-part-label] > [data-part-mark],
195
+ [data-ui-field] > [data-part-header] > [data-part-label] > [data-part-mark] {
196
196
  color: var(--slotted-field-mark-color, var(--slotted-tone-danger-text));
197
197
  margin-inline-start: var(--slotted-field-mark-gap, var(--slotted-space-2, 0.25rem));
198
198
  /* The label breaks anywhere; the necessity word never does. `(required)`
@@ -217,13 +217,13 @@
217
217
  * a qualifier rather than as two labels. `optional` writes the word only on
218
218
  * the fields a reader may skip; `words` writes both.
219
219
  */
220
- [data-ui='field']:is([data-necessity='optional'], [data-necessity='words'])
221
- > [data-part='label']
222
- > [data-part='mark'],
223
- [data-ui='field']:is([data-necessity='optional'], [data-necessity='words'])
224
- > [data-part='header']
225
- > [data-part='label']
226
- > [data-part='mark'] {
220
+ [data-ui-field]:is([data-necessity='optional'], [data-necessity='words'])
221
+ > [data-part-label]
222
+ > [data-part-mark],
223
+ [data-ui-field]:is([data-necessity='optional'], [data-necessity='words'])
224
+ > [data-part-header]
225
+ > [data-part-label]
226
+ > [data-part-mark] {
227
227
  color: var(--slotted-field-mark-text-color, var(--slotted-text-muted));
228
228
  font-size: var(--slotted-control-font-size-sm, 12px);
229
229
  font-weight: var(--slotted-font-weight-regular, 400);
@@ -243,7 +243,7 @@
243
243
  * anything inside it are the label's line. It wraps: in a narrow field the
244
244
  * action and the counter move to a second line, still at its end.
245
245
  */
246
- [data-ui='field'] > [data-part='header'] {
246
+ [data-ui-field] > [data-part-header] {
247
247
  align-items: baseline;
248
248
  column-gap: var(--slotted-field-header-gap, var(--slotted-space-3, 0.375rem));
249
249
  display: flex;
@@ -253,7 +253,7 @@
253
253
  min-inline-size: 0;
254
254
  }
255
255
 
256
- [data-ui='field'] > [data-part='header'] > [data-part='label'] {
256
+ [data-ui-field] > [data-part-header] > [data-part-label] {
257
257
  flex: 0 1 auto;
258
258
  }
259
259
 
@@ -264,12 +264,12 @@
264
264
  * distance a side label keeps from its control, so a link and a number do
265
265
  * not read as one phrase.
266
266
  */
267
- [data-ui='field'] > [data-part='header'] > [data-part='action'],
268
- [data-ui='field'] > [data-part='header'] > [data-part='counter'] {
267
+ [data-ui-field] > [data-part-header] > [data-part-action],
268
+ [data-ui-field] > [data-part-header] > [data-part-counter] {
269
269
  margin-inline-start: auto;
270
270
  }
271
271
 
272
- [data-ui='field'] > [data-part='header'] > [data-part='action'] ~ [data-part='counter'] {
272
+ [data-ui-field] > [data-part-header] > [data-part-action] ~ [data-part-counter] {
273
273
  margin-inline-start: var(--slotted-space-3, 0.375rem);
274
274
  }
275
275
 
@@ -306,7 +306,7 @@
306
306
  * the glyph, which put its centre on the band's top: four pixels high, and a
307
307
  * line box 3.3 pixels taller than the label's.
308
308
  */
309
- [data-ui='field'] > [data-part='header'] > [data-part='help'] {
309
+ [data-ui-field] > [data-part-header] > [data-part-help] {
310
310
  /* Never shorter than the label's line: at dense the inside of a control is
311
311
  16 pixels and the line 17.39, and a button shorter than its own line
312
312
  overflows downward and pushes the row 0.69 pixels taller. */
@@ -348,13 +348,13 @@
348
348
  /* The pointer target: a transparent square centred on the box that reaches
349
349
  the WCAG minimum wherever the box falls short of it — 22 pixels at
350
350
  comfortable, 16 at dense. It takes no room, so the row keeps its height. */
351
- [data-ui='field'] > [data-part='header'] > [data-part='help']::before {
351
+ [data-ui-field] > [data-part-header] > [data-part-help]::before {
352
352
  content: '';
353
353
  inset: min(0px, calc((100% - var(--slotted-target-min, 24px)) / 2));
354
354
  position: absolute;
355
355
  }
356
356
 
357
- [data-ui='field'] > [data-part='header'] > [data-part='help'] > [data-ui='icon'] {
357
+ [data-ui-field] > [data-part-header] > [data-part-help] > [data-ui-icon] {
358
358
  vertical-align: calc(((1cap + 1ex) / 2 - var(--_help-glyph)) / 2);
359
359
  }
360
360
 
@@ -363,22 +363,22 @@
363
363
  * hover ground while its tooltip is showing, so the reader sees which icon
364
364
  * the layer belongs to after the pointer has moved onto the layer.
365
365
  */
366
- [data-ui='field'] > [data-part='header'] > [data-part='help']:enabled:hover,
367
- [data-ui='field'] > [data-part='header'] > [data-part='help'][data-open] {
366
+ [data-ui-field] > [data-part-header] > [data-part-help]:enabled:hover,
367
+ [data-ui-field] > [data-part-header] > [data-part-help][data-open] {
368
368
  background-color: var(
369
369
  --slotted-field-help-surface-hover,
370
370
  var(--slotted-tone-secondary-subtle-hover, ButtonFace)
371
371
  );
372
372
  }
373
373
 
374
- [data-ui='field'] > [data-part='header'] > [data-part='help']:enabled:active {
374
+ [data-ui-field] > [data-part-header] > [data-part-help]:enabled:active {
375
375
  background-color: var(
376
376
  --slotted-field-help-surface-active,
377
377
  var(--slotted-tone-secondary-subtle-active, ButtonFace)
378
378
  );
379
379
  }
380
380
 
381
- [data-ui='field'] > [data-part='header'] > [data-part='help']:focus-visible {
381
+ [data-ui-field] > [data-part-header] > [data-part-help]:focus-visible {
382
382
  outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
383
383
  outline-offset: var(--slotted-focus-ring-offset, 2px);
384
384
  }
@@ -391,7 +391,7 @@
391
391
  * description rather than with its name. The badges are the badge family's;
392
392
  * the field only spaces them.
393
393
  */
394
- [data-ui='field'] > [data-part='header'] > [data-part='indicator'] {
394
+ [data-ui-field] > [data-part-header] > [data-part-indicator] {
395
395
  align-items: center;
396
396
  /* A badge is a box, not a line of text. Set on the label's baseline, its
397
397
  own inset stood it 1.77 pixels above the label's line and the row grew
@@ -419,7 +419,7 @@
419
419
  * from a padding and a line — the sum measured 23.98 — and a flex box's
420
420
  * baseline is its words', so the row still aligns on it.
421
421
  */
422
- [data-ui='field'] > [data-part='header'] > [data-part='action'] {
422
+ [data-ui-field] > [data-part-header] > [data-part-action] {
423
423
  --_rest: var(--slotted-field-action-color, var(--slotted-tone-accent-text, LinkText));
424
424
 
425
425
  align-items: center;
@@ -453,9 +453,9 @@
453
453
  unicode-bidi: plaintext;
454
454
  }
455
455
 
456
- [data-ui='field']
457
- > [data-part='header']
458
- > [data-part='action']:not(:disabled, [aria-disabled='true']):hover {
456
+ [data-ui-field]
457
+ > [data-part-header]
458
+ > [data-part-action]:not(:disabled, [aria-disabled='true']):hover {
459
459
  color: var(
460
460
  --slotted-field-action-color-hover,
461
461
  color-mix(in oklab, var(--_rest) 65%, var(--slotted-text, CanvasText))
@@ -463,9 +463,9 @@
463
463
  text-decoration-color: currentColor;
464
464
  }
465
465
 
466
- [data-ui='field']
467
- > [data-part='header']
468
- > [data-part='action']:not(:disabled, [aria-disabled='true']):active {
466
+ [data-ui-field]
467
+ > [data-part-header]
468
+ > [data-part-action]:not(:disabled, [aria-disabled='true']):active {
469
469
  color: var(
470
470
  --slotted-field-action-color-active,
471
471
  color-mix(in oklab, var(--_rest) 35%, var(--slotted-text, CanvasText))
@@ -473,15 +473,13 @@
473
473
  text-decoration-color: currentColor;
474
474
  }
475
475
 
476
- [data-ui='field'] > [data-part='header'] > [data-part='action']:focus-visible {
476
+ [data-ui-field] > [data-part-header] > [data-part-action]:focus-visible {
477
477
  outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
478
478
  outline-offset: var(--slotted-focus-ring-offset, 2px);
479
479
  text-decoration-color: currentColor;
480
480
  }
481
481
 
482
- [data-ui='field']
483
- > [data-part='header']
484
- > [data-part='action']:is(:disabled, [aria-disabled='true']) {
482
+ [data-ui-field] > [data-part-header] > [data-part-action]:is(:disabled, [aria-disabled='true']) {
485
483
  color: var(--slotted-disabled-foreground, GrayText);
486
484
  cursor: not-allowed;
487
485
  }
@@ -492,12 +490,12 @@
492
490
  * keeps its height and the ground and the ring stay the box a mouse sees.
493
491
  */
494
492
  @media (pointer: coarse) {
495
- [data-ui='field'] > [data-part='header'] > [data-part='action'] {
493
+ [data-ui-field] > [data-part-header] > [data-part-action] {
496
494
  position: relative;
497
495
  }
498
496
 
499
- [data-ui='field'] > [data-part='header'] > [data-part='help']::before,
500
- [data-ui='field'] > [data-part='header'] > [data-part='action']::before {
497
+ [data-ui-field] > [data-part-header] > [data-part-help]::before,
498
+ [data-ui-field] > [data-part-header] > [data-part-action]::before {
501
499
  content: '';
502
500
  inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
503
501
  position: absolute;
@@ -514,8 +512,8 @@
514
512
  * Tabular figures, because a counter that jitters as it counts is a counter
515
513
  * the eye follows instead of the field.
516
514
  */
517
- [data-ui='field'] > [data-part='counter'],
518
- [data-ui='field'] > [data-part='header'] > [data-part='counter'] {
515
+ [data-ui-field] > [data-part-counter],
516
+ [data-ui-field] > [data-part-header] > [data-part-counter] {
519
517
  color: var(--slotted-field-counter-color, var(--slotted-text-muted));
520
518
  font-size: var(--slotted-control-font-size-sm, 12px);
521
519
  font-variant-numeric: tabular-nums;
@@ -528,7 +526,7 @@
528
526
  * The counter the family draws on a field with no header: the end of the
529
527
  * label row, in the third track, apart from the label by the side gap.
530
528
  */
531
- [data-ui='field'] > [data-part='counter'] {
529
+ [data-ui-field] > [data-part-counter] {
532
530
  align-self: end;
533
531
  grid-column: 3;
534
532
  grid-row: 1;
@@ -541,8 +539,8 @@
541
539
  * its maximum while validation has not yet run, and a counter that only turned
542
540
  * at submit would say nothing at the moment it is being read.
543
541
  */
544
- [data-ui='field'] > [data-part='counter'][data-invalid],
545
- [data-ui='field'] > [data-part='header'] > [data-part='counter'][data-invalid] {
542
+ [data-ui-field] > [data-part-counter][data-invalid],
543
+ [data-ui-field] > [data-part-header] > [data-part-counter][data-invalid] {
546
544
  color: var(--slotted-field-counter-invalid-color, var(--slotted-tone-danger-text));
547
545
  font-weight: var(--slotted-font-weight-medium, 500);
548
546
  }
@@ -560,7 +558,7 @@
560
558
  * form that renders its error unconditionally so nothing below it moves when
561
559
  * the error arrives.
562
560
  */
563
- [data-ui='field'] > [data-ui='inline-message']:not([data-reserve]):has([data-part='text']:empty) {
561
+ [data-ui-field] > [data-ui-inline-message]:not([data-reserve]):has([data-part-text]:empty) {
564
562
  display: none;
565
563
  }
566
564
 
@@ -575,7 +573,7 @@
575
573
  * own root rule, which has the same two attributes; equal specificity would
576
574
  * leave the winner to stylesheet order.
577
575
  */
578
- [data-ui='field'][data-part='root'] > [data-ui='inline-message'] {
576
+ [data-ui-field][data-part-root] > [data-ui-inline-message] {
579
577
  font-size: var(--slotted-font-size-xs, 0.75rem);
580
578
  }
581
579
 
@@ -586,8 +584,8 @@
586
584
  * size (`inline-message`, R5) and its own ink, and the weight is what makes
587
585
  * the two read as two kinds of sentence rather than one.
588
586
  */
589
- [data-ui='field'][data-part='root'] > [data-ui='inline-message'][data-tone='danger'],
590
- [data-ui='field'][data-part='root'] > [data-ui='inline-message'][data-tone='success'] {
587
+ [data-ui-field][data-part-root] > [data-ui-inline-message][data-tone='danger'],
588
+ [data-ui-field][data-part-root] > [data-ui-inline-message][data-tone='success'] {
591
589
  font-weight: var(--slotted-font-weight-medium, 500);
592
590
  }
593
591
 
@@ -618,7 +616,7 @@
618
616
  * and a label of three lines — or a header whose action wrapped under the
619
617
  * label — stretched a one-line input beside it to 43 pixels.
620
618
  */
621
- [data-ui='field'][data-part='root'][data-label-placement='side'] > * {
619
+ [data-ui-field][data-part-root][data-label-placement='side'] > * {
622
620
  align-self: start;
623
621
  grid-column: 2 / 3;
624
622
  }
@@ -629,8 +627,8 @@
629
627
  * textarea four lines tall. `max()` keeps a label taller than its control —
630
628
  * three wrapped lines beside a 30-pixel input — from being pushed down.
631
629
  */
632
- [data-ui='field'][data-part='root'][data-label-placement='side'] > [data-part='label'],
633
- [data-ui='field'][data-part='root'][data-label-placement='side'] > [data-part='header'] {
630
+ [data-ui-field][data-part-root][data-label-placement='side'] > [data-part-label],
631
+ [data-ui-field][data-part-root][data-label-placement='side'] > [data-part-header] {
634
632
  grid-column: 1;
635
633
  grid-row: 1;
636
634
  padding-block-start: max(0px, calc((var(--_control-block-size) - 1lh) / 2));
@@ -644,7 +642,7 @@
644
642
  * control, where it sat until the header existed, was a second place. Restated inside the query because `> *` above is one selector
645
643
  * more specific than the counter's own rule.
646
644
  */
647
- [data-ui='field'][data-part='root'][data-label-placement='side'] > [data-part='counter'] {
645
+ [data-ui-field][data-part-root][data-label-placement='side'] > [data-part-counter] {
648
646
  grid-column: 1;
649
647
  grid-row: 2;
650
648
  justify-self: end;
@@ -657,9 +655,9 @@
657
655
  * part of the name — `Assunto 12/60` — and it stood one line higher than
658
656
  * the counter a field without a header draws.
659
657
  */
660
- [data-ui='field'][data-part='root'][data-label-placement='side']
661
- > [data-part='header']
662
- > [data-part='counter'] {
658
+ [data-ui-field][data-part-root][data-label-placement='side']
659
+ > [data-part-header]
660
+ > [data-part-counter] {
663
661
  flex-basis: 100%;
664
662
  margin-inline-start: 0;
665
663
  text-align: end;
@@ -675,20 +673,18 @@
675
673
  * The messages need no rule here. The field passes `disabled` to them, and
676
674
  * `inline-message` mutes itself to the same colour and stops its own ring.
677
675
  */
678
- [data-ui='field'][data-part='root'][data-disabled] > [data-part='label'],
679
- [data-ui='field'][data-part='root'][data-disabled] > [data-part='counter'],
680
- [data-ui='field'][data-part='root'][data-disabled] > [data-part='header'] > [data-part='label'],
681
- [data-ui='field'][data-part='root'][data-disabled]
682
- > [data-part='header']
683
- > [data-part='counter'] {
676
+ [data-ui-field][data-part-root][data-disabled] > [data-part-label],
677
+ [data-ui-field][data-part-root][data-disabled] > [data-part-counter],
678
+ [data-ui-field][data-part-root][data-disabled] > [data-part-header] > [data-part-label],
679
+ [data-ui-field][data-part-root][data-disabled] > [data-part-header] > [data-part-counter] {
684
680
  color: var(--slotted-disabled-foreground);
685
681
  }
686
682
 
687
- [data-ui='field'][data-part='root'][data-disabled] > [data-part='label'] > [data-part='mark'],
688
- [data-ui='field'][data-part='root'][data-disabled]
689
- > [data-part='header']
690
- > [data-part='label']
691
- > [data-part='mark'] {
683
+ [data-ui-field][data-part-root][data-disabled] > [data-part-label] > [data-part-mark],
684
+ [data-ui-field][data-part-root][data-disabled]
685
+ > [data-part-header]
686
+ > [data-part-label]
687
+ > [data-part-mark] {
692
688
  color: var(--slotted-disabled-foreground);
693
689
  }
694
690
 
@@ -697,10 +693,10 @@
697
693
  * whose counter is over its limit paints the counter muted rather than red.
698
694
  * A control nobody can type in is not over a limit; it is off.
699
695
  */
700
- [data-ui='field'][data-part='root'][data-disabled] > [data-part='counter'][data-invalid],
701
- [data-ui='field'][data-part='root'][data-disabled]
702
- > [data-part='header']
703
- > [data-part='counter'][data-invalid] {
696
+ [data-ui-field][data-part-root][data-disabled] > [data-part-counter][data-invalid],
697
+ [data-ui-field][data-part-root][data-disabled]
698
+ > [data-part-header]
699
+ > [data-part-counter][data-invalid] {
704
700
  color: var(--slotted-disabled-foreground);
705
701
  font-weight: var(--slotted-font-weight-regular, 400);
706
702
  }
@@ -19,7 +19,7 @@
19
19
  * fields is a `content` element the family draws, and the legend never
20
20
  * competes with it.
21
21
  */
22
- [data-ui='field-group'][data-part='root'] {
22
+ [data-ui-field-group][data-part-root] {
23
23
  --_font-size: var(--slotted-control-font-size-lg, 14px);
24
24
  /** Legend to its own description, and description to error. */
25
25
  --_message-gap: var(--slotted-field-group-message-gap, var(--slotted-space-2, 0.25rem));
@@ -45,18 +45,18 @@
45
45
  }
46
46
 
47
47
  /* Legend, then what is said about the set, then the set. */
48
- [data-ui='field-group'][data-part='root'] > * + * {
48
+ [data-ui-field-group][data-part-root] > * + * {
49
49
  margin-block-start: var(--_message-gap);
50
50
  }
51
51
 
52
52
  /* `inline-message` zeroes its root's margin at the weight of the rule above,
53
53
  so the order the two stylesheets load in decided the gap; a third
54
54
  attribute decides it here. */
55
- [data-ui='field-group'][data-part='root'] > * + [data-ui='inline-message'] {
55
+ [data-ui-field-group][data-part-root] > * + [data-ui-inline-message] {
56
56
  margin-block-start: var(--_message-gap);
57
57
  }
58
58
 
59
- [data-ui='field-group'][data-part='root'] > [data-part='content'] {
59
+ [data-ui-field-group][data-part-root] > [data-part-content] {
60
60
  margin-block-start: var(--_content-gap);
61
61
  }
62
62
 
@@ -69,15 +69,15 @@
69
69
  * because a third type scale would be a fourth thing for a theme to retune.
70
70
  */
71
71
 
72
- [data-ui='field-group'][data-part='root'][data-size='sm'] {
72
+ [data-ui-field-group][data-part-root][data-size='sm'] {
73
73
  --_font-size: var(--slotted-control-font-size-md, 13px);
74
74
  }
75
75
 
76
- [data-ui='field-group'][data-part='root'][data-size='md'] {
76
+ [data-ui-field-group][data-part-root][data-size='md'] {
77
77
  --_font-size: var(--slotted-control-font-size-lg, 14px);
78
78
  }
79
79
 
80
- [data-ui='field-group'][data-part='root'][data-size='lg'] {
80
+ [data-ui-field-group][data-part-root][data-size='lg'] {
81
81
  --_font-size: var(--slotted-control-font-size-lg, 14px);
82
82
  }
83
83
 
@@ -90,7 +90,7 @@
90
90
  * recommendation work: on a page asking one question, the legend contains the
91
91
  * page's `h1`, so a reader hears the question once rather than twice.
92
92
  */
93
- [data-ui='field-group'] > [data-part='legend'] {
93
+ [data-ui-field-group] > [data-part-legend] {
94
94
  color: var(--slotted-field-group-legend-color, var(--slotted-text));
95
95
  display: block;
96
96
  font-size: var(--_font-size);
@@ -110,7 +110,7 @@
110
110
  * is. The glyph takes the danger ink and the words do not, which is the field
111
111
  * family's decision applied to the element one level up.
112
112
  */
113
- [data-ui='field-group'] > [data-part='legend'] > [data-part='mark'] {
113
+ [data-ui-field-group] > [data-part-legend] > [data-part-mark] {
114
114
  color: var(--slotted-field-group-mark-color, var(--slotted-tone-danger-text));
115
115
  margin-inline-start: var(--slotted-field-group-mark-gap, var(--slotted-space-2, 0.25rem));
116
116
  overflow-wrap: normal;
@@ -131,7 +131,7 @@
131
131
  * `font: inherit` here would shrink every question page's title to the size
132
132
  * of a form label.
133
133
  */
134
- [data-ui='field-group'] > [data-part='legend'] > :is(h1, h2, h3, h4, h5, h6) {
134
+ [data-ui-field-group] > [data-part-legend] > :is(h1, h2, h3, h4, h5, h6) {
135
135
  display: inline;
136
136
  font-family: var(
137
137
  --slotted-font-family-heading,
@@ -140,9 +140,9 @@
140
140
  margin: 0;
141
141
  }
142
142
 
143
- [data-ui='field-group']:is([data-necessity='optional'], [data-necessity='words'])
144
- > [data-part='legend']
145
- > [data-part='mark'] {
143
+ [data-ui-field-group]:is([data-necessity='optional'], [data-necessity='words'])
144
+ > [data-part-legend]
145
+ > [data-part-mark] {
146
146
  color: var(--slotted-field-group-mark-text-color, var(--slotted-text-muted));
147
147
  font-size: var(--slotted-control-font-size-sm, 12px);
148
148
  font-weight: var(--slotted-font-weight-regular, 400);
@@ -154,8 +154,7 @@
154
154
  * below from moving when the error arrives. The same two rules the field
155
155
  * writes, because the group holds the same two messages.
156
156
  */
157
- [data-ui='field-group']
158
- > [data-ui='inline-message']:not([data-reserve]):has([data-part='text']:empty) {
157
+ [data-ui-field-group] > [data-ui-inline-message]:not([data-reserve]):has([data-part-text]:empty) {
159
158
  display: none;
160
159
  }
161
160
 
@@ -167,12 +166,12 @@
167
166
  * selector carries the root's part so it outweighs the message family's own
168
167
  * root rule, which has the same two attributes.
169
168
  */
170
- [data-ui='field-group'][data-part='root'] > [data-ui='inline-message'] {
169
+ [data-ui-field-group][data-part-root] > [data-ui-inline-message] {
171
170
  font-size: var(--slotted-font-size-xs, 0.75rem);
172
171
  }
173
172
 
174
- [data-ui='field-group'][data-part='root'] > [data-ui='inline-message'][data-tone='danger'],
175
- [data-ui='field-group'][data-part='root'] > [data-ui='inline-message'][data-tone='success'] {
173
+ [data-ui-field-group][data-part-root] > [data-ui-inline-message][data-tone='danger'],
174
+ [data-ui-field-group][data-part-root] > [data-ui-inline-message][data-tone='success'] {
176
175
  font-weight: var(--slotted-font-weight-medium, 500);
177
176
  }
178
177
 
@@ -188,19 +187,19 @@
188
187
  * a scale: `14rem` holds a date, a document number or a short name at the `md`
189
188
  * step without the control clipping what is being typed into it.
190
189
  */
191
- [data-ui='field-group'] > [data-part='content'] {
190
+ [data-ui-field-group] > [data-part-content] {
192
191
  display: flex;
193
192
  flex-direction: column;
194
193
  gap: var(--_field-gap);
195
194
  min-inline-size: 0;
196
195
  }
197
196
 
198
- [data-ui='field-group'][data-orientation='horizontal'] > [data-part='content'] {
197
+ [data-ui-field-group][data-orientation='horizontal'] > [data-part-content] {
199
198
  flex-direction: row;
200
199
  flex-wrap: wrap;
201
200
  }
202
201
 
203
- [data-ui='field-group'][data-orientation='horizontal'] > [data-part='content'] > * {
202
+ [data-ui-field-group][data-orientation='horizontal'] > [data-part-content] > * {
204
203
  flex: 1 1 var(--slotted-field-group-track-min, 14rem);
205
204
  min-inline-size: 0;
206
205
  }
@@ -217,10 +216,8 @@
217
216
  * disabled appearance at all, which is the defect
218
217
  * `docs/history/designs/2026-08-31-field-aware-controls-design.md` records.
219
218
  */
220
- [data-ui='field-group'][data-part='root'][data-disabled] > [data-part='legend'],
221
- [data-ui='field-group'][data-part='root'][data-disabled]
222
- > [data-part='legend']
223
- > [data-part='mark'] {
219
+ [data-ui-field-group][data-part-root][data-disabled] > [data-part-legend],
220
+ [data-ui-field-group][data-part-root][data-disabled] > [data-part-legend] > [data-part-mark] {
224
221
  color: var(--slotted-disabled-foreground);
225
222
  }
226
223
  }