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

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,441 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * The trail of ancestors above the current page. It is a line of text, not a
4
+ * row of controls: no fill, no frame, no height of its own. What it borrows
5
+ * from the control scale is the gap and the type size, so a trail sitting
6
+ * above a toolbar reads at the same weight as the toolbar's own labels.
7
+ *
8
+ * Two colours carry the whole family. `--_rest` is the muted step every
9
+ * ancestor is painted in, and `--_strong` is the page's own text colour,
10
+ * which is where hover goes and where the current page sits already. Mixing
11
+ * toward a colour the theme holds to a contrast ratio in every scheme is the
12
+ * rule `link` arrived at after painting hover with a fill role; a trail is
13
+ * text for the same reason a link is.
14
+ */
15
+ [data-ui='breadcrumb'] {
16
+ --_rest: var(--slotted-breadcrumb-color, var(--slotted-text-muted, GrayText));
17
+ --_strong: var(--slotted-breadcrumb-color-current, var(--slotted-text, CanvasText));
18
+ --_hover: var(
19
+ --slotted-breadcrumb-color-hover,
20
+ color-mix(in oklab, var(--_rest) 30%, var(--_strong))
21
+ );
22
+ --_separator: var(
23
+ --slotted-breadcrumb-separator-color,
24
+ color-mix(in oklab, var(--_rest) 72%, transparent)
25
+ );
26
+ --_gap: var(--slotted-breadcrumb-gap, var(--slotted-control-gap-md, 8px));
27
+ /**
28
+ * The control glyph scale sizes the ellipsis control's box, as it sizes
29
+ * every inner control in the library (R2); the mark inside it is text and
30
+ * keeps the trail's own type.
31
+ */
32
+ --_icon-size: var(--slotted-control-icon-size-md, 16px);
33
+ --_inner-size: var(--slotted-control-inner-size-md, 24px);
34
+ --_ellipsis-hover: var(--slotted-tone-secondary-subtle-hover);
35
+ --_ellipsis-active: var(--slotted-tone-secondary-subtle-active);
36
+
37
+ color: var(--_rest);
38
+ display: block;
39
+ font-family: var(--slotted-breadcrumb-font-family, var(--slotted-font-family-sans, inherit));
40
+ font-size: var(--slotted-breadcrumb-font-size, var(--slotted-control-font-size-md, 13px));
41
+ /**
42
+ * The line box is rounded to an even number of pixels, as `alert` rounds
43
+ * its own. At 13-pixel type the scale's 1.45 gave 18.85, so every crumb,
44
+ * its focus ring and the ellipsis's ground sat on a fractional edge, and
45
+ * the page's own label drew a device pixel above the ancestors beside it.
46
+ * `md` at 13 is 19.5 and rounds to 20; dense 12 gives 18.
47
+ */
48
+ line-height: round(
49
+ nearest,
50
+ calc(var(--slotted-breadcrumb-line-height, var(--slotted-line-height-md, 1.5)) * 1em),
51
+ 2px
52
+ );
53
+ }
54
+
55
+ /**
56
+ * The list wraps rather than scrolling. A trail that scrolls hides its own
57
+ * first crumb, which is the one a reader looks for; a trail that wraps keeps
58
+ * every ancestor visible and costs one line. `row-gap` is smaller than the
59
+ * inline gap because two wrapped lines of one type size need less air between
60
+ * them than two words do beside each other.
61
+ */
62
+ [data-ui='breadcrumb'] [data-part='list'] {
63
+ align-items: center;
64
+ display: flex;
65
+ flex-wrap: wrap;
66
+ list-style: none;
67
+ margin: 0;
68
+ padding: 0;
69
+ column-gap: var(--_gap);
70
+ /**
71
+ * At least a target's height from one line to the next. A crumb is one
72
+ * line tall, below the 24-pixel minimum, and WCAG 2.5.8 accepts it only
73
+ * while a 24-pixel circle on each crumb misses its neighbours: with a
74
+ * 20-pixel line the step of 4 does that, and dense's 18-pixel line needs 6.
75
+ */
76
+ row-gap: max(
77
+ var(--slotted-breadcrumb-row-gap, var(--slotted-space-2, 0.25rem)),
78
+ calc(var(--slotted-target-min, 24px) - 1lh)
79
+ );
80
+ }
81
+
82
+ [data-ui='breadcrumb'] [data-part='item'] {
83
+ align-items: center;
84
+ column-gap: var(--_gap);
85
+ display: flex;
86
+ /**
87
+ * The item shrinks and its label truncates; the separator beside it does
88
+ * not, so a trail under pressure loses characters from the longest crumb
89
+ * rather than losing the marks that make it a trail.
90
+ */
91
+ min-inline-size: 0;
92
+ /**
93
+ * And it never exceeds the trail. Without this a pasted identifier with no
94
+ * break opportunity in it widens the list past the column it sits in,
95
+ * because a wrapping row wraps between items and not inside one.
96
+ */
97
+ max-inline-size: 100%;
98
+ }
99
+
100
+ /**
101
+ * A crumb the collapse is hiding. The rule exists because `display: flex` on
102
+ * the item above beats the user agent's own `[hidden] { display: none }` —
103
+ * author styles win over the user agent sheet — so without it every hidden
104
+ * crumb rendered and the collapse did nothing at all. The capture is what
105
+ * said so; both bindings write the attribute and neither could have known.
106
+ */
107
+ [data-ui='breadcrumb'] [data-part='item'][hidden] {
108
+ display: none;
109
+ }
110
+
111
+ /**
112
+ * The crumbs the ellipsis revealed arrive rather than appear. `@starting-style`
113
+ * applies only to an element with no style before this one, which is exactly
114
+ * a crumb leaving `hidden`; the crumbs that were already there do not move.
115
+ * Scoped to an expanded trail, so a trail that paints expanded from the start
116
+ * does not fade its crumbs in on every page load.
117
+ *
118
+ * Folding back does not animate. With `overflow="collapse"` the trail folds
119
+ * while its column is being resized, which is movement repeated on every
120
+ * frame of a drag, and the ellipsis returns in the same frame to the place
121
+ * the crumbs leave.
122
+ */
123
+ [data-ui='breadcrumb'][data-expanded] [data-part='item'] {
124
+ transition: opacity var(--slotted-duration-medium) var(--slotted-easing-enter);
125
+ }
126
+
127
+ @starting-style {
128
+ [data-ui='breadcrumb'][data-expanded] [data-part='item'] {
129
+ opacity: 0;
130
+ }
131
+ }
132
+
133
+ /* ── The crumbs ─────────────────────────────────────────────────────────
134
+ *
135
+ * An ancestor is a muted label that reaches the page's text colour under the
136
+ * pointer, and the current page is that colour already. Neither is
137
+ * underlined at rest: a trail is a row of eight rules stacked above a
138
+ * heading, and the underline arrives with the pointer and with focus, where
139
+ * it distinguishes the one crumb being addressed from the seven beside it.
140
+ */
141
+
142
+ [data-ui='breadcrumb'] :is([data-part='link'], [data-part='page'], [data-part='trigger']) {
143
+ border-radius: var(--slotted-breadcrumb-radius, var(--slotted-control-radius, 4px));
144
+ display: block;
145
+ /**
146
+ * A crumb truncates because the trail ran out of room, not because it
147
+ * passed a number this stylesheet invented: the row wraps first, and only
148
+ * a crumb wider than the whole trail loses characters. An application that
149
+ * wants every crumb capped sets the measure itself. Whatever is cut, the
150
+ * string stays in the DOM and in the accessible name, which is the
151
+ * repository's rule for every truncation.
152
+ */
153
+ max-inline-size: var(--slotted-breadcrumb-item-measure, 100%);
154
+ /* A flex item refuses to shrink below its content until it is told to. */
155
+ min-inline-size: 0;
156
+ overflow: hidden;
157
+ text-decoration-color: transparent;
158
+ text-decoration-line: underline;
159
+ text-decoration-thickness: var(--slotted-breadcrumb-underline-thickness, from-font);
160
+ text-overflow: ellipsis;
161
+ text-underline-offset: var(--slotted-breadcrumb-underline-offset, 0.2em);
162
+ transition:
163
+ color var(--slotted-duration-short) var(--slotted-easing-standard),
164
+ text-decoration-color var(--slotted-duration-short) var(--slotted-easing-standard);
165
+ white-space: nowrap;
166
+ }
167
+
168
+ [data-ui='breadcrumb'] [data-part='link'] {
169
+ color: inherit;
170
+ }
171
+
172
+ /**
173
+ * A crumb that opens a menu of its siblings. It is a `button` dressed as the
174
+ * crumb it stands for: the same muted text, the same underline arriving with
175
+ * the pointer, and a chevron after the label that says a list opens here
176
+ * rather than a page. It keeps the line's height; the menu is the consumer's.
177
+ */
178
+ [data-ui='breadcrumb'] [data-part='trigger'] {
179
+ appearance: none;
180
+ background-color: transparent;
181
+ border: 0;
182
+ color: inherit;
183
+ cursor: pointer;
184
+ font: inherit;
185
+ padding: 0;
186
+ text-align: start;
187
+ }
188
+
189
+ /* The switcher of the page the reader is on is still the page. */
190
+ [data-ui='breadcrumb'] [data-part='trigger'][aria-current='page'] {
191
+ color: var(--_strong);
192
+ font-weight: var(--slotted-breadcrumb-page-weight, var(--slotted-font-weight-medium, 500));
193
+ }
194
+
195
+ /**
196
+ * What a crumb carries beside its label: a glyph or an avatar before it, a
197
+ * count after it, the chevron at the end of a switcher. They stay inline so
198
+ * the label keeps its ellipsis — a flex crumb would put the text in an
199
+ * anonymous box that cannot truncate — and `icon` already centres itself on
200
+ * the text. The trail only decides the distance, a step of 6 either side.
201
+ * An atomic inline box takes no underline, so the hover rule marks the words
202
+ * and not the glyph.
203
+ */
204
+ [data-ui='breadcrumb']
205
+ :is([data-part='link'], [data-part='page'], [data-part='trigger'])
206
+ > :is([data-ui='icon'], [data-ui='avatar']) {
207
+ margin-inline-end: var(--slotted-breadcrumb-content-gap, var(--slotted-space-3, 6px));
208
+ }
209
+
210
+ [data-ui='breadcrumb']
211
+ :is([data-part='link'], [data-part='page'], [data-part='trigger'])
212
+ > [data-ui='badge'] {
213
+ margin-inline-start: var(--slotted-breadcrumb-content-gap, var(--slotted-space-3, 6px));
214
+ }
215
+
216
+ /* The switcher's chevron is its last element, after the label. */
217
+ [data-ui='breadcrumb'] [data-part='trigger'] > [data-ui='icon']:last-child {
218
+ margin-inline: var(--slotted-space-2, 4px) 0;
219
+ transition: rotate var(--slotted-duration-short) var(--slotted-easing-standard);
220
+ }
221
+
222
+ /* The chevron turns while the menu it opened is up, and back when it closes. */
223
+ [data-ui='breadcrumb'] [data-part='trigger'][data-open] > [data-ui='icon']:last-child {
224
+ rotate: 180deg;
225
+ }
226
+
227
+ /**
228
+ * The page the reader is on. It takes the strongest text colour and gains
229
+ * weight, so the end of the trail is legible without reading it — and the
230
+ * weight is on the one crumb that never moves, so nothing beside it shifts
231
+ * when the pointer arrives.
232
+ */
233
+ [data-ui='breadcrumb'] [data-part='page'] {
234
+ color: var(--_strong);
235
+ font-weight: var(--slotted-breadcrumb-page-weight, var(--slotted-font-weight-medium, 500));
236
+ }
237
+
238
+ [data-ui='breadcrumb'] :is([data-part='link'], [data-part='trigger']):not([data-disabled]):hover {
239
+ color: var(--_hover);
240
+ text-decoration-color: currentColor;
241
+ }
242
+
243
+ /* An open switcher holds the pressed colour for as long as its menu is up. */
244
+ [data-ui='breadcrumb']
245
+ :is([data-part='link'], [data-part='trigger']):not([data-disabled]):is(:active, [data-open]) {
246
+ color: var(--_strong);
247
+ /* Without the pointer over it an open switcher would read as the page:
248
+ same colour, no mark. The underline says which crumb the menu is from. */
249
+ text-decoration-color: currentColor;
250
+ }
251
+
252
+ /**
253
+ * The page's own switcher is already at the strongest colour, so the pointer
254
+ * brings only the underline, and a press — or the menu it opened — steps the
255
+ * label back to the hover mix. Hover and press still differ, as on a link.
256
+ */
257
+ [data-ui='breadcrumb'] [data-part='trigger'][aria-current='page']:not([data-disabled]):hover {
258
+ color: var(--_strong);
259
+ }
260
+
261
+ [data-ui='breadcrumb']
262
+ [data-part='trigger'][aria-current='page']:not([data-disabled]):is(:active, [data-open]) {
263
+ color: var(--_hover);
264
+ }
265
+
266
+ /**
267
+ * The ring hugs a crumb at one pixel and sits inside the ellipsis. A crumb is
268
+ * text with no border for the ring to clear — the distance `link` arrived at
269
+ * for the same reason — and at two pixels its ring reached into the
270
+ * separator beside it. The ellipsis draws its ring inward, the way every
271
+ * inner control in the library draws it: the box hands half the gap back to
272
+ * the trail, and a rotated separator leans two pixels past its own one-pixel
273
+ * box, so a ring drawn outside crossed both separators — at two pixels out,
274
+ * and on its own edge at dense.
275
+ */
276
+ [data-ui='breadcrumb'] :is([data-part='link'], [data-part='trigger']):focus-visible {
277
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
278
+ outline-offset: var(--slotted-breadcrumb-focus-ring-offset, 1px);
279
+ text-decoration-color: currentColor;
280
+ }
281
+
282
+ [data-ui='breadcrumb'] [data-part='ellipsis']:focus-visible {
283
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
284
+ outline-offset: var(
285
+ --slotted-breadcrumb-ellipsis-focus-ring-offset,
286
+ calc(-1 * var(--slotted-focus-ring-width, 2px))
287
+ );
288
+ }
289
+
290
+ /* ── The separator ──────────────────────────────────────────────────────
291
+ *
292
+ * Geometry, not a character and not a glyph mask. The APG example draws it
293
+ * as a border skewed with `transform` so it never reaches the accessibility
294
+ * tree, and `docs/token-foundation.md` forbids drawing an icon from a
295
+ * character — a rotated rule is neither.
296
+ *
297
+ * It is an element rather than a pseudo-element because a consumer may put
298
+ * their own mark inside it, and a pseudo-element holds no content the
299
+ * consumer wrote. The rule is drawn on the element itself, so a separator
300
+ * with children shows the children and the empty one shows the rule.
301
+ */
302
+
303
+ [data-ui='breadcrumb'] [data-part='separator'] {
304
+ align-items: center;
305
+ color: var(--_separator);
306
+ display: flex;
307
+ flex: none;
308
+ justify-content: center;
309
+ }
310
+
311
+ [data-ui='breadcrumb'] [data-part='separator']:empty {
312
+ background-color: currentColor;
313
+ /* Rounded, so a rule of `0.9em` ends on a whole pixel: 12 at 13px, 11 dense. */
314
+ block-size: round(nearest, var(--slotted-breadcrumb-separator-length, 0.9em), 1px);
315
+ border-radius: var(--slotted-radius-full, 9999px);
316
+ inline-size: var(
317
+ --slotted-breadcrumb-separator-thickness,
318
+ var(--slotted-border-width-thin, 1px)
319
+ );
320
+ rotate: var(--slotted-breadcrumb-separator-skew, 20deg);
321
+ }
322
+
323
+ /**
324
+ * A slash leans the other way in a right-to-left document, the same way the
325
+ * trail itself runs the other way. `:dir()` rather than an ancestor `[dir]`,
326
+ * so a trail inside a left-to-right island leans the way that island reads.
327
+ */
328
+ [data-ui='breadcrumb'] [data-part='separator']:empty:dir(rtl) {
329
+ rotate: calc(-1 * var(--slotted-breadcrumb-separator-skew, 20deg));
330
+ }
331
+
332
+ /* ── The ellipsis ───────────────────────────────────────────────────────
333
+ *
334
+ * What the collapse hides, and the control that reveals it. It is an inner
335
+ * control, not a button (R2, BC1): one line of the trail tall, so it sits
336
+ * on the crumbs' own line and not on a taller box centred over it; the
337
+ * control glyph plus a step of air wide, floored at the WCAG 2.2 minimum;
338
+ * and the rest of that minimum in the block axis is a transparent halo
339
+ * around the paint, so the target is whole without the box being tall.
340
+ *
341
+ * The mark inside it is the `ellipsis` Glyph element in an `icon` box, at
342
+ * the control glyph size — the same way every other inner control in the
343
+ * library draws its mark, and what BC1 asks for. It was the
344
+ * character U+2026 set in the trail's own type, which was the one exception
345
+ * the library took to rule 3 of `docs/token-foundation.md`, on the grounds
346
+ * that U+2026 stands in for omitted content rather than for a concept. The
347
+ * exception cost more than it bought: a character carries the metrics of
348
+ * whatever font the page loads, so the three dots had to be re-sized and
349
+ * lifted off their own baseline by hand to sit where a glyph sits by
350
+ * construction — which is what `toolbar` was doing with a font step and a
351
+ * translate of half an x-height (BC2). The rule stands as written; this
352
+ * control stops being its exception.
353
+ *
354
+ * The box still keeps the trail's type, because `1lh` is the trail's line
355
+ * and that is the alignment BC1 asks for: the box is one line of the trail
356
+ * tall and the mark is centred in it.
357
+ *
358
+ * The button's accessible name says how many crumbs it hides, so what a
359
+ * reader hears is a count rather than three dots.
360
+ */
361
+
362
+ [data-ui='breadcrumb'] [data-part='ellipsis'] {
363
+ --slotted-icon-size: var(--_icon-size);
364
+
365
+ align-items: center;
366
+ appearance: none;
367
+ background-color: transparent;
368
+ block-size: 1lh;
369
+ border: 0;
370
+ border-radius: var(--slotted-breadcrumb-ellipsis-radius, var(--slotted-radius-xs, 2px));
371
+ color: inherit;
372
+ cursor: pointer;
373
+ display: flex;
374
+ font: inherit;
375
+ inline-size: max(
376
+ var(--slotted-target-min, 24px),
377
+ min(calc(var(--_icon-size) + 2 * var(--slotted-space-2, 0.25rem)), var(--_inner-size))
378
+ );
379
+ justify-content: center;
380
+ /**
381
+ * The box carries a step of air on each side of the glyph so the target
382
+ * reaches 24 pixels, and that air added itself to the trail's gap: the
383
+ * dots stood 12 pixels from the separators where every word stands 8. The
384
+ * margin hands the gap back down to one step of air between the box and
385
+ * the separator's own box, because the rotated rule leans two pixels past
386
+ * it and the ring and the hover ground must clear its tips: 8 becomes 4 at
387
+ * comfortable, and dense, whose gap is already 4, keeps it. The target
388
+ * stays whole.
389
+ */
390
+ margin-inline: min(0px, calc(var(--slotted-space-2, 0.25rem) - var(--_gap)));
391
+ padding: 0;
392
+ position: relative;
393
+ transition: background-color var(--slotted-duration-short) var(--slotted-easing-standard);
394
+ }
395
+
396
+ /* The halo that completes the target where the line is shorter than it. */
397
+ [data-ui='breadcrumb'] [data-part='ellipsis']::after {
398
+ content: '';
399
+ inset: min(0px, calc((100% - var(--slotted-target-min, 24px)) / 2));
400
+ position: absolute;
401
+ }
402
+
403
+ /* On a finger the halo reaches the comfortable size in both axes; the box
404
+ keeps the line's height, so the trail does not grow. */
405
+ @media (pointer: coarse) {
406
+ [data-ui='breadcrumb'] [data-part='ellipsis']::after {
407
+ inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
408
+ }
409
+ }
410
+
411
+ /* The ground moves under the pointer and nothing else does (R2). */
412
+ [data-ui='breadcrumb'] [data-part='ellipsis']:not([data-disabled]):hover {
413
+ background-color: var(--slotted-breadcrumb-ellipsis-background-hover, var(--_ellipsis-hover));
414
+ }
415
+
416
+ [data-ui='breadcrumb'] [data-part='ellipsis']:not([data-disabled]):active {
417
+ background-color: var(--slotted-breadcrumb-ellipsis-background-active, var(--_ellipsis-active));
418
+ }
419
+
420
+ /* ── Forced colours ─────────────────────────────────────────────────────
421
+ *
422
+ * The theme remaps every token it owns, so this block covers only what the
423
+ * family paints itself, which is one thing: the separator is a painted rule,
424
+ * and a painted surface is replaced by the page's own background when the
425
+ * system takes the palette over. It is restated against a system colour so
426
+ * the trail keeps its marks.
427
+ *
428
+ * The ellipsis mark is an `svg` stroked in `currentColor`, which is the
429
+ * button's own ink, and the system forces that ink to its text colour.
430
+ */
431
+
432
+ @media (forced-colors: active) {
433
+ [data-ui='breadcrumb'] [data-part='separator']:empty {
434
+ background-color: GrayText;
435
+ }
436
+
437
+ [data-ui='breadcrumb'] [data-part='ellipsis'] {
438
+ border: var(--slotted-border-width-thin, 1px) solid ButtonBorder;
439
+ }
440
+ }
441
+ }
@@ -0,0 +1,50 @@
1
+ [
2
+ "--slotted-border-width-thin",
3
+ "--slotted-breadcrumb-color",
4
+ "--slotted-breadcrumb-color-current",
5
+ "--slotted-breadcrumb-color-hover",
6
+ "--slotted-breadcrumb-content-gap",
7
+ "--slotted-breadcrumb-ellipsis-background-active",
8
+ "--slotted-breadcrumb-ellipsis-background-hover",
9
+ "--slotted-breadcrumb-ellipsis-focus-ring-offset",
10
+ "--slotted-breadcrumb-ellipsis-radius",
11
+ "--slotted-breadcrumb-focus-ring-offset",
12
+ "--slotted-breadcrumb-font-family",
13
+ "--slotted-breadcrumb-font-size",
14
+ "--slotted-breadcrumb-gap",
15
+ "--slotted-breadcrumb-item-measure",
16
+ "--slotted-breadcrumb-line-height",
17
+ "--slotted-breadcrumb-page-weight",
18
+ "--slotted-breadcrumb-radius",
19
+ "--slotted-breadcrumb-row-gap",
20
+ "--slotted-breadcrumb-separator-color",
21
+ "--slotted-breadcrumb-separator-length",
22
+ "--slotted-breadcrumb-separator-skew",
23
+ "--slotted-breadcrumb-separator-thickness",
24
+ "--slotted-breadcrumb-underline-offset",
25
+ "--slotted-breadcrumb-underline-thickness",
26
+ "--slotted-control-font-size-md",
27
+ "--slotted-control-gap-md",
28
+ "--slotted-control-icon-size-md",
29
+ "--slotted-control-inner-size-md",
30
+ "--slotted-control-radius",
31
+ "--slotted-duration-medium",
32
+ "--slotted-duration-short",
33
+ "--slotted-easing-enter",
34
+ "--slotted-easing-standard",
35
+ "--slotted-focus-ring-color",
36
+ "--slotted-focus-ring-width",
37
+ "--slotted-font-family-sans",
38
+ "--slotted-font-weight-medium",
39
+ "--slotted-line-height-md",
40
+ "--slotted-radius-full",
41
+ "--slotted-radius-xs",
42
+ "--slotted-space-2",
43
+ "--slotted-space-3",
44
+ "--slotted-target-comfortable",
45
+ "--slotted-target-min",
46
+ "--slotted-text",
47
+ "--slotted-text-muted",
48
+ "--slotted-tone-secondary-subtle-active",
49
+ "--slotted-tone-secondary-subtle-hover"
50
+ ]