@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
@@ -13,7 +13,7 @@
13
13
  * used outside a field looks the same as one inside it and the field's DOM
14
14
  * never becomes part of this stylesheet's contract.
15
15
  */
16
- [data-ui='text-field'][data-part='root'] {
16
+ [data-ui-text-field][data-part-root] {
17
17
  /**
18
18
  * Type, height, inline padding, gap and glyph size all come from the
19
19
  * control scales — the only ones the theme restates per density — so a
@@ -130,15 +130,15 @@
130
130
  * The cost is written down: at `md` the glyph now ends four pixels nearer
131
131
  * the border than the text begins from it.
132
132
  */
133
- [data-ui='text-field'][data-part='root']:has(
134
- > :is([data-part='clear'], [data-part='copy'], [data-part='reveal']):not([hidden]):last-child,
135
- > [data-part='end']:last-child > [data-part='action']:last-child
133
+ [data-ui-text-field][data-part-root]:has(
134
+ > :is([data-part-clear], [data-part-copy], [data-part-reveal]):not([hidden]):last-child,
135
+ > [data-part-end]:last-child > [data-part-action]:last-child
136
136
  ) {
137
137
  padding-inline-end: var(--_inset);
138
138
  }
139
139
 
140
- [data-ui='text-field'][data-part='root']:has(
141
- > [data-part='start']:first-child > [data-part='action']:first-child
140
+ [data-ui-text-field][data-part-root]:has(
141
+ > [data-part-start]:first-child > [data-part-action]:first-child
142
142
  ) {
143
143
  padding-inline-start: var(--_inset);
144
144
  }
@@ -149,7 +149,7 @@
149
149
  * it a text control: the value, the caret, the selection and every native
150
150
  * attribute a consumer wrote.
151
151
  */
152
- [data-ui='text-field'] > [data-part='input'] {
152
+ [data-ui-text-field] > [data-part-input] {
153
153
  background-color: transparent;
154
154
  /* The frame's border box, not its content box: on a coarse pointer the frame
155
155
  is the touch target's height and the control it holds is too. Stretched
@@ -175,7 +175,7 @@
175
175
  text-overflow: ellipsis;
176
176
  }
177
177
 
178
- [data-ui='text-field'] > [data-part='input']::placeholder {
178
+ [data-ui-text-field] > [data-part-input]::placeholder {
179
179
  color: var(--slotted-text-field-placeholder-color, var(--slotted-text-muted, GrayText));
180
180
  /* A placeholder longer than the control is clipped at a word rather than
181
181
  mid-glyph, which is the difference between a hint and a smear. */
@@ -187,21 +187,32 @@
187
187
  * `type="search"` control would be the second. The native decorations are
188
188
  * withdrawn rather than left to overlap.
189
189
  */
190
- [data-ui='text-field'] > [data-part='input']::-webkit-search-cancel-button,
191
- [data-ui='text-field'] > [data-part='input']::-webkit-search-decoration {
190
+ [data-ui-text-field] > [data-part-input]::-webkit-search-cancel-button,
191
+ [data-ui-text-field] > [data-part-input]::-webkit-search-decoration {
192
192
  appearance: none;
193
193
  }
194
194
 
195
195
  /**
196
- * Autofill. Chrome paints its own ground over the control's, and the classic
197
- * repair — a hundred-pixel inset shadow — is the only way to reach it. The
198
- * signal is kept rather than erased: an autofilled value is a fact worth
199
- * seeing, so it is repainted in the accent surface the theme owns instead of
200
- * in the browser's yellow.
201
- */
202
- [data-ui='text-field'] > [data-part='input']:autofill {
196
+ * Autofill. Chrome paints its own ground over the input, and a hundred-pixel
197
+ * inset shadow is the only way to reach it. The signal is kept rather than
198
+ * erased, in the accent surface the theme owns, and it is the whole
199
+ * control's: the frame takes the tint under its border and inside its
200
+ * corner, and the input repaints the browser's ground in the same colour.
201
+ * Painted on the input alone, the tint left the frame's padding, the slots
202
+ * and the buttons bare, and covered the border the input overlaps by one width.
203
+ */
204
+ [data-ui-text-field][data-part-root]:has(> [data-part-input]:autofill) {
205
+ background-color: var(
206
+ --slotted-text-field-autofill-background,
207
+ var(--slotted-tone-accent-surface)
208
+ );
209
+ }
210
+
211
+ [data-ui-text-field] > [data-part-input]:autofill {
203
212
  box-shadow: inset 0 0 0 100px
204
213
  var(--slotted-text-field-autofill-background, var(--slotted-tone-accent-surface));
214
+ /* The input overlaps the frame's border by one width; the tint stops at it. */
215
+ clip-path: inset(var(--slotted-control-border-width, 1px) 0);
205
216
  -webkit-text-fill-color: var(--slotted-text-field-color, var(--slotted-text, CanvasText));
206
217
  }
207
218
 
@@ -213,7 +224,7 @@
213
224
  * disagreeing about one row.
214
225
  */
215
226
 
216
- [data-ui='text-field'][data-part='root'][data-size='sm'] {
227
+ [data-ui-text-field][data-part-root][data-size='sm'] {
217
228
  --_font-size: var(--slotted-control-font-size-sm, 12px);
218
229
  --_height: var(--slotted-control-height-sm, 30px);
219
230
  --_padding-inline: var(--slotted-control-padding-inline-sm, 10px);
@@ -222,7 +233,7 @@
222
233
  --_inner-size: var(--slotted-control-inner-size-sm, 22px);
223
234
  }
224
235
 
225
- [data-ui='text-field'][data-part='root'][data-size='md'] {
236
+ [data-ui-text-field][data-part-root][data-size='md'] {
226
237
  --_font-size: var(--slotted-control-font-size-md, 13px);
227
238
  --_height: var(--slotted-control-height-md, 34px);
228
239
  --_padding-inline: var(--slotted-control-padding-inline-md, 13px);
@@ -231,7 +242,7 @@
231
242
  --_inner-size: var(--slotted-control-inner-size-md, 24px);
232
243
  }
233
244
 
234
- [data-ui='text-field'][data-part='root'][data-size='lg'] {
245
+ [data-ui-text-field][data-part-root][data-size='lg'] {
235
246
  --_font-size: var(--slotted-control-font-size-lg, 14px);
236
247
  --_height: var(--slotted-control-height-lg, 38px);
237
248
  --_padding-inline: var(--slotted-control-padding-inline-lg, 16px);
@@ -246,7 +257,7 @@
246
257
  * it takes the width the buttons leave rather than the whole row, so the
247
258
  * button's label never wraps to make room for it.
248
259
  */
249
- [data-ui='button-group'] > [data-ui='text-field'][data-part='root'] {
260
+ [data-ui-button-group] > [data-ui-text-field][data-part-root] {
250
261
  flex: 1 1 0;
251
262
  inline-size: auto;
252
263
  }
@@ -265,7 +276,7 @@
265
276
  * pointer crosses it.
266
277
  */
267
278
 
268
- [data-ui='text-field'][data-part='root'][data-variant='subtle'] {
279
+ [data-ui-text-field][data-part-root][data-variant='subtle'] {
269
280
  background-color: var(
270
281
  --slotted-text-field-subtle-background,
271
282
  var(--slotted-surface-sunken, Canvas)
@@ -279,7 +290,7 @@
279
290
  /* No edge, no lift, no ground and no corner of its own: the cell it sits in
280
291
  is the box, the row is the ground, a cell has no corner, and the resting
281
292
  shadow would draw the cell where there is none. */
282
- [data-ui='text-field'][data-part='root'][data-variant='plain'] {
293
+ [data-ui-text-field][data-part-root][data-variant='plain'] {
283
294
  background-color: transparent;
284
295
  border-color: transparent;
285
296
  border-radius: var(--slotted-radius-none, 0px);
@@ -292,7 +303,7 @@
292
303
  * its only edge exactly where an edge matters most.
293
304
  */
294
305
  @media (forced-colors: active) {
295
- [data-ui='text-field'][data-part='root'][data-variant='plain'] {
306
+ [data-ui-text-field][data-part-root][data-variant='plain'] {
296
307
  border-color: ButtonBorder;
297
308
  }
298
309
  }
@@ -302,7 +313,7 @@
302
313
  * A back-office form full of identifiers, hashes and keys, which is the
303
314
  * audience `docs/product/prd.md` names first. Primer and Polaris both ship it.
304
315
  */
305
- [data-ui='text-field'][data-part='root'][data-mono] {
316
+ [data-ui-text-field][data-part-root][data-mono] {
306
317
  font-family: var(--slotted-font-family-mono, monospace);
307
318
  /* Digits that do not shift as a value is typed over. */
308
319
  font-variant-numeric: tabular-nums;
@@ -315,8 +326,8 @@
315
326
  * than the value: an adornment annotates, and a reader looking for what they
316
327
  * typed should not have to step over it.
317
328
  */
318
- [data-ui='text-field'] > [data-part='start'],
319
- [data-ui='text-field'] > [data-part='end'] {
329
+ [data-ui-text-field] > [data-part-start],
330
+ [data-ui-text-field] > [data-part-end] {
320
331
  align-items: center;
321
332
  color: var(--slotted-text-field-adornment-color, var(--slotted-text-muted, GrayText));
322
333
  display: inline-flex;
@@ -345,16 +356,16 @@
345
356
  * table draws a 12-pixel glyph and nothing has to be written per instance.
346
357
  * A bare `svg` a consumer passed instead is held to the same box.
347
358
  */
348
- [data-ui='text-field'] > [data-part='start'],
349
- [data-ui='text-field'] > [data-part='end'] {
359
+ [data-ui-text-field] > [data-part-start],
360
+ [data-ui-text-field] > [data-part-end] {
350
361
  --slotted-icon-size: var(--_icon-size);
351
362
  /* And a key or a chip placed there is the height the inside of this
352
363
  control has, from the foundation's scale for it. */
353
364
  --slotted-control-inner-size: var(--_inner-size);
354
365
  }
355
366
 
356
- [data-ui='text-field'] > [data-part='start'] > svg,
357
- [data-ui='text-field'] > [data-part='end'] > svg {
367
+ [data-ui-text-field] > [data-part-start] > svg,
368
+ [data-ui-text-field] > [data-part-end] > svg {
358
369
  block-size: var(--_icon-size);
359
370
  inline-size: var(--_icon-size);
360
371
  }
@@ -373,10 +384,8 @@
373
384
  * keeps the gap to the value equal as well, and because a symmetric padding
374
385
  * cannot disagree with `unicode-bidi: plaintext` about which side is which.
375
386
  */
376
- [data-ui='text-field']
377
- > [data-part='start']:not(:has(svg, img, [data-ui='icon'], [data-part='action'])),
378
- [data-ui='text-field']
379
- > [data-part='end']:not(:has(svg, img, [data-ui='icon'], [data-part='action'])) {
387
+ [data-ui-text-field] > [data-part-start]:not(:has(svg, img, [data-ui-icon], [data-part-action])),
388
+ [data-ui-text-field] > [data-part-end]:not(:has(svg, img, [data-ui-icon], [data-part-action])) {
380
389
  padding-inline: calc(var(--_icon-size) / 8);
381
390
  }
382
391
 
@@ -390,8 +399,8 @@
390
399
  * Their glyphs are the `Glyph` element the binding renders: a character is
391
400
  * never an icon.
392
401
  */
393
- [data-ui='text-field'] > :is([data-part='clear'], [data-part='copy'], [data-part='reveal']),
394
- [data-ui='text-field'] > :is([data-part='start'], [data-part='end']) > [data-part='action'] {
402
+ [data-ui-text-field] > :is([data-part-clear], [data-part-copy], [data-part-reveal]),
403
+ [data-ui-text-field] > :is([data-part-start], [data-part-end]) > [data-part-action] {
395
404
  --slotted-icon-size: var(--_icon-size);
396
405
 
397
406
  align-items: center;
@@ -434,9 +443,9 @@
434
443
  * the two, so the attribute that makes it accessible is the one that shapes
435
444
  * it.
436
445
  */
437
- [data-ui='text-field']
438
- > :is([data-part='start'], [data-part='end'])
439
- > [data-part='action']:not([aria-label], [aria-labelledby]) {
446
+ [data-ui-text-field]
447
+ > :is([data-part-start], [data-part-end])
448
+ > [data-part-action]:not([aria-label], [aria-labelledby]) {
440
449
  /* Words in the frame's quiet ink read as a suffix, not as something to
441
450
  press: "Search" beside the value looked like a unit. A named command
442
451
  or a chosen country code carries the value's ink; a lone mark stays
@@ -458,9 +467,9 @@
458
467
  * translate puts its centre at `(1cap + 1ex) / 4` above the baseline — the
459
468
  * midpoint of the capitals' and the lowercase letters' own centres.
460
469
  */
461
- [data-ui='text-field']
462
- > :is([data-part='start'], [data-part='end'])
463
- > [data-part='action']:not([aria-label], [aria-labelledby]) {
470
+ [data-ui-text-field]
471
+ > :is([data-part-start], [data-part-end])
472
+ > [data-part-action]:not([aria-label], [aria-labelledby]) {
464
473
  align-content: center;
465
474
  align-items: baseline;
466
475
  display: inline-grid;
@@ -468,10 +477,10 @@
468
477
  justify-content: center;
469
478
  }
470
479
 
471
- [data-ui='text-field']
472
- > :is([data-part='start'], [data-part='end'])
473
- > [data-part='action']:not([aria-label], [aria-labelledby])
474
- > [data-ui='icon'] {
480
+ [data-ui-text-field]
481
+ > :is([data-part-start], [data-part-end])
482
+ > [data-part-action]:not([aria-label], [aria-labelledby])
483
+ > [data-ui-icon] {
475
484
  margin-block-start: calc((1cap + 1ex) / 4 - var(--_icon-size) / 2);
476
485
  translate: 0 calc(var(--_icon-size) / 2 - (1cap + 1ex) / 4);
477
486
  }
@@ -480,7 +489,7 @@
480
489
  * An adornment holding a button is not quiet text any more: its gap is the
481
490
  * one between two buttons, and it does not pad a glyph that is not there.
482
491
  */
483
- [data-ui='text-field'] > :is([data-part='start'], [data-part='end']):has(> [data-part='action']) {
492
+ [data-ui-text-field] > :is([data-part-start], [data-part-end]):has(> [data-part-action]) {
484
493
  gap: 0;
485
494
  }
486
495
 
@@ -493,11 +502,8 @@
493
502
  * correction `docs/token-foundation.md` leaves to the family rather than to
494
503
  * the theme.
495
504
  */
496
- [data-ui='text-field']
497
- > :is([data-part='clear'], [data-part='copy'], [data-part='reveal'])::after,
498
- [data-ui='text-field']
499
- > :is([data-part='start'], [data-part='end'])
500
- > [data-part='action']::after {
505
+ [data-ui-text-field] > :is([data-part-clear], [data-part-copy], [data-part-reveal])::after,
506
+ [data-ui-text-field] > :is([data-part-start], [data-part-end]) > [data-part-action]::after {
501
507
  content: '';
502
508
  inset: min(0px, calc((100% - var(--slotted-target-min, 24px)) / 2));
503
509
  position: absolute;
@@ -508,45 +514,42 @@
508
514
  the hit area grows to 44 pixels around them. Side by side, no button
509
515
  reaches across the edge it shares with the next. */
510
516
  @media (pointer: coarse) {
511
- [data-ui='text-field']
512
- > :is([data-part='start'], [data-part='end'])
513
- > [data-part='action']::after,
514
- [data-ui='text-field']
515
- > :is([data-part='clear'], [data-part='copy'], [data-part='reveal'])::after {
517
+ [data-ui-text-field] > :is([data-part-start], [data-part-end]) > [data-part-action]::after,
518
+ [data-ui-text-field] > :is([data-part-clear], [data-part-copy], [data-part-reveal])::after {
516
519
  inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
517
520
  }
518
521
 
519
- [data-ui='text-field']
520
- > :is([data-part='clear'], [data-part='copy']):has(
521
- ~ :is([data-part='copy'], [data-part='reveal']):not([hidden])
522
+ [data-ui-text-field]
523
+ > :is([data-part-clear], [data-part-copy]):has(
524
+ ~ :is([data-part-copy], [data-part-reveal]):not([hidden])
522
525
  )::after,
523
- [data-ui='text-field']
524
- > :is([data-part='start'], [data-part='end'])
525
- > [data-part='action']:has(+ [data-part='action'])::after {
526
+ [data-ui-text-field]
527
+ > :is([data-part-start], [data-part-end])
528
+ > [data-part-action]:has(+ [data-part-action])::after {
526
529
  inset-inline-end: 0;
527
530
  }
528
531
 
529
- [data-ui='text-field']
530
- > :is([data-part='clear'], [data-part='copy']):not([hidden])
531
- ~ :is([data-part='copy'], [data-part='reveal'])::after,
532
- [data-ui='text-field']
533
- > :is([data-part='start'], [data-part='end'])
534
- > [data-part='action']
535
- + [data-part='action']::after {
532
+ [data-ui-text-field]
533
+ > :is([data-part-clear], [data-part-copy]):not([hidden])
534
+ ~ :is([data-part-copy], [data-part-reveal])::after,
535
+ [data-ui-text-field]
536
+ > :is([data-part-start], [data-part-end])
537
+ > [data-part-action]
538
+ + [data-part-action]::after {
536
539
  inset-inline-start: 0;
537
540
  }
538
541
  }
539
542
 
540
543
  /* An open menu keeps its button pressed under the pointer as well, and a
541
544
  finished copy keeps its success ink until the check goes. */
542
- [data-ui='text-field']
543
- > :is([data-part='clear'], [data-part='copy'], [data-part='reveal']):hover:not(
545
+ [data-ui-text-field]
546
+ > :is([data-part-clear], [data-part-copy], [data-part-reveal]):hover:not(
544
547
  :disabled,
545
548
  [data-complete]
546
549
  ),
547
- [data-ui='text-field']
548
- > :is([data-part='start'], [data-part='end'])
549
- > [data-part='action']:hover:not(:disabled, [aria-expanded='true']) {
550
+ [data-ui-text-field]
551
+ > :is([data-part-start], [data-part-end])
552
+ > [data-part-action]:hover:not(:disabled, [aria-expanded='true']) {
550
553
  background-color: var(
551
554
  --slotted-text-field-action-hover-background,
552
555
  var(--slotted-tone-secondary-subtle-hover)
@@ -559,11 +562,11 @@
559
562
  * settles a pixel, and inside a 24-pixel box beside the value that reads as
560
563
  * the value moving (dossier § 4, `recusar`).
561
564
  */
562
- [data-ui='text-field']
563
- > :is([data-part='clear'], [data-part='copy'], [data-part='reveal']):active:not(:disabled),
564
- [data-ui='text-field']
565
- > :is([data-part='start'], [data-part='end'])
566
- > [data-part='action']:active:not(:disabled) {
565
+ [data-ui-text-field]
566
+ > :is([data-part-clear], [data-part-copy], [data-part-reveal]):active:not(:disabled),
567
+ [data-ui-text-field]
568
+ > :is([data-part-start], [data-part-end])
569
+ > [data-part-action]:active:not(:disabled) {
567
570
  background-color: var(
568
571
  --slotted-text-field-action-active-background,
569
572
  var(--slotted-tone-secondary-subtle-active)
@@ -571,21 +574,19 @@
571
574
  }
572
575
 
573
576
  /* A menu or a popover the button opened keeps it pressed while it is open. */
574
- [data-ui='text-field']
575
- > :is([data-part='start'], [data-part='end'])
576
- > [data-part='action'][aria-expanded='true'] {
577
+ [data-ui-text-field]
578
+ > :is([data-part-start], [data-part-end])
579
+ > [data-part-action][aria-expanded='true'] {
577
580
  background-color: var(
578
581
  --slotted-text-field-action-active-background,
579
582
  var(--slotted-tone-secondary-subtle-active)
580
583
  );
581
584
  }
582
585
 
583
- [data-ui='text-field']
584
- > :is([data-part='start'], [data-part='end'])
585
- > [data-part='action']:disabled,
586
- [data-ui='text-field'][data-part='root'][data-disabled]
587
- > :is([data-part='start'], [data-part='end'])
588
- > [data-part='action'] {
586
+ [data-ui-text-field] > :is([data-part-start], [data-part-end]) > [data-part-action]:disabled,
587
+ [data-ui-text-field][data-part-root][data-disabled]
588
+ > :is([data-part-start], [data-part-end])
589
+ > [data-part-action] {
589
590
  color: var(--slotted-disabled-foreground);
590
591
  cursor: not-allowed;
591
592
  }
@@ -595,17 +596,16 @@
595
596
  * from the value to a button has to move something visible, and a ring
596
597
  * around the whole frame would sit still while focus moved inside it.
597
598
  */
598
- [data-ui='text-field']
599
- > :is([data-part='clear'], [data-part='copy'], [data-part='reveal']):focus-visible,
600
- [data-ui='text-field']
601
- > :is([data-part='start'], [data-part='end'])
602
- > [data-part='action']:focus-visible {
599
+ [data-ui-text-field] > :is([data-part-clear], [data-part-copy], [data-part-reveal]):focus-visible,
600
+ [data-ui-text-field]
601
+ > :is([data-part-start], [data-part-end])
602
+ > [data-part-action]:focus-visible {
603
603
  outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
604
604
  outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
605
605
  }
606
606
 
607
607
  /** A copy that finished: the mark changes as well as the ink, and returns on its own. */
608
- [data-ui='text-field'] > [data-part='copy'][data-complete] {
608
+ [data-ui-text-field] > [data-part-copy][data-complete] {
609
609
  color: var(
610
610
  --slotted-text-field-copy-complete-color,
611
611
  var(--slotted-tone-success-text, CanvasText)
@@ -618,14 +618,14 @@
618
618
  * fifths of its size and transparent, on the entering curve. Nothing leaves:
619
619
  * the old mark is gone in the same frame, so there is no exit to time.
620
620
  */
621
- [data-ui='text-field'] > :is([data-part='copy'], [data-part='reveal']) > [data-ui='icon'] {
621
+ [data-ui-text-field] > :is([data-part-copy], [data-part-reveal]) > [data-ui-icon] {
622
622
  transition:
623
623
  opacity var(--slotted-duration-short) var(--slotted-easing-enter),
624
624
  scale var(--slotted-duration-short) var(--slotted-easing-enter);
625
625
  }
626
626
 
627
627
  @starting-style {
628
- [data-ui='text-field'] > :is([data-part='copy'], [data-part='reveal']) > [data-ui='icon'] {
628
+ [data-ui-text-field] > :is([data-part-copy], [data-part-reveal]) > [data-ui-icon] {
629
629
  opacity: 0;
630
630
  scale: 0.8;
631
631
  }
@@ -641,8 +641,8 @@
641
641
  * out on the leaving one, in the same short step, and `display` is held
642
642
  * until it has gone.
643
643
  */
644
- [data-ui='text-field']
645
- > :is([data-part='busy'], [data-part='caps-lock'], [data-part='clear'], [data-part='copy']) {
644
+ [data-ui-text-field]
645
+ > :is([data-part-busy], [data-part-caps-lock], [data-part-clear], [data-part-copy]) {
646
646
  transition:
647
647
  var(--_action-transition),
648
648
  opacity var(--slotted-duration-short) var(--slotted-easing-enter),
@@ -650,13 +650,8 @@
650
650
  display var(--slotted-duration-short) allow-discrete;
651
651
  }
652
652
 
653
- [data-ui='text-field']
654
- > :is(
655
- [data-part='busy'],
656
- [data-part='caps-lock'],
657
- [data-part='clear'],
658
- [data-part='copy']
659
- )[hidden] {
653
+ [data-ui-text-field]
654
+ > :is([data-part-busy], [data-part-caps-lock], [data-part-clear], [data-part-copy])[hidden] {
660
655
  display: none;
661
656
  opacity: 0;
662
657
  scale: 0.8;
@@ -667,8 +662,8 @@
667
662
  }
668
663
 
669
664
  @starting-style {
670
- [data-ui='text-field']
671
- > :is([data-part='busy'], [data-part='caps-lock'], [data-part='clear'], [data-part='copy']) {
665
+ [data-ui-text-field]
666
+ > :is([data-part-busy], [data-part-caps-lock], [data-part-clear], [data-part-copy]) {
672
667
  opacity: 0;
673
668
  scale: 0.8;
674
669
  }
@@ -678,7 +673,7 @@
678
673
  * The ring is the one `spinner` draws for every family, at this control's
679
674
  * glyph size, so it occupies the box a mark beside it would.
680
675
  */
681
- [data-ui='text-field'] > [data-part='busy'] {
676
+ [data-ui-text-field] > [data-part-busy] {
682
677
  --slotted-spinner-size: var(--_icon-size);
683
678
 
684
679
  color: var(--slotted-text-field-adornment-color, var(--slotted-text-muted, GrayText));
@@ -690,7 +685,7 @@
690
685
  * the value, so it is the warning ink on the glyph alone and never the
691
686
  * frame's edge — the frame's one alarming state is `invalid`.
692
687
  */
693
- [data-ui='text-field'] > [data-part='caps-lock'] {
688
+ [data-ui-text-field] > [data-part-caps-lock] {
694
689
  --slotted-icon-size: var(--_icon-size);
695
690
 
696
691
  align-items: center;
@@ -705,24 +700,24 @@
705
700
  * one it can meet, which is the order `STATE_PRECEDENCE` sets.
706
701
  */
707
702
 
708
- [data-ui='text-field'][data-part='root']:hover:not([data-disabled]):not([data-readonly]):not(
703
+ [data-ui-text-field][data-part-root]:hover:not([data-disabled]):not([data-readonly]):not(
709
704
  [data-invalid]
710
705
  ) {
711
706
  border-color: var(--slotted-text-field-hover-border-color, var(--slotted-tone-accent-border));
712
707
  }
713
708
 
714
- [data-ui='text-field'][data-part='root'][data-variant='subtle']:hover:not([data-disabled]):not(
709
+ [data-ui-text-field][data-part-root][data-variant='subtle']:hover:not([data-disabled]):not(
715
710
  [data-readonly]
716
- ):not([data-invalid]) {
711
+ ):not([data-invalid]):not(:has(> [data-part-input]:autofill)) {
717
712
  background-color: var(
718
713
  --slotted-text-field-subtle-hover-background,
719
714
  var(--slotted-tone-secondary-subtle-hover)
720
715
  );
721
716
  }
722
717
 
723
- [data-ui='text-field'][data-part='root'][data-variant='plain']:hover:not([data-disabled]):not(
718
+ [data-ui-text-field][data-part-root][data-variant='plain']:hover:not([data-disabled]):not(
724
719
  [data-readonly]
725
- ):not([data-invalid]) {
720
+ ):not([data-invalid]):not(:has(> [data-part-input]:autofill)) {
726
721
  background-color: var(
727
722
  --slotted-text-field-plain-hover-background,
728
723
  var(--slotted-tone-secondary-subtle-hover)
@@ -737,7 +732,7 @@
737
732
  * pointer press as well as for a Tab, which is exactly right for a control
738
733
  * whose caret is the thing that moved.
739
734
  */
740
- [data-ui='text-field'][data-part='root']:has(> [data-part='input']:focus-visible) {
735
+ [data-ui-text-field][data-part-root]:has(> [data-part-input]:focus-visible) {
741
736
  /**
742
737
  * The resting shadow, recoloured. The geometry is the foundation's and the
743
738
  * ink is the focus ring's, so the lift under the control and the ring
@@ -746,7 +741,7 @@
746
741
  box-shadow: var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
747
742
  var(--slotted-focus-ring-color, Highlight);
748
743
  outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
749
- outline-offset: var(--slotted-focus-ring-offset, 2px);
744
+ outline-offset: var(--slotted-control-focus-ring-offset, var(--slotted-focus-ring-offset, 2px));
750
745
  }
751
746
 
752
747
  /**
@@ -756,8 +751,8 @@
756
751
  * shadow that appears only under focus is a cell that changes size when it
757
752
  * is used.
758
753
  */
759
- [data-ui='text-field'][data-part='root'][data-variant='plain']:has(
760
- > [data-part='input']:focus-visible
754
+ [data-ui-text-field][data-part-root][data-variant='plain']:has(
755
+ > [data-part-input]:focus-visible
761
756
  ) {
762
757
  box-shadow: none;
763
758
  outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
@@ -775,7 +770,7 @@
775
770
  * rule for a family, and it is the rule `checkbox`, `radio-group` and
776
771
  * `switch` inherit rather than restate when they arrive.
777
772
  */
778
- [data-ui='text-field'][data-part='root'][data-invalid] {
773
+ [data-ui-text-field][data-part-root][data-invalid] {
779
774
  --slotted-focus-ring-color: var(
780
775
  --slotted-text-field-invalid-focus-ring-color,
781
776
  var(--slotted-focus-ring-color-invalid, Highlight)
@@ -802,15 +797,15 @@
802
797
  box-shadow: var(--_invalid-edge);
803
798
  }
804
799
 
805
- [data-ui='text-field'][data-part='root'][data-invalid]:has(> [data-part='input']:focus-visible) {
800
+ [data-ui-text-field][data-part-root][data-invalid]:has(> [data-part-input]:focus-visible) {
806
801
  box-shadow:
807
802
  var(--_invalid-edge),
808
803
  var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
809
804
  var(--slotted-focus-ring-color, Highlight);
810
805
  }
811
806
 
812
- [data-ui='text-field'][data-part='root'][data-variant='plain'][data-invalid]:has(
813
- > [data-part='input']:focus-visible
807
+ [data-ui-text-field][data-part-root][data-variant='plain'][data-invalid]:has(
808
+ > [data-part-input]:focus-visible
814
809
  ) {
815
810
  /* The ring lies inside the box here, over the border and an edge as wide as
816
811
  it; the edge reaches past the ring. */
@@ -828,23 +823,24 @@
828
823
  * control draws its ring double, which a valid ring is not.
829
824
  */
830
825
  @media (forced-colors: active) {
831
- [data-ui='text-field'][data-part='root'][data-invalid] {
826
+ [data-ui-text-field][data-part-root][data-invalid] {
832
827
  outline: var(--_invalid-edge-width) solid CanvasText;
833
828
  outline-offset: calc(
834
829
  -1 * (var(--slotted-control-border-width, 1px) + var(--_invalid-edge-width))
835
830
  );
836
831
  }
837
832
 
838
- [data-ui='text-field'][data-part='root'][data-invalid]:has(
839
- > [data-part='input']:focus-visible
840
- ) {
833
+ [data-ui-text-field][data-part-root][data-invalid]:has(> [data-part-input]:focus-visible) {
841
834
  outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
842
835
  var(--slotted-focus-ring-color, Highlight);
843
- outline-offset: var(--slotted-focus-ring-offset, 2px);
836
+ outline-offset: var(
837
+ --slotted-control-focus-ring-offset,
838
+ var(--slotted-focus-ring-offset, 2px)
839
+ );
844
840
  }
845
841
 
846
- [data-ui='text-field'][data-part='root'][data-variant='plain'][data-invalid]:has(
847
- > [data-part='input']:focus-visible
842
+ [data-ui-text-field][data-part-root][data-variant='plain'][data-invalid]:has(
843
+ > [data-part-input]:focus-visible
848
844
  ) {
849
845
  outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
850
846
  var(--slotted-focus-ring-color, Highlight);
@@ -859,7 +855,7 @@
859
855
  * mistakable for disabled: the value is still real and still submitted. The
860
856
  * ground says "not yours to change" and the ink says nothing at all.
861
857
  */
862
- [data-ui='text-field'][data-part='root'][data-readonly] {
858
+ [data-ui-text-field][data-part-root][data-readonly] {
863
859
  background-color: var(
864
860
  --slotted-text-field-readonly-background,
865
861
  var(--slotted-tone-secondary-subtle-hover)
@@ -875,8 +871,8 @@
875
871
  * operable and answering nothing — a defect the deleted `input` family
876
872
  * recorded and fixed, and one no rebuild is allowed to reintroduce.
877
873
  */
878
- [data-ui='text-field'][data-part='root'][data-disabled],
879
- [data-ui='text-field'][data-part='root']:has(> [data-part='input']:disabled) {
874
+ [data-ui-text-field][data-part-root][data-disabled],
875
+ [data-ui-text-field][data-part-root]:has(> [data-part-input]:disabled) {
880
876
  background-color: var(
881
877
  --slotted-text-field-disabled-background,
882
878
  var(--slotted-disabled-background)
@@ -893,8 +889,8 @@
893
889
  * value nobody can read is a field nobody can check, and a disabled form
894
890
  * still has to say what it holds.
895
891
  */
896
- [data-ui='text-field'][data-part='root'][data-disabled] > [data-part='start'],
897
- [data-ui='text-field'][data-part='root'][data-disabled] > [data-part='end'] {
892
+ [data-ui-text-field][data-part-root][data-disabled] > [data-part-start],
893
+ [data-ui-text-field][data-part-root][data-disabled] > [data-part-end] {
898
894
  color: var(--slotted-disabled-foreground);
899
895
  }
900
896
  }
@@ -2,6 +2,7 @@
2
2
  "--slotted-border-subtle",
3
3
  "--slotted-control-border-color",
4
4
  "--slotted-control-border-width",
5
+ "--slotted-control-focus-ring-offset",
5
6
  "--slotted-control-font-family",
6
7
  "--slotted-control-font-size-lg",
7
8
  "--slotted-control-font-size-md",