@slotted/styles 0.0.0-stage → 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/package.json +276 -3
  4. package/src/accordion/accordion.css +96 -0
  5. package/src/accordion/accordion.tokens.json +14 -0
  6. package/src/action-bar/action-bar.css +455 -0
  7. package/src/action-bar/action-bar.tokens.json +50 -0
  8. package/src/action-sheet/action-sheet.css +462 -0
  9. package/src/action-sheet/action-sheet.tokens.json +59 -0
  10. package/src/alert/alert.css +764 -0
  11. package/src/alert/alert.tokens.json +77 -0
  12. package/src/app-shell/app-shell.css +1899 -0
  13. package/src/app-shell/app-shell.tokens.json +88 -0
  14. package/src/aspect-ratio/aspect-ratio.css +131 -0
  15. package/src/aspect-ratio/aspect-ratio.tokens.json +1 -0
  16. package/src/attachment/attachment.css +906 -0
  17. package/src/attachment/attachment.tokens.json +85 -0
  18. package/src/avatar/avatar.css +598 -0
  19. package/src/avatar/avatar.tokens.json +64 -0
  20. package/src/avatar-group/avatar-group.css +268 -0
  21. package/src/avatar-group/avatar-group.tokens.json +16 -0
  22. package/src/badge/badge.css +462 -0
  23. package/src/badge/badge.tokens.json +58 -0
  24. package/src/breadcrumb/breadcrumb.css +441 -0
  25. package/src/breadcrumb/breadcrumb.tokens.json +50 -0
  26. package/src/button/button.css +754 -0
  27. package/src/button/button.tokens.json +72 -0
  28. package/src/button-group/button-group.css +455 -0
  29. package/src/button-group/button-group.tokens.json +11 -0
  30. package/src/calendar/calendar.css +846 -0
  31. package/src/calendar/calendar.tokens.json +67 -0
  32. package/src/card/card.css +602 -0
  33. package/src/card/card.tokens.json +68 -0
  34. package/src/carousel/carousel.css +860 -0
  35. package/src/carousel/carousel.tokens.json +62 -0
  36. package/src/cascader/cascader.css +1320 -0
  37. package/src/cascader/cascader.tokens.json +103 -0
  38. package/src/chart/chart.css +1473 -0
  39. package/src/chart/chart.tokens.json +107 -0
  40. package/src/checkbox/checkbox.css +1011 -0
  41. package/src/checkbox/checkbox.tokens.json +102 -0
  42. package/src/checkbox-group/checkbox-group.css +70 -0
  43. package/src/checkbox-group/checkbox-group.tokens.json +6 -0
  44. package/src/code-block/code-block.css +555 -0
  45. package/src/code-block/code-block.tokens.json +69 -0
  46. package/src/collapsible/collapsible.css +546 -0
  47. package/src/collapsible/collapsible.tokens.json +55 -0
  48. package/src/color-picker/color-picker.css +607 -0
  49. package/src/color-picker/color-picker.tokens.json +58 -0
  50. package/src/column-manager/column-manager.css +452 -0
  51. package/src/column-manager/column-manager.tokens.json +43 -0
  52. package/src/combobox/combobox.css +1048 -0
  53. package/src/combobox/combobox.tokens.json +112 -0
  54. package/src/command-palette/command-palette.css +1000 -0
  55. package/src/command-palette/command-palette.tokens.json +75 -0
  56. package/src/container/container.css +198 -0
  57. package/src/container/container.tokens.json +18 -0
  58. package/src/context-menu/context-menu.css +104 -0
  59. package/src/context-menu/context-menu.tokens.json +11 -0
  60. package/src/currency-field/currency-field.css +787 -0
  61. package/src/currency-field/currency-field.tokens.json +80 -0
  62. package/src/dashboard-grid/dashboard-grid.css +748 -0
  63. package/src/dashboard-grid/dashboard-grid.tokens.json +67 -0
  64. package/src/data-grid/data-grid.css +2484 -0
  65. package/src/data-grid/data-grid.tokens.json +100 -0
  66. package/src/data-list/data-list.css +455 -0
  67. package/src/data-list/data-list.tokens.json +35 -0
  68. package/src/date-field/date-field.css +560 -0
  69. package/src/date-field/date-field.tokens.json +80 -0
  70. package/src/date-picker/date-picker.css +420 -0
  71. package/src/date-picker/date-picker.tokens.json +49 -0
  72. package/src/date-range-picker/date-range-picker.css +983 -0
  73. package/src/date-range-picker/date-range-picker.tokens.json +109 -0
  74. package/src/datetime-field/datetime-field.css +850 -0
  75. package/src/datetime-field/datetime-field.tokens.json +91 -0
  76. package/src/datetime-picker/datetime-picker.css +843 -0
  77. package/src/datetime-picker/datetime-picker.tokens.json +78 -0
  78. package/src/datetime-range-picker/datetime-range-picker.css +1375 -0
  79. package/src/datetime-range-picker/datetime-range-picker.tokens.json +135 -0
  80. package/src/description-list/description-list.css +675 -0
  81. package/src/description-list/description-list.tokens.json +66 -0
  82. package/src/detail-panel/detail-panel.css +329 -0
  83. package/src/detail-panel/detail-panel.tokens.json +33 -0
  84. package/src/dialog/dialog.css +968 -0
  85. package/src/dialog/dialog.tokens.json +66 -0
  86. package/src/divider/divider.css +131 -0
  87. package/src/divider/divider.tokens.json +18 -0
  88. package/src/drawer/drawer.css +1303 -0
  89. package/src/drawer/drawer.tokens.json +75 -0
  90. package/src/entity-picker/entity-picker.css +1367 -0
  91. package/src/entity-picker/entity-picker.tokens.json +118 -0
  92. package/src/event-calendar/event-calendar.css +2148 -0
  93. package/src/event-calendar/event-calendar.tokens.json +87 -0
  94. package/src/field/field.css +707 -0
  95. package/src/field/field.tokens.json +58 -0
  96. package/src/field-group/field-group.css +226 -0
  97. package/src/field-group/field-group.tokens.json +33 -0
  98. package/src/filter-bar/filter-bar.css +1306 -0
  99. package/src/filter-bar/filter-bar.tokens.json +78 -0
  100. package/src/form/form.css +218 -0
  101. package/src/form/form.tokens.json +32 -0
  102. package/src/fullscreen/fullscreen.css +376 -0
  103. package/src/fullscreen/fullscreen.tokens.json +50 -0
  104. package/src/grid/grid.css +173 -0
  105. package/src/grid/grid.tokens.json +20 -0
  106. package/src/highlight/highlight.css +135 -0
  107. package/src/highlight/highlight.tokens.json +16 -0
  108. package/src/hover-card/hover-card.css +93 -0
  109. package/src/hover-card/hover-card.tokens.json +17 -0
  110. package/src/icon/icon.css +136 -0
  111. package/src/icon/icon.tokens.json +14 -0
  112. package/src/image/image.css +449 -0
  113. package/src/image/image.tokens.json +27 -0
  114. package/src/import-export-center/import-export-center.css +1175 -0
  115. package/src/import-export-center/import-export-center.tokens.json +84 -0
  116. package/src/inline/inline.css +149 -0
  117. package/src/inline/inline.tokens.json +14 -0
  118. package/src/inline-message/inline-message.css +396 -0
  119. package/src/inline-message/inline-message.tokens.json +19 -0
  120. package/src/kbd/kbd.css +490 -0
  121. package/src/kbd/kbd.tokens.json +40 -0
  122. package/src/link/link.css +237 -0
  123. package/src/link/link.tokens.json +25 -0
  124. package/src/list/list.css +240 -0
  125. package/src/list/list.tokens.json +42 -0
  126. package/src/list-item/list-item.css +937 -0
  127. package/src/list-item/list-item.tokens.json +114 -0
  128. package/src/listbox/listbox.css +674 -0
  129. package/src/listbox/listbox.tokens.json +72 -0
  130. package/src/loading-overlay/loading-overlay.css +730 -0
  131. package/src/loading-overlay/loading-overlay.tokens.json +48 -0
  132. package/src/markdown/markdown.css +168 -0
  133. package/src/markdown/markdown.tokens.json +18 -0
  134. package/src/menu/menu.css +817 -0
  135. package/src/menu/menu.tokens.json +78 -0
  136. package/src/menubar/menubar.css +170 -0
  137. package/src/menubar/menubar.tokens.json +32 -0
  138. package/src/message/message.css +1453 -0
  139. package/src/message/message.tokens.json +85 -0
  140. package/src/message-scroller/message-scroller.css +371 -0
  141. package/src/message-scroller/message-scroller.tokens.json +47 -0
  142. package/src/multi-select/multi-select.css +1427 -0
  143. package/src/multi-select/multi-select.tokens.json +114 -0
  144. package/src/navigation-menu/navigation-menu.css +1029 -0
  145. package/src/navigation-menu/navigation-menu.tokens.json +70 -0
  146. package/src/notification-center/notification-center.css +856 -0
  147. package/src/notification-center/notification-center.tokens.json +84 -0
  148. package/src/number-field/number-field.css +794 -0
  149. package/src/number-field/number-field.tokens.json +80 -0
  150. package/src/otp-input/otp-input.css +525 -0
  151. package/src/otp-input/otp-input.tokens.json +69 -0
  152. package/src/page/page.css +179 -0
  153. package/src/page/page.tokens.json +20 -0
  154. package/src/page-header/page-header.css +1181 -0
  155. package/src/page-header/page-header.tokens.json +71 -0
  156. package/src/pagination/pagination.css +500 -0
  157. package/src/pagination/pagination.tokens.json +56 -0
  158. package/src/popover/popover.css +526 -0
  159. package/src/popover/popover.tokens.json +60 -0
  160. package/src/progress-indicator/progress-indicator.css +1584 -0
  161. package/src/progress-indicator/progress-indicator.tokens.json +50 -0
  162. package/src/prompt-composer/prompt-composer.css +680 -0
  163. package/src/prompt-composer/prompt-composer.tokens.json +99 -0
  164. package/src/prose/prose.css +733 -0
  165. package/src/prose/prose.tokens.json +79 -0
  166. package/src/radio-group/radio-group.css +778 -0
  167. package/src/radio-group/radio-group.tokens.json +103 -0
  168. package/src/rating/rating.css +1071 -0
  169. package/src/rating/rating.tokens.json +88 -0
  170. package/src/result-state/result-state.css +980 -0
  171. package/src/result-state/result-state.tokens.json +63 -0
  172. package/src/runtime-properties.mjs +321 -0
  173. package/src/saved-views/saved-views.css +394 -0
  174. package/src/saved-views/saved-views.tokens.json +41 -0
  175. package/src/scroll-area/scroll-area.css +481 -0
  176. package/src/scroll-area/scroll-area.tokens.json +15 -0
  177. package/src/section/section.css +177 -0
  178. package/src/section/section.tokens.json +39 -0
  179. package/src/segmented-control/segmented-control.css +564 -0
  180. package/src/segmented-control/segmented-control.tokens.json +67 -0
  181. package/src/select/select.css +1593 -0
  182. package/src/select/select.tokens.json +110 -0
  183. package/src/side-navigation/side-navigation.css +1096 -0
  184. package/src/side-navigation/side-navigation.tokens.json +87 -0
  185. package/src/skeleton/skeleton.css +431 -0
  186. package/src/skeleton/skeleton.tokens.json +29 -0
  187. package/src/slider/slider.css +792 -0
  188. package/src/slider/slider.tokens.json +75 -0
  189. package/src/sparkline/sparkline.css +282 -0
  190. package/src/sparkline/sparkline.tokens.json +45 -0
  191. package/src/spinner/spinner.css +224 -0
  192. package/src/spinner/spinner.tokens.json +8 -0
  193. package/src/split-button/split-button.css +253 -0
  194. package/src/split-button/split-button.tokens.json +12 -0
  195. package/src/splitter/splitter.css +336 -0
  196. package/src/splitter/splitter.tokens.json +24 -0
  197. package/src/stack/stack.css +128 -0
  198. package/src/stack/stack.tokens.json +14 -0
  199. package/src/stat-card/stat-card.css +641 -0
  200. package/src/stat-card/stat-card.tokens.json +95 -0
  201. package/src/status-indicator/status-indicator.css +481 -0
  202. package/src/status-indicator/status-indicator.tokens.json +38 -0
  203. package/src/stepper/stepper.css +629 -0
  204. package/src/stepper/stepper.tokens.json +72 -0
  205. package/src/switch/switch.css +703 -0
  206. package/src/switch/switch.tokens.json +75 -0
  207. package/src/table/table.css +1482 -0
  208. package/src/table/table.tokens.json +69 -0
  209. package/src/table-of-contents/table-of-contents.css +533 -0
  210. package/src/table-of-contents/table-of-contents.tokens.json +53 -0
  211. package/src/tabs/tabs.css +998 -0
  212. package/src/tabs/tabs.tokens.json +82 -0
  213. package/src/tag/tag.css +768 -0
  214. package/src/tag/tag.tokens.json +85 -0
  215. package/src/tags-input/tags-input.css +757 -0
  216. package/src/tags-input/tags-input.tokens.json +84 -0
  217. package/src/text-field/text-field.css +900 -0
  218. package/src/text-field/text-field.tokens.json +87 -0
  219. package/src/textarea/textarea.css +365 -0
  220. package/src/textarea/textarea.tokens.json +59 -0
  221. package/src/time-field/time-field.css +719 -0
  222. package/src/time-field/time-field.tokens.json +86 -0
  223. package/src/time-picker/time-picker.css +665 -0
  224. package/src/time-picker/time-picker.tokens.json +66 -0
  225. package/src/time-range-picker/time-range-picker.css +1287 -0
  226. package/src/time-range-picker/time-range-picker.tokens.json +134 -0
  227. package/src/timeline/timeline.css +1596 -0
  228. package/src/timeline/timeline.tokens.json +96 -0
  229. package/src/toast/toast.css +943 -0
  230. package/src/toast/toast.tokens.json +90 -0
  231. package/src/toggle/toggle.css +290 -0
  232. package/src/toggle/toggle.tokens.json +54 -0
  233. package/src/toggle-group/toggle-group.css +463 -0
  234. package/src/toggle-group/toggle-group.tokens.json +54 -0
  235. package/src/toolbar/toolbar.css +434 -0
  236. package/src/toolbar/toolbar.tokens.json +49 -0
  237. package/src/tooltip/tooltip.css +368 -0
  238. package/src/tooltip/tooltip.tokens.json +39 -0
  239. package/src/top-navigation/top-navigation.css +1287 -0
  240. package/src/top-navigation/top-navigation.tokens.json +91 -0
  241. package/src/tour/tour.css +680 -0
  242. package/src/tour/tour.tokens.json +67 -0
  243. package/src/transfer/transfer.css +571 -0
  244. package/src/transfer/transfer.tokens.json +49 -0
  245. package/src/tree/tree.css +1000 -0
  246. package/src/tree/tree.tokens.json +80 -0
  247. package/src/typography/typography.css +211 -0
  248. package/src/typography/typography.tokens.json +31 -0
  249. package/src/upload/upload.css +1706 -0
  250. package/src/upload/upload.tokens.json +123 -0
  251. package/src/visually-hidden/visually-hidden.css +52 -0
  252. package/src/visually-hidden/visually-hidden.tokens.json +1 -0
  253. package/src/wizard/wizard.css +740 -0
  254. package/src/wizard/wizard.tokens.json +63 -0
@@ -0,0 +1,629 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * Where the reader is in a sequence of steps, which steps they may reach,
4
+ * and the panel belonging to the step they are on.
5
+ *
6
+ * The whole family is drawn from three measurements and one ratio: the
7
+ * marker is a circle sized from the control scale, the connector is a rule
8
+ * one border width thick, and the gap between a marker and its label is the
9
+ * control gap. Everything else — where the connector starts, how far the
10
+ * column indents, where the label sits — is derived from those, so a theme
11
+ * that retunes the control scale moves the whole stepper together instead of
12
+ * leaving the connector behind.
13
+ */
14
+ [data-ui='stepper'] {
15
+ --_marker: var(--slotted-stepper-marker-size, var(--slotted-control-height-md, 34px));
16
+ --_gap: var(--slotted-stepper-gap, var(--slotted-control-gap-md, 8px));
17
+ --_rule: var(--slotted-stepper-connector-thickness, var(--slotted-border-width-thick, 2px));
18
+ --_muted: var(--slotted-stepper-color-muted, var(--slotted-text-muted, GrayText));
19
+ --_strong: var(--slotted-stepper-color, var(--slotted-text, CanvasText));
20
+ --_pending-line: var(--slotted-stepper-connector-color, var(--slotted-border-subtle, GrayText));
21
+ /**
22
+ * The ring of a step the reader has not reached. It is a step above the
23
+ * connector, and deliberately: the track behind a flow is decoration and
24
+ * may be faint, while the ring is the frame of the marker itself and holds
25
+ * the 3:1 every non-text element needs. `--slotted-border-subtle` reads at
26
+ * about 1.2:1 against the surface, and the four pending markers in a
27
+ * six-step row all but disappeared.
28
+ */
29
+ --_pending-ring: var(
30
+ --slotted-stepper-marker-border,
31
+ var(--slotted-control-border-color, ButtonBorder)
32
+ );
33
+ --_done-line: var(
34
+ --slotted-stepper-connector-color-complete,
35
+ var(--slotted-tone-accent-solid, Highlight)
36
+ );
37
+
38
+ /**
39
+ * The wash a press puts over the marker: the family's own strong ink at a
40
+ * low strength, over whatever ground the status gave the marker. It is the
41
+ * state layer `alert`, `toast` and `tag` answer a press with, at the same
42
+ * strength, and a theme retunes it by strength — which is what the
43
+ * component token is for.
44
+ *
45
+ * The ink is stated rather than taken from `currentcolor`, which is what
46
+ * those three take: a complete marker and an invalid one draw their number
47
+ * in `transparent`, because the check and the alert are painted over it, so
48
+ * a wash of `currentcolor` there would be a wash of nothing. The strong ink
49
+ * darkens a filled marker and greys an empty one, and it is near-white in
50
+ * the dark scheme, where it lightens both.
51
+ */
52
+ --_state-press: color-mix(
53
+ in oklab,
54
+ var(--_strong) var(--slotted-stepper-marker-press-strength, 14%),
55
+ transparent
56
+ );
57
+
58
+ color: var(--_strong);
59
+ container-name: slotted-stepper;
60
+ container-type: inline-size;
61
+ display: block;
62
+ font-family: var(--slotted-stepper-font-family, var(--slotted-font-family-sans, inherit));
63
+ font-size: var(--slotted-stepper-font-size, var(--slotted-control-font-size-md, 13px));
64
+ }
65
+
66
+ /* ── The row, and the column ────────────────────────────────────────────
67
+ *
68
+ * Horizontal is a row of equal columns, so five steps divide the width
69
+ * evenly however long their labels are; a row of intrinsic widths would give
70
+ * "Review" a quarter of the space it gives "Shipping and billing address"
71
+ * and the markers would stop lining up with anything.
72
+ *
73
+ * Vertical is a column, and the connector runs down the marker's own centre
74
+ * line rather than beside it.
75
+ */
76
+
77
+ [data-ui='stepper'] [data-part='list'] {
78
+ display: flex;
79
+ list-style: none;
80
+ margin: 0;
81
+ padding: 0;
82
+ }
83
+
84
+ [data-ui='stepper'][data-orientation='horizontal'] [data-part='list'] {
85
+ align-items: flex-start;
86
+ flex-direction: row;
87
+ }
88
+
89
+ [data-ui='stepper'][data-orientation='vertical'] [data-part='list'] {
90
+ flex-direction: column;
91
+ }
92
+
93
+ [data-ui='stepper'] [data-part='item'] {
94
+ display: flex;
95
+ position: relative;
96
+ }
97
+
98
+ [data-ui='stepper'][data-orientation='horizontal'] [data-part='item'] {
99
+ flex: 1 1 0;
100
+ /* A label longer than its column wraps instead of widening the column. */
101
+ min-inline-size: 0;
102
+ }
103
+
104
+ [data-ui='stepper'][data-orientation='vertical'] [data-part='item'] {
105
+ flex-direction: column;
106
+ }
107
+
108
+ /* ── The header ─────────────────────────────────────────────────────────
109
+ *
110
+ * A `button`, an `a` or a `span`, depending on what the flow lets the reader
111
+ * do. All three are painted the same, because what changes between them is
112
+ * whether the step can be reached, not what a step looks like — and the
113
+ * `span` is the read-only progress indicator the field ships as a separate
114
+ * component.
115
+ */
116
+
117
+ [data-ui='stepper'] [data-part='trigger'] {
118
+ align-items: center;
119
+ appearance: none;
120
+ background: none;
121
+ border: 0;
122
+ border-radius: var(--slotted-stepper-radius, var(--slotted-control-radius, 4px));
123
+ color: inherit;
124
+ column-gap: var(--_gap);
125
+ display: flex;
126
+ font: inherit;
127
+ padding: 0;
128
+ text-align: start;
129
+ text-decoration: none;
130
+ transition: color var(--slotted-control-transition-duration)
131
+ var(--slotted-control-transition-easing);
132
+ }
133
+
134
+ [data-ui='stepper'] button[data-part='trigger'],
135
+ [data-ui='stepper'] a[data-part='trigger'] {
136
+ cursor: pointer;
137
+ }
138
+
139
+ /**
140
+ * `end` puts the label beside the marker and `bottom` puts it under, which
141
+ * is what a row of five steps needs once the labels are longer than a word.
142
+ * The stack is centred so the marker sits over the middle of its own label
143
+ * rather than over the middle of the column.
144
+ */
145
+ [data-ui='stepper'][data-label-placement='bottom'] [data-part='trigger'] {
146
+ align-items: center;
147
+ flex-direction: column;
148
+ /**
149
+ * The label fills its column, so two long names in adjacent columns meet
150
+ * with nothing between them. The inset is on the header rather than on the
151
+ * item, because the connector is measured from the item's own edges and
152
+ * padding there would shorten every track by twice this.
153
+ */
154
+ padding-inline: var(--slotted-stepper-column-inset, var(--slotted-space-3, 0.375rem));
155
+ row-gap: var(--slotted-stepper-label-gap, var(--slotted-space-3, 0.375rem));
156
+ text-align: center;
157
+ }
158
+
159
+ [data-ui='stepper'] [data-part='trigger']:focus-visible {
160
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
161
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
162
+ }
163
+
164
+ /* ── The marker ─────────────────────────────────────────────────────────
165
+ *
166
+ * A circle holding the step's number, and the one part that never wraps,
167
+ * never shrinks and never moves. Its four appearances are the four statuses,
168
+ * and each of them is a fill and an edge rather than a colour alone: a
169
+ * pending step is an outline, the current one is a filled ring, a complete
170
+ * one is a solid disc with a check, and a step in error is a solid disc with
171
+ * an alert. `docs/component-features.md` section 7 requires exactly this —
172
+ * progress that does not depend on colour.
173
+ */
174
+
175
+ [data-ui='stepper'] [data-part='marker'] {
176
+ /**
177
+ * The colour of the glyph drawn over the number, held on the marker rather
178
+ * than stated on the glyph's box. Reading it through one custom property
179
+ * keeps the family's system-colour last resort on the element where the
180
+ * theme's own tokens live, and lets the invalid step restate it once.
181
+ */
182
+ --_mark: var(
183
+ --slotted-stepper-marker-color-complete,
184
+ var(--slotted-tone-accent-on-solid, HighlightText)
185
+ );
186
+ --_mark-size: var(--slotted-stepper-glyph-size, var(--slotted-control-icon-size-md, 16px));
187
+
188
+ align-items: center;
189
+ background-color: var(--slotted-stepper-marker-surface, transparent);
190
+ block-size: var(--_marker);
191
+ border: var(--_rule) solid var(--_pending-ring);
192
+ border-radius: var(--slotted-radius-full, 9999px);
193
+ /**
194
+ * The marker measures `--_marker` including its ring, because every other
195
+ * rule in this sheet is written as though it does: the connector's centre,
196
+ * the panel's indent and the vertical track all read that one length. With
197
+ * the ring outside it the circle stood four pixels wider than the number
198
+ * the rest of the family was using, and the connector ran two pixels off
199
+ * every marker centre it was supposed to be on — in both orientations and
200
+ * at all three densities (ST2).
201
+ */
202
+ box-sizing: border-box;
203
+ color: var(--_muted);
204
+ display: flex;
205
+ flex: none;
206
+ font-variant-numeric: tabular-nums;
207
+ font-weight: var(--slotted-stepper-marker-weight, var(--slotted-font-weight-semibold, 600));
208
+ inline-size: var(--_marker);
209
+ justify-content: center;
210
+ line-height: 1;
211
+ /* The check and the alert are drawn over the number, not beside it. */
212
+ position: relative;
213
+ transition:
214
+ background-color var(--slotted-control-transition-duration)
215
+ var(--slotted-control-transition-easing),
216
+ border-color var(--slotted-control-transition-duration)
217
+ var(--slotted-control-transition-easing),
218
+ box-shadow var(--slotted-control-transition-duration) var(--slotted-control-transition-easing),
219
+ color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
220
+ }
221
+
222
+ /**
223
+ * The step the reader is on. The ring thickens to the accent and the number
224
+ * takes the accent's text colour: it is where they are, not where they have
225
+ * been, so it stays an outline and does not fill.
226
+ */
227
+ [data-ui='stepper'] [data-current] [data-part='marker'] {
228
+ border-color: var(--slotted-stepper-marker-border-current, var(--_done-line));
229
+ color: var(--slotted-stepper-marker-color-current, var(--slotted-tone-accent-text, Highlight));
230
+ }
231
+
232
+ /**
233
+ * A step that is finished. The disc fills and the number gives way to a
234
+ * check, because a reader scanning the row counts filled discs rather than
235
+ * reading five numbers.
236
+ */
237
+ [data-ui='stepper'] [data-complete]:not([data-current], [data-invalid]) [data-part='marker'] {
238
+ background-color: var(--slotted-stepper-marker-surface-complete, var(--_done-line));
239
+ border-color: var(--slotted-stepper-marker-surface-complete, var(--_done-line));
240
+ }
241
+
242
+ [data-ui='stepper'] [data-invalid] [data-part='marker'] {
243
+ --_mark: var(
244
+ --slotted-stepper-marker-color-invalid,
245
+ var(--slotted-tone-danger-on-solid, MarkText)
246
+ );
247
+
248
+ background-color: var(
249
+ --slotted-stepper-marker-surface-invalid,
250
+ var(--slotted-tone-danger-solid, Mark)
251
+ );
252
+ border-color: var(
253
+ --slotted-stepper-marker-surface-invalid,
254
+ var(--slotted-tone-danger-solid, Mark)
255
+ );
256
+ }
257
+
258
+ [data-ui='stepper'] [data-disabled]:not([data-invalid]) [data-part='marker'] {
259
+ background-color: transparent;
260
+ border-color: var(--slotted-disabled-border, GrayText);
261
+ color: var(--slotted-disabled-foreground, GrayText);
262
+ }
263
+
264
+ /**
265
+ * The glyph a finished or failed step shows in place of its number. It is
266
+ * the Glyph element the binding renders in the marker, chosen from the
267
+ * step's state, and laid over the number the binding leaves in the DOM. The
268
+ * number stays there because a reader enlarging the page to four hundred per
269
+ * cent still needs to know which step this is, and because the accessible
270
+ * name is built from the `status` part rather than from what is painted
271
+ * here.
272
+ *
273
+ * A failed step shows a bare cross rather than the scale's circled alert.
274
+ * The status glyphs carry their own container, and `docs/token-foundation.md`
275
+ * says why: the bare marks are the ones drawn inside a box some control
276
+ * already provides. The marker is that box, and a circle inside a disc reads
277
+ * as a ring inside a ring rather than as a failure.
278
+ */
279
+ /**
280
+ * The number gives way to the mark. Neither the complete rule nor the
281
+ * invalid one paints the number any more, and that is the fix rather than
282
+ * the tidying: both used to set a colour for it, both outranked this rule on
283
+ * specificity, and a finished step drew its number and its check on top of
284
+ * each other. The capture is what said so — the two marks overlap into a
285
+ * shape that is neither.
286
+ */
287
+ [data-ui='stepper'] :is([data-complete], [data-invalid]) [data-part='marker'] {
288
+ color: transparent;
289
+ }
290
+
291
+ [data-ui='stepper'] [data-part='marker'] > [data-ui='icon'] {
292
+ --slotted-icon-size: var(--_mark-size);
293
+
294
+ color: var(--_mark);
295
+ /**
296
+ * Centred by its own box rather than by the flex container's alignment.
297
+ * An absolutely positioned child takes a static position the engines do
298
+ * not agree on inside a flex container, and the capture showed the result:
299
+ * the check drawn from the marker's top corner, with half of it outside
300
+ * the disc. `inset` plus automatic margins centres a fixed-size box in
301
+ * every engine.
302
+ */
303
+ inset: 0;
304
+ margin: auto;
305
+ position: absolute;
306
+ }
307
+
308
+ /**
309
+ * The current step keeps its number even where the consumer also marked it
310
+ * complete, because the number is what says where the reader is in a
311
+ * sequence and a check would say they had left it.
312
+ */
313
+ [data-ui='stepper'] [data-current]:not([data-invalid]) [data-part='marker'] {
314
+ color: var(--slotted-stepper-marker-color-current, var(--slotted-tone-accent-text, Highlight));
315
+ }
316
+
317
+ /* ── The label and its second line ──────────────────────────────────────
318
+ *
319
+ * The label wraps; the marker does not. A step whose name is a forty-letter
320
+ * compound takes two lines of its own column and leaves every other step
321
+ * where it was.
322
+ */
323
+
324
+ [data-ui='stepper'] [data-part='label'] {
325
+ color: var(--_muted);
326
+ font-weight: var(--slotted-stepper-label-weight, var(--slotted-font-weight-medium, 500));
327
+ line-height: var(--slotted-stepper-line-height, var(--slotted-line-height-sm, 1.45));
328
+ min-inline-size: 0;
329
+ overflow-wrap: anywhere;
330
+ }
331
+
332
+ [data-ui='stepper'] :is([data-current], [data-complete]) [data-part='label'] {
333
+ color: var(--_strong);
334
+ }
335
+
336
+ [data-ui='stepper'] [data-invalid] [data-part='label'] {
337
+ color: var(--slotted-stepper-label-color-invalid, var(--slotted-tone-danger-text, MarkText));
338
+ }
339
+
340
+ [data-ui='stepper'] [data-disabled]:not([data-invalid]) [data-part='label'] {
341
+ color: var(--slotted-disabled-foreground, GrayText);
342
+ }
343
+
344
+ [data-ui='stepper'] [data-part='description'] {
345
+ color: var(--_muted);
346
+ display: block;
347
+ font-size: var(--slotted-stepper-description-font-size, var(--slotted-font-size-xs, 0.75rem));
348
+ line-height: var(--slotted-stepper-line-height, var(--slotted-line-height-sm, 1.45));
349
+ margin-block-start: var(--slotted-stepper-description-gap, var(--slotted-space-1, 0.125rem));
350
+ }
351
+
352
+ /**
353
+ * A step whose header can be pressed answers the pointer, and it answers it
354
+ * on the label rather than on the whole column: the column is mostly empty
355
+ * space, and a fill across it would read as a selected row.
356
+ */
357
+ [data-ui='stepper']
358
+ [data-part='item']:not([data-disabled], [data-loading])
359
+ :is(button, a)[data-part='trigger']:hover
360
+ [data-part='label'] {
361
+ color: var(--_strong);
362
+ text-decoration-color: currentColor;
363
+ text-decoration-line: underline;
364
+ text-underline-offset: var(--slotted-stepper-underline-offset, 0.2em);
365
+ }
366
+
367
+ /**
368
+ * The press is said on the marker's own ground rather than by shrinking it.
369
+ * The marker grew smaller by six per cent for one iteration, and R7 refuses
370
+ * it: the marker carries the step's number, and a box of type drawn at
371
+ * ninety-four per cent resamples the number for the length of the press.
372
+ *
373
+ * A wash of the marker's own ink over whatever ground it has is what says
374
+ * *taken* instead — the state layer `alert`, `toast` and `tag` already
375
+ * answer a press with, at the same strength. It is written as an inset
376
+ * shadow rather than as a background because the ground underneath is the
377
+ * status: a complete marker is filled with the accent, an invalid one with
378
+ * the danger tone, and a press that replaced either would be a press that
379
+ * also changed what the step is.
380
+ */
381
+ [data-ui='stepper']
382
+ [data-part='item']:not([data-disabled], [data-loading])
383
+ :is(button, a)[data-part='trigger']:active
384
+ [data-part='marker'] {
385
+ box-shadow: inset 0 0 0 var(--_marker) var(--_state-press);
386
+ }
387
+
388
+ /* ── The connector ──────────────────────────────────────────────────────
389
+ *
390
+ * The rule between two markers, and the only part that shows how far the
391
+ * flow has come without reading a word. It is painted up to the step the
392
+ * reader has reached, so the row reads as a filled track rather than as five
393
+ * separate marks.
394
+ *
395
+ * Horizontally it runs across the marker's own centre line, which is half a
396
+ * marker below the top of the item; vertically it runs down the marker's
397
+ * centre, which is half a marker in from the item's start edge. Both are
398
+ * derived from the marker rather than stated, so the rule stays on the
399
+ * centre at every density.
400
+ */
401
+
402
+ [data-ui='stepper'] [data-part='separator'] {
403
+ background-color: var(--_pending-line);
404
+ display: block;
405
+ flex: none;
406
+ }
407
+
408
+ /**
409
+ * The connector fills for a step the reader has walked past, which is
410
+ * distance travelled rather than work completed — the same measure
411
+ * `stepPercent` reports. The two facts are deliberately on different
412
+ * elements: `data-complete` on an item is the consumer's claim that the work
413
+ * is done, and `data-complete` on a connector is the family's own arithmetic
414
+ * about where the reader has been. A track that filled only where the
415
+ * consumer marked completion would stay grey through every flow that never
416
+ * claims it.
417
+ */
418
+ [data-ui='stepper'] [data-part='separator'][data-complete] {
419
+ background-color: var(--_done-line);
420
+ }
421
+
422
+ /**
423
+ * With the label beside the marker, the connector is a flex child that takes
424
+ * whatever the label leaves. It was an absolutely positioned stub at the
425
+ * item's trailing edge until the capture showed what that produces: a dash
426
+ * touching the next marker rather than a track between two of them. Nothing
427
+ * knows how wide a label is, so nothing can position around it — but a flex
428
+ * item can be told to take the rest.
429
+ */
430
+ [data-ui='stepper'][data-orientation='horizontal'][data-label-placement='end']
431
+ [data-part='separator'] {
432
+ align-self: center;
433
+ block-size: var(--_rule);
434
+ flex: 1 1 auto;
435
+ margin-inline: var(--slotted-stepper-track-gap, var(--slotted-space-5, 0.75rem));
436
+ min-inline-size: var(--slotted-stepper-track-min, var(--slotted-space-8, 1.5rem));
437
+ position: static;
438
+ }
439
+
440
+ [data-ui='stepper'][data-orientation='horizontal'][data-label-placement='end']
441
+ [data-part='trigger'] {
442
+ flex: 0 1 auto;
443
+ min-inline-size: 0;
444
+ }
445
+
446
+ /**
447
+ * With the label under the marker, the connector runs between two marker
448
+ * centres. The columns are equal, so the next centre is exactly one column
449
+ * away, and both ends are derived from the marker rather than stated.
450
+ */
451
+ [data-ui='stepper'][data-orientation='horizontal'][data-label-placement='bottom']
452
+ [data-part='separator'] {
453
+ block-size: var(--_rule);
454
+ inset-block-start: calc(0.5 * (var(--_marker) - var(--_rule)));
455
+ inset-inline-end: calc(-50% + 0.5 * var(--_marker) + var(--_gap));
456
+ inset-inline-start: calc(50% + 0.5 * var(--_marker) + var(--_gap));
457
+ position: absolute;
458
+ }
459
+
460
+ /**
461
+ * Down the marker's own centre line, from below this marker to above the
462
+ * next one, with the same room at both ends. The bottom of the item is where
463
+ * the next marker begins, so the end inset is that room and not zero: at
464
+ * zero the rule stopped short of the marker above and ran into the marker
465
+ * below, which read as misaligned in every vertical flow.
466
+ *
467
+ * The room is its own length rather than `--_gap`, the space between a
468
+ * marker and its label. A one-line step is its header plus the step gap
469
+ * tall, and `--_gap` at both ends of a step gap of one rem left a rule of
470
+ * no length at all; a quarter rem leaves half the step gap drawn.
471
+ */
472
+ [data-ui='stepper'][data-orientation='vertical'] [data-part='separator'] {
473
+ --_rule-room: var(--slotted-stepper-connector-gap, var(--slotted-space-2, 0.25rem));
474
+
475
+ inline-size: var(--_rule);
476
+ inset-block-end: var(--_rule-room);
477
+ inset-block-start: calc(var(--_marker) + var(--_rule-room));
478
+ inset-inline-start: calc(0.5 * (var(--_marker) - var(--_rule)));
479
+ position: absolute;
480
+ }
481
+
482
+ /**
483
+ * The last step draws no connector, because there is nothing after it. The
484
+ * binding does not render the element at all; this is what a consumer who
485
+ * renders one anyway gets, and it is nothing.
486
+ */
487
+ [data-ui='stepper'] [data-part='item']:last-child [data-part='separator'] {
488
+ display: none;
489
+ }
490
+
491
+ /* ── Horizontal geometry ────────────────────────────────────────────────
492
+ *
493
+ * With the label under the marker the header fills its column, so the marker
494
+ * centres over the column and the connector runs between two centres.
495
+ */
496
+
497
+ [data-ui='stepper'][data-orientation='horizontal'][data-label-placement='bottom']
498
+ [data-part='trigger'] {
499
+ inline-size: 100%;
500
+ }
501
+
502
+ /* ── Vertical geometry ──────────────────────────────────────────────────
503
+ *
504
+ * The panel is indented to the label's own start edge, so the content of a
505
+ * step lines up with its name rather than with its number.
506
+ */
507
+
508
+ [data-ui='stepper'][data-orientation='vertical'] [data-part='item'] {
509
+ padding-block-end: var(--slotted-stepper-step-gap, var(--slotted-space-6, 1rem));
510
+ }
511
+
512
+ [data-ui='stepper'][data-orientation='vertical'] [data-part='item']:last-child {
513
+ padding-block-end: 0;
514
+ }
515
+
516
+ [data-ui='stepper'][data-orientation='vertical'] [data-part='panel'] {
517
+ margin-inline-start: calc(var(--_marker) + var(--_gap));
518
+ padding-block-start: var(--slotted-stepper-panel-gap, var(--slotted-space-4, 0.5rem));
519
+ }
520
+
521
+ [data-ui='stepper'][data-orientation='horizontal'] [data-part='panel'] {
522
+ padding-block-start: var(--slotted-stepper-panel-gap, var(--slotted-space-6, 1rem));
523
+ }
524
+
525
+ [data-ui='stepper'] [data-part='panel']:focus-visible {
526
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
527
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
528
+ }
529
+
530
+ /* ── Reflow ─────────────────────────────────────────────────────────────
531
+ *
532
+ * Five labels in a row at 320 pixels are five columns two characters wide.
533
+ * Below the breakpoint a horizontal stepper becomes a column, which is the
534
+ * composition change section 2.7 of `docs/component-features.md` asks for
535
+ * rather than a smaller version of the same row. A stepper the consumer set
536
+ * to vertical is already one and is left alone.
537
+ *
538
+ * The breakpoint is a literal because `@container (min-width: var(--x))` is
539
+ * invalid CSS, which rule 4 of `docs/token-foundation.md` states.
540
+ */
541
+
542
+ @container slotted-stepper (max-width: 30rem) {
543
+ [data-ui='stepper'][data-orientation='horizontal'] [data-part='list'] {
544
+ align-items: stretch;
545
+ flex-direction: column;
546
+ }
547
+
548
+ [data-ui='stepper'][data-orientation='horizontal'] [data-part='item'] {
549
+ flex: none;
550
+ flex-direction: column;
551
+ padding-block-end: var(--slotted-stepper-step-gap, var(--slotted-space-6, 1rem));
552
+ padding-inline-end: 0;
553
+ }
554
+
555
+ [data-ui='stepper'][data-orientation='horizontal'] [data-part='item']:last-child {
556
+ padding-block-end: 0;
557
+ }
558
+
559
+ [data-ui='stepper'][data-orientation='horizontal'][data-label-placement] [data-part='trigger'] {
560
+ align-items: center;
561
+ flex-direction: row;
562
+ inline-size: auto;
563
+ /**
564
+ * The column inset goes with the columns. It exists so two long names in
565
+ * adjacent columns do not meet, and a stepper that has turned into a
566
+ * column has no neighbour to keep away from — while the connector below
567
+ * is measured from the item's own edge, so six pixels of padding on the
568
+ * header moved the marker off the track and left the two joined by
569
+ * nothing (ST2).
570
+ */
571
+ padding-inline: 0;
572
+ text-align: start;
573
+ }
574
+
575
+ /**
576
+ * `[data-label-placement]` is here for specificity, not for selection: the
577
+ * two rules this one replaces name the placement, and a container query
578
+ * adds no weight of its own. Without it the row's own connector geometry
579
+ * survived the reflow and the column drew four-pixel dots down its side.
580
+ */
581
+ [data-ui='stepper'][data-orientation='horizontal'][data-label-placement]
582
+ [data-part='separator'] {
583
+ block-size: auto;
584
+ flex: none;
585
+ inline-size: var(--_rule);
586
+ inset-block-end: 0;
587
+ inset-block-start: calc(var(--_marker) + var(--_gap));
588
+ inset-inline-end: auto;
589
+ inset-inline-start: calc(0.5 * (var(--_marker) - var(--_rule)));
590
+ margin-inline: 0;
591
+ min-inline-size: 0;
592
+ position: absolute;
593
+ }
594
+
595
+ [data-ui='stepper'][data-orientation='horizontal'][data-label-placement] [data-part='panel'] {
596
+ margin-inline-start: calc(var(--_marker) + var(--_gap));
597
+ padding-block-start: var(--slotted-stepper-panel-gap, var(--slotted-space-4, 0.5rem));
598
+ }
599
+ }
600
+
601
+ /* ── Forced colours ─────────────────────────────────────────────────────
602
+ *
603
+ * The system replaces every painted surface with the page's own background,
604
+ * which would flatten the four statuses into one outline. Three things need
605
+ * restating: the connector, which is a painted rule; the fill that separates
606
+ * a finished step from a pending one; and the glyph inside it, which keeps
607
+ * its paint through the marker's own `forced-color-adjust` rather than
608
+ * through a system colour this family would have to choose.
609
+ */
610
+
611
+ @media (forced-colors: active) {
612
+ [data-ui='stepper'] [data-part='separator'] {
613
+ background-color: GrayText;
614
+ }
615
+
616
+ [data-ui='stepper'] [data-part='separator'][data-complete] {
617
+ background-color: Highlight;
618
+ }
619
+
620
+ [data-ui='stepper']
621
+ :is([data-complete], [data-invalid]):not([data-current])
622
+ [data-part='marker'] {
623
+ background-color: Highlight;
624
+ border-color: Highlight;
625
+ color: HighlightText;
626
+ forced-color-adjust: none;
627
+ }
628
+ }
629
+ }