@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,740 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * A flow of steps that accumulates answers. The progress is `stepper`'s,
4
+ * each step's body is `form`'s, the actions are `button`'s, the error is
5
+ * `alert`'s, the optional mark is `tag`'s and the restore wait is
6
+ * `skeleton`'s. What this stylesheet draws is the two columns, the step's
7
+ * heading with its position, the row of actions and its two groups, the
8
+ * compact progress bar and its disclosure, and the pinned footer under
9
+ * `scroll=self`.
10
+ *
11
+ * root (container slotted-wizard)
12
+ * └ layout ▸ ┌ progress ─────┐ ┌ main ─────────────────────────────┐
13
+ * │ toggle (<600) │ │ error ▸ alert │
14
+ * │ stepper │ │ step ▸ step-header ▸ step-title │
15
+ * │ │ │ form (the form family) │
16
+ * │ │ ├────────────────────────────────────┤
17
+ * │ │ │ actions ▸ start … end │
18
+ * └───────────────┘ └────────────────────────────────────┘
19
+ *
20
+ * The root is the query container and the grid is one element in, so the
21
+ * query can change the grid's tracks (`docs/build-briefing.md`, _Decisions
22
+ * already taken_). Every part is reached from the root with child
23
+ * combinators: the content is other families, and a descendant rule would
24
+ * restyle a `form`'s actions or an `alert`'s title.
25
+ */
26
+ [data-ui='wizard'] {
27
+ --_text: var(--slotted-text, CanvasText);
28
+ --_muted: var(--slotted-text-muted, GrayText);
29
+ --_rule: var(--slotted-wizard-border, var(--slotted-border-subtle, ButtonBorder));
30
+ --_rule-size: var(--slotted-border-width-thin, 1px);
31
+ /**
32
+ * The column the vertical progress takes. Fourteen rem holds a marker, its
33
+ * gap and a two-word label at the default type size without a break; a
34
+ * longer label wraps inside it. The contract records the literal.
35
+ */
36
+ --_progress-size: var(--slotted-wizard-progress-inline-size, 14rem);
37
+ /** Between the progress and the step, in either arrangement. */
38
+ --_gap: var(--slotted-wizard-gap, var(--slotted-space-9, 2rem));
39
+ /** Between the error, the step and the actions. */
40
+ --_rhythm: var(--slotted-wizard-rhythm, var(--slotted-space-8, 1.5rem));
41
+ /** Between the step's heading and its first field. */
42
+ --_header-gap: var(--slotted-wizard-header-gap, var(--slotted-space-6, 1rem));
43
+ /** Between two buttons of one group, the gap a control row keeps. */
44
+ --_action-gap: var(--slotted-control-gap-md, var(--slotted-space-3, 0.375rem));
45
+ /**
46
+ * The ground the pinned footer paints under `scroll=self`, so what scrolls
47
+ * under it is covered. Inside a page it is the page's own; outside, the
48
+ * surface.
49
+ */
50
+ --_ground: var(--slotted-page-ground, var(--slotted-surface, Canvas));
51
+ /**
52
+ * How far a focus ring stands outside the control it rings: its width and
53
+ * its offset. A region that scrolls clips at its own edge, so under
54
+ * `scroll=self` each scrolling region pads its content by this much, and
55
+ * the error and the actions take the same inset so the three still share
56
+ * one column. The inset stays inside the wizard's own box: a region that
57
+ * reached past it with a negative margin was clipped by the layer around
58
+ * the wizard instead.
59
+ */
60
+ --_ring-room: calc(
61
+ var(--slotted-focus-ring-width, 2px) + var(--slotted-focus-ring-offset, 2px)
62
+ );
63
+
64
+ color: var(--_text);
65
+ container-name: slotted-wizard;
66
+ container-type: inline-size;
67
+ display: flex;
68
+ flex-direction: column;
69
+ font-family: var(--slotted-font-family-sans, ui-sans-serif, system-ui, sans-serif);
70
+ min-inline-size: 0;
71
+ }
72
+
73
+ /* ── The two columns ──────────────────────────────────────────────────── */
74
+
75
+ [data-ui='wizard'] > [data-part='layout'] {
76
+ display: grid;
77
+ gap: var(--_gap);
78
+ grid-template-columns: minmax(0, 1fr);
79
+ min-inline-size: 0;
80
+ }
81
+
82
+ /**
83
+ * Beside the step, the progress is a column of the declared width and the
84
+ * step takes the rest. `align-items: start` keeps a short progress from
85
+ * stretching to the step's height, which the sticky rule below needs.
86
+ */
87
+ [data-ui='wizard'][data-progress='start'] > [data-part='layout'] {
88
+ align-items: start;
89
+ grid-template-columns: var(--_progress-size) minmax(0, 1fr);
90
+ }
91
+
92
+ [data-ui='wizard'][data-progress='none'] > [data-part='layout'] > [data-part='progress'] {
93
+ display: none;
94
+ }
95
+
96
+ [data-ui='wizard'] > [data-part='layout'] > [data-part='progress'] {
97
+ display: flex;
98
+ flex-direction: column;
99
+ gap: var(--slotted-space-4, 0.5rem);
100
+ min-inline-size: 0;
101
+ }
102
+
103
+ /**
104
+ * On a page that scrolls, the column stays in view while a long step
105
+ * scrolls past it, under whatever chrome the page publishes (the briefing's
106
+ * `--slotted-page-sticky-top` decision). Under `scroll=self` the column is
107
+ * inside the root's own scroller and needs no stickiness.
108
+ */
109
+ [data-ui='wizard'][data-progress='start']:not([data-scroll='self'])
110
+ > [data-part='layout']
111
+ > [data-part='progress'] {
112
+ inset-block-start: var(--slotted-page-sticky-top, 0px);
113
+ position: sticky;
114
+ }
115
+
116
+ /**
117
+ * Above the step, the progress is a row closed by a rule: without it the
118
+ * row of markers and the step's heading read as one block of text.
119
+ */
120
+ [data-ui='wizard'][data-progress='top'] > [data-part='layout'] > [data-part='progress'] {
121
+ border-block-end: var(--_rule-size) solid var(--_rule);
122
+ padding-block-end: var(--_rhythm);
123
+ }
124
+
125
+ /* ── The compact progress ─────────────────────────────────────────────── */
126
+
127
+ /**
128
+ * One bar that says where the reader is, and opens the whole list. It is
129
+ * laid out only below the compact class (the query at the end of this
130
+ * sheet); above it the list is always open and the bar is gone.
131
+ *
132
+ * ┌──────────────────────────────────────────────┐
133
+ * │ Step 2 of 5 ⌄ │
134
+ * │ ▬▬▬▬▬▬▬ ▬▬▬▬▬▬▬ ▭▭▭▭▭▭▭ ▭▭▭▭▭▭▭ ▭▭▭▭▭▭▭ │
135
+ * └──────────────────────────────────────────────┘
136
+ *
137
+ * It does not repeat the step's name: the step's heading stands directly
138
+ * under it and says it at heading size. What the bar adds is how far the
139
+ * flow goes, one segment per step, which a phone has no column to show.
140
+ *
141
+ * It is painted as a control at rest — the control surface, its resting
142
+ * edge and lift, its radius — because it is one: it opens and closes.
143
+ */
144
+ [data-ui='wizard']
145
+ > [data-part='layout']
146
+ > [data-part='progress']
147
+ > [data-part='progress-toggle'] {
148
+ align-items: center;
149
+ appearance: none;
150
+ background-color: var(--slotted-control-surface, Field);
151
+ border: var(--slotted-control-border-width, 1px) solid
152
+ var(--slotted-control-border-color, ButtonBorder);
153
+ border-radius: var(--slotted-control-radius, 6px);
154
+ box-shadow: var(--slotted-control-shadow, none);
155
+ color: inherit;
156
+ column-gap: var(--slotted-space-5, 0.75rem);
157
+ cursor: pointer;
158
+ display: none;
159
+ font: inherit;
160
+ grid-template-areas:
161
+ 'position icon'
162
+ 'track icon';
163
+ grid-template-columns: minmax(0, 1fr) auto;
164
+ inline-size: 100%;
165
+ margin: 0;
166
+ min-block-size: var(--slotted-control-height-lg, 2.75rem);
167
+ padding-block: var(--slotted-space-4, 0.5rem);
168
+ padding-inline: var(--slotted-control-padding-inline-md, 0.75rem);
169
+ row-gap: var(--slotted-space-3, 0.375rem);
170
+ text-align: start;
171
+ transition:
172
+ border-color var(--slotted-control-transition-duration, var(--slotted-duration-short))
173
+ var(--slotted-control-transition-easing, var(--slotted-easing-standard, ease)),
174
+ box-shadow var(--slotted-control-transition-duration, var(--slotted-duration-short))
175
+ var(--slotted-control-transition-easing, var(--slotted-easing-standard, ease));
176
+ }
177
+
178
+ [data-ui='wizard']
179
+ > [data-part='layout']
180
+ > [data-part='progress']
181
+ > [data-part='progress-toggle']:hover:not(:disabled):not([data-disabled]) {
182
+ border-color: var(
183
+ --slotted-wizard-toggle-hover-border-color,
184
+ var(--slotted-tone-accent-border)
185
+ );
186
+ }
187
+
188
+ [data-ui='wizard']
189
+ > [data-part='layout']
190
+ > [data-part='progress']
191
+ > [data-part='progress-toggle']:active:not(:disabled):not([data-disabled]) {
192
+ background-color: var(
193
+ --slotted-wizard-toggle-active-background,
194
+ var(--slotted-tone-secondary-subtle-hover)
195
+ );
196
+ }
197
+
198
+ [data-ui='wizard']
199
+ > [data-part='layout']
200
+ > [data-part='progress']
201
+ > [data-part='progress-toggle']:focus-visible {
202
+ box-shadow: var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
203
+ var(--slotted-focus-ring-color, Highlight);
204
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
205
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
206
+ }
207
+
208
+ [data-ui='wizard']
209
+ > [data-part='layout']
210
+ > [data-part='progress']
211
+ > [data-part='progress-toggle']
212
+ > [data-part='progress-position'] {
213
+ font-size: var(--slotted-font-size-sm, 0.8125rem);
214
+ font-weight: var(--slotted-font-weight-medium, 500);
215
+ grid-area: position;
216
+ line-height: var(--slotted-line-height-sm, 1.45);
217
+ }
218
+
219
+ /**
220
+ * One segment per step, filled for a step that is complete or current and
221
+ * painted in the danger tone for a step in error: the same three facts the
222
+ * list's markers carry, at the size a bar can hold. The track is
223
+ * `aria-hidden`; the position in words is the bar's accessible name.
224
+ * Every segment fills the track's height; colour alone separates a step
225
+ * ahead from a step reached.
226
+ */
227
+ [data-ui='wizard']
228
+ > [data-part='layout']
229
+ > [data-part='progress']
230
+ > [data-part='progress-toggle']
231
+ > [data-part='progress-track'] {
232
+ align-items: center;
233
+ block-size: var(--slotted-space-2, 0.25rem);
234
+ display: flex;
235
+ gap: var(--slotted-space-1, 0.125rem);
236
+ grid-area: track;
237
+ min-inline-size: 0;
238
+ }
239
+
240
+ [data-ui='wizard']
241
+ > [data-part='layout']
242
+ > [data-part='progress']
243
+ > [data-part='progress-toggle']
244
+ > [data-part='progress-track']
245
+ > [data-part='progress-segment'] {
246
+ background-color: var(
247
+ --slotted-wizard-segment-color,
248
+ var(--slotted-control-border-color, ButtonBorder)
249
+ );
250
+ block-size: 100%;
251
+ border-radius: var(--slotted-radius-full, 9999px);
252
+ flex: 1 1 0;
253
+ transition: background-color var(--slotted-duration-medium) var(--slotted-easing-standard, ease);
254
+ }
255
+
256
+ [data-ui='wizard']
257
+ > [data-part='layout']
258
+ > [data-part='progress']
259
+ > [data-part='progress-toggle']
260
+ > [data-part='progress-track']
261
+ > [data-part='progress-segment']:is([data-complete], [data-current]) {
262
+ background-color: var(
263
+ --slotted-wizard-segment-color-complete,
264
+ var(--slotted-tone-accent-solid, Highlight)
265
+ );
266
+ }
267
+
268
+ [data-ui='wizard']
269
+ > [data-part='layout']
270
+ > [data-part='progress']
271
+ > [data-part='progress-toggle']
272
+ > [data-part='progress-track']
273
+ > [data-part='progress-segment'][data-invalid] {
274
+ background-color: var(
275
+ --slotted-wizard-segment-color-invalid,
276
+ var(--slotted-tone-danger-solid, Mark)
277
+ );
278
+ }
279
+
280
+ /**
281
+ * The chevron turns a half turn when the list opens. The eye follows it
282
+ * because it is the control the reader just pressed.
283
+ */
284
+ [data-ui='wizard']
285
+ > [data-part='layout']
286
+ > [data-part='progress']
287
+ > [data-part='progress-toggle']
288
+ > [data-ui='icon'] {
289
+ color: var(--_muted);
290
+ grid-area: icon;
291
+ transition: rotate var(--slotted-duration-short) var(--slotted-easing-standard, ease);
292
+ }
293
+
294
+ [data-ui='wizard']
295
+ > [data-part='layout']
296
+ > [data-part='progress'][data-open]
297
+ > [data-part='progress-toggle']
298
+ > [data-ui='icon'] {
299
+ rotate: 180deg;
300
+ }
301
+
302
+ /* ── The step ─────────────────────────────────────────────────────────── */
303
+
304
+ [data-ui='wizard'] > [data-part='layout'] > [data-part='main'] {
305
+ display: flex;
306
+ flex-direction: column;
307
+ gap: var(--_rhythm);
308
+ min-inline-size: 0;
309
+ }
310
+
311
+ [data-ui='wizard'] > [data-part='layout'] > [data-part='main'] > [data-part='error'] {
312
+ min-inline-size: 0;
313
+ }
314
+
315
+ [data-ui='wizard'] > [data-part='layout'] > [data-part='main'] > [data-part='step'] {
316
+ display: flex;
317
+ flex-direction: column;
318
+ gap: var(--_header-gap);
319
+ min-inline-size: 0;
320
+ }
321
+
322
+ [data-ui='wizard']
323
+ > [data-part='layout']
324
+ > [data-part='main']
325
+ > [data-part='step']
326
+ > [data-part='step-header'] {
327
+ display: flex;
328
+ flex-direction: column;
329
+ gap: var(--slotted-space-2, 0.25rem);
330
+ min-inline-size: 0;
331
+ }
332
+
333
+ /**
334
+ * The heading carries the position on its own line above the name, so a
335
+ * screen reader that lands on it hears "Step 2 of 5, Shipping address" —
336
+ * the order the WAI multi-page tutorial asks for — and a sighted reader
337
+ * sees the name at heading size and the position as its eyebrow.
338
+ *
339
+ * It takes focus on every step change and draws no ring: it is a reading
340
+ * position, not a control, and a ring on a heading after every Next reads
341
+ * as a selection nobody made. `form`'s summary, which is a region a reader
342
+ * is sent to with work to do, keeps its own.
343
+ */
344
+ [data-ui='wizard']
345
+ > [data-part='layout']
346
+ > [data-part='main']
347
+ > [data-part='step']
348
+ > [data-part='step-header']
349
+ > [data-part='step-title'] {
350
+ font-family: var(
351
+ --slotted-font-family-heading,
352
+ var(--slotted-font-family-sans, ui-sans-serif, system-ui, sans-serif)
353
+ );
354
+ font-size: var(--slotted-font-size-2xl, 1.25rem);
355
+ font-weight: var(--slotted-font-weight-semibold, 600);
356
+ line-height: var(--slotted-line-height-2xl, 1.4);
357
+ margin: 0;
358
+ outline: none;
359
+ overflow-wrap: anywhere;
360
+ }
361
+
362
+ [data-ui='wizard']
363
+ > [data-part='layout']
364
+ > [data-part='main']
365
+ > [data-part='step']
366
+ > [data-part='step-header']
367
+ > [data-part='step-title']
368
+ > [data-part='position'] {
369
+ color: var(--_muted);
370
+ display: block;
371
+ font-size: var(--slotted-font-size-sm, 0.8125rem);
372
+ font-weight: var(--slotted-font-weight-medium, 500);
373
+ line-height: var(--slotted-line-height-sm, 1.45);
374
+ margin-block-end: var(--slotted-space-1, 0.125rem);
375
+ }
376
+
377
+ /**
378
+ * The optional mark sits after the name on the heading's line. Its own
379
+ * baseline alignment is `tag`'s. The part opens with a space, which keeps
380
+ * the name and the mark two words in the heading's accessible name; the
381
+ * margin adds to that space what a tag's frame needs to stand clear.
382
+ */
383
+ [data-ui='wizard']
384
+ > [data-part='layout']
385
+ > [data-part='main']
386
+ > [data-part='step']
387
+ > [data-part='step-header']
388
+ > [data-part='step-title']
389
+ > [data-part='optional'] {
390
+ margin-inline-start: var(--slotted-space-1, 0.125rem);
391
+ vertical-align: middle;
392
+ }
393
+
394
+ [data-ui='wizard']
395
+ > [data-part='layout']
396
+ > [data-part='main']
397
+ > [data-part='step']
398
+ > [data-part='step-header']
399
+ > [data-part='step-description'] {
400
+ color: var(--_muted);
401
+ font-size: var(--slotted-font-size-md, 0.875rem);
402
+ line-height: var(--slotted-line-height-md, 1.5);
403
+ margin: 0;
404
+ }
405
+
406
+ /**
407
+ * The restore wait. The step keeps its header, whose parts hold skeleton
408
+ * lines in place of the position and the name — each line one cap of the
409
+ * type it stands for, inside that type's own line box — and the form is
410
+ * replaced by this part: one `field` whose label and control are
411
+ * skeletons, at the field's own gap. Nothing moves when the step arrives.
412
+ * Actions are absent while it stands.
413
+ */
414
+ [data-ui='wizard']
415
+ > [data-part='layout']
416
+ > [data-part='main']
417
+ > [data-part='step']
418
+ > [data-part='skeleton'] {
419
+ display: flex;
420
+ flex-direction: column;
421
+ min-inline-size: 0;
422
+ }
423
+
424
+ /* ── The actions ──────────────────────────────────────────────────────── */
425
+
426
+ /**
427
+ * Two groups at the two ends of one row, above a rule that ends the step.
428
+ * The order on screen is the order in the DOM (WCAG 2.4.3): what leaves
429
+ * the flow at the start, what moves it at the end, the primary action last.
430
+ */
431
+ [data-ui='wizard'] > [data-part='layout'] > [data-part='main'] > [data-part='actions'] {
432
+ align-items: center;
433
+ border-block-start: var(--_rule-size) solid var(--_rule);
434
+ display: flex;
435
+ flex-wrap: wrap;
436
+ gap: var(--_action-gap) var(--_gap);
437
+ justify-content: space-between;
438
+ padding-block-start: var(--_rhythm);
439
+ }
440
+
441
+ [data-ui='wizard']
442
+ > [data-part='layout']
443
+ > [data-part='main']
444
+ > [data-part='actions']
445
+ > :is([data-part='actions-start'], [data-part='actions-end']) {
446
+ align-items: center;
447
+ display: flex;
448
+ flex-wrap: wrap;
449
+ gap: var(--_action-gap);
450
+ min-inline-size: 0;
451
+ }
452
+
453
+ /**
454
+ * The end group keeps the end edge when the start group is empty or
455
+ * absent, and when the row wraps.
456
+ */
457
+ /**
458
+ * The draft status is set a step smaller than the button labels beside it,
459
+ * and centred boxes of two type sizes put their words on two lines a pixel
460
+ * apart. The start group aligns by baseline, so the status reads on the
461
+ * labels' line.
462
+ */
463
+ [data-ui='wizard']
464
+ > [data-part='layout']
465
+ > [data-part='main']
466
+ > [data-part='actions']
467
+ > [data-part='actions-start'] {
468
+ align-items: baseline;
469
+ }
470
+
471
+ [data-ui='wizard']
472
+ > [data-part='layout']
473
+ > [data-part='main']
474
+ > [data-part='actions']
475
+ > [data-part='actions-end'] {
476
+ justify-content: flex-end;
477
+ margin-inline-start: auto;
478
+ }
479
+
480
+ /**
481
+ * A ghost button has no edge, so its label is what the eye aligns, and the
482
+ * label stands one inset in from the button's box. The first one in the
483
+ * start group gives the inset back, which puts "Cancel" on the column's
484
+ * edge under the fields; its hover wash then reaches the inset past the
485
+ * edge, the way a link's does.
486
+ *
487
+ * The button neither shrinks nor takes `button`'s cap of the container's
488
+ * width: the margin makes the group an inset narrower than the button,
489
+ * and either rule gave the inset up from the button's own box and broke
490
+ * its label in two. The margin is not on the group either, which moved a
491
+ * wrapped draft status past the column.
492
+ */
493
+ [data-ui='wizard']
494
+ > [data-part='layout']
495
+ > [data-part='main']
496
+ > [data-part='actions']
497
+ > [data-part='actions-start']
498
+ > [data-ui='button'][data-variant='ghost']:first-child {
499
+ flex: none;
500
+ max-inline-size: none;
501
+ margin-inline-start: calc(var(--slotted-control-padding-inline-md, 0.75rem) * -1);
502
+ }
503
+
504
+ [data-ui='wizard']
505
+ > [data-part='layout']
506
+ > [data-part='main']
507
+ > [data-part='actions']
508
+ > [data-part='actions-start']
509
+ > [data-part='draft-status'] {
510
+ color: var(--_muted);
511
+ font-size: var(--slotted-font-size-sm, 0.8125rem);
512
+ line-height: var(--slotted-line-height-sm, 1.45);
513
+ }
514
+
515
+ [data-ui='wizard']
516
+ > [data-part='layout']
517
+ > [data-part='main']
518
+ > [data-part='actions']
519
+ > [data-part='actions-start']
520
+ > [data-part='draft-status']:empty {
521
+ display: none;
522
+ }
523
+
524
+ /* ── Edit ─────────────────────────────────────────────────────────────── */
525
+
526
+ /**
527
+ * The control a review step puts beside each answer. It is text in the
528
+ * accent, as GOV.UK's "Change" is, because it stands in a row of text — the
529
+ * action column of a `description-list` is one line box tall and aligns
530
+ * its content to the row's start, and a button's box there sat a third of
531
+ * a line below the answer it changes. It is a `button` because it moves
532
+ * the flow rather than the page; nothing else about it is a button's.
533
+ *
534
+ * It is the one part reached with a descendant combinator: it stands
535
+ * wherever the consumer's review content puts it.
536
+ */
537
+ [data-ui='wizard'] [data-part='edit'] {
538
+ appearance: none;
539
+ background: none;
540
+ border: 0;
541
+ border-radius: var(--slotted-radius-xs, 2px);
542
+ color: var(--slotted-wizard-edit-color, var(--slotted-tone-accent-text, LinkText));
543
+ cursor: pointer;
544
+ font: inherit;
545
+ font-weight: var(--slotted-font-weight-medium, 500);
546
+ margin: 0;
547
+ padding: 0;
548
+ text-decoration-line: none;
549
+ text-decoration-thickness: var(--slotted-border-width-thin, 1px);
550
+ text-underline-offset: 0.2em;
551
+ }
552
+
553
+ [data-ui='wizard'] [data-part='edit']:hover:not(:disabled):not([aria-disabled='true']) {
554
+ text-decoration-line: underline;
555
+ }
556
+
557
+ [data-ui='wizard'] [data-part='edit']:focus-visible {
558
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
559
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
560
+ }
561
+
562
+ [data-ui='wizard'] [data-part='edit']:is(:disabled, [aria-disabled='true']) {
563
+ color: var(--slotted-disabled-foreground, GrayText);
564
+ cursor: not-allowed;
565
+ }
566
+
567
+ /* ── After the submission ─────────────────────────────────────────────── */
568
+
569
+ /**
570
+ * The consumer's content in place of the step and the actions. It takes
571
+ * focus once, and draws no ring for the step title's reason.
572
+ */
573
+ [data-ui='wizard'] > [data-part='layout'] > [data-part='main'] > [data-part='complete'] {
574
+ min-inline-size: 0;
575
+ outline: none;
576
+ }
577
+
578
+ /* ── Scrolling inside a layer ─────────────────────────────────────────── */
579
+
580
+ /**
581
+ * Inside a dialog, a drawer or a pane with a height: the root takes that
582
+ * height, the step scrolls, and the actions stay at the bottom on the
583
+ * ground of the host. `min-block-size: 0` at each level is what lets a
584
+ * flex child shrink below its content; `overscroll-behavior` keeps a wheel
585
+ * at the end of the step from scrolling the page behind the layer.
586
+ */
587
+ [data-ui='wizard'][data-scroll='self'] {
588
+ block-size: 100%;
589
+ min-block-size: 0;
590
+ }
591
+
592
+ [data-ui='wizard'][data-scroll='self'] > [data-part='layout'] {
593
+ block-size: 100%;
594
+ min-block-size: 0;
595
+ }
596
+
597
+ [data-ui='wizard'][data-scroll='self'] > [data-part='layout'] > [data-part='progress'] {
598
+ max-block-size: 100%;
599
+ overflow: auto;
600
+ padding: var(--_ring-room);
601
+ }
602
+
603
+ [data-ui='wizard'][data-scroll='self'] > [data-part='layout'] > [data-part='main'] {
604
+ block-size: 100%;
605
+ gap: 0;
606
+ min-block-size: 0;
607
+ }
608
+
609
+ [data-ui='wizard'][data-scroll='self']
610
+ > [data-part='layout']
611
+ > [data-part='main']
612
+ > :is([data-part='step'], [data-part='complete']) {
613
+ flex: 1 1 auto;
614
+ min-block-size: 0;
615
+ overflow: auto;
616
+ overscroll-behavior: contain;
617
+ padding-block: var(--_ring-room) var(--_rhythm);
618
+ padding-inline: var(--_ring-room);
619
+ }
620
+
621
+ [data-ui='wizard'][data-scroll='self']
622
+ > [data-part='layout']
623
+ > [data-part='main']
624
+ > [data-part='error'] {
625
+ padding-block-end: var(--_rhythm);
626
+ padding-inline: var(--_ring-room);
627
+ }
628
+
629
+ [data-ui='wizard'][data-scroll='self']
630
+ > [data-part='layout']
631
+ > [data-part='main']
632
+ > [data-part='actions'] {
633
+ background-color: var(--_ground);
634
+ flex: none;
635
+ padding-block-end: 0;
636
+ padding-inline: var(--_ring-room);
637
+ }
638
+
639
+ /* ── The compact class ────────────────────────────────────────────────── */
640
+
641
+ /**
642
+ * Below 600 pixels of its own width — the compact size class of
643
+ * `docs/component-features.md` §2.7 — the wizard is one column whatever the
644
+ * `progress` axis says, the list folds behind the bar, and the two action
645
+ * groups stack with the moving group underneath, each of its buttons
646
+ * sharing the line. The breakpoint is a literal because a container
647
+ * condition cannot read a custom property (token foundation, rule 4).
648
+ */
649
+ @container slotted-wizard (width < 600px) {
650
+ [data-ui='wizard'] > [data-part='layout'] {
651
+ gap: var(--_rhythm);
652
+ }
653
+
654
+ [data-ui='wizard'][data-progress='start'] > [data-part='layout'] {
655
+ grid-template-columns: minmax(0, 1fr);
656
+ }
657
+
658
+ [data-ui='wizard'][data-progress] > [data-part='layout'] > [data-part='progress'] {
659
+ border-block-end: 0;
660
+ padding-block-end: 0;
661
+ position: static;
662
+ }
663
+
664
+ [data-ui='wizard']
665
+ > [data-part='layout']
666
+ > [data-part='progress']
667
+ > [data-part='progress-toggle'] {
668
+ display: grid;
669
+ }
670
+
671
+ [data-ui='wizard']
672
+ > [data-part='layout']
673
+ > [data-part='progress']:not([data-open])
674
+ > [data-ui='stepper'] {
675
+ display: none;
676
+ }
677
+
678
+ /**
679
+ * The open list stands under the bar, in the flow, on a sunken ground
680
+ * so it reads as the bar's content rather than as the step.
681
+ */
682
+ [data-ui='wizard']
683
+ > [data-part='layout']
684
+ > [data-part='progress'][data-open]
685
+ > [data-ui='stepper'] {
686
+ background-color: var(--slotted-surface-sunken, Canvas);
687
+ border-radius: var(--slotted-control-radius, 6px);
688
+ padding: var(--slotted-space-5, 0.75rem);
689
+ }
690
+
691
+ [data-ui='wizard']
692
+ > [data-part='layout']
693
+ > [data-part='main']
694
+ > [data-part='actions']
695
+ > :is([data-part='actions-start'], [data-part='actions-end']) {
696
+ inline-size: 100%;
697
+ }
698
+
699
+ /**
700
+ * The two moving buttons share the line; a ghost Skip keeps its own
701
+ * width, because a borderless third of a row reads as empty space.
702
+ */
703
+ [data-ui='wizard']
704
+ > [data-part='layout']
705
+ > [data-part='main']
706
+ > [data-part='actions']
707
+ > [data-part='actions-end']
708
+ > [data-ui='button']:not([data-variant='ghost']) {
709
+ flex: 1 1 0;
710
+ }
711
+
712
+ /**
713
+ * The bar above says the position, so the heading's eyebrow leaves the
714
+ * picture here — and only the picture: it stays in the heading's text,
715
+ * which is what a screen reader hears when focus lands there.
716
+ */
717
+ [data-ui='wizard'][data-progress='start']
718
+ > [data-part='layout']
719
+ > [data-part='main']
720
+ > [data-part='step']
721
+ > [data-part='step-header']
722
+ > [data-part='step-title']
723
+ > [data-part='position'],
724
+ [data-ui='wizard'][data-progress='top']
725
+ > [data-part='layout']
726
+ > [data-part='main']
727
+ > [data-part='step']
728
+ > [data-part='step-header']
729
+ > [data-part='step-title']
730
+ > [data-part='position'] {
731
+ block-size: 1px;
732
+ clip-path: inset(50%);
733
+ inline-size: 1px;
734
+ margin: 0;
735
+ overflow: hidden;
736
+ position: absolute;
737
+ white-space: nowrap;
738
+ }
739
+ }
740
+ }