@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,768 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * ── The chip box ───────────────────────────────────────────────────────
4
+ *
5
+ * An entity, a filter or a compact value. It is not metadata — that is
6
+ * `badge`, and the two share this tone and this type scale on purpose — and
7
+ * it is not a command until a member says so.
8
+ *
9
+ * Two attributes on every selector, always. `group` is the one part in this
10
+ * family that contains its family's root instead of sitting inside it, so it
11
+ * carries `data-ui` itself, as `badge`'s `anchor` does.
12
+ *
13
+ * **The root is never the interactive element.** A `button` cannot contain a
14
+ * `button` and an `a` cannot contain either, so a chip that both acts and
15
+ * removes has to put its two controls side by side. The root paints the box;
16
+ * `body` holds the content and is the primary target; `remove` is its
17
+ * sibling. That decision is taken once, for every member, which is what
18
+ * removes the branch Primer needs (`hasMultipleActionTargets`) and the grid
19
+ * React Aria and Angular Material reach for.
20
+ *
21
+ * There is no height token. The block size is the chip's own line box plus a
22
+ * symmetric inset, floored at the WCAG target minimum, so a tag never
23
+ * disagrees with the type it contains and no density can leave one of its
24
+ * controls unhittable.
25
+ */
26
+ [data-ui='tag'][data-part='root'] {
27
+ /**
28
+ * Tone. The neutral fill is the tone's `solid-hover` step rather than its
29
+ * `solid` one, for the reason `badge` recorded: `solid` is the colour of
30
+ * the surface itself in all three schemes, so a filled neutral chip and a
31
+ * tinted one were the same rectangle and neither read as filled.
32
+ */
33
+ --_solid: var(--slotted-tone-secondary-solid-hover);
34
+ --_solid-hover: var(--slotted-tone-secondary-solid-active);
35
+ --_solid-active: var(--slotted-tone-secondary-solid-active);
36
+ --_on-solid: var(--slotted-tone-secondary-on-solid);
37
+ --_surface: var(--slotted-tone-secondary-surface);
38
+ --_subtle-hover: var(--slotted-tone-secondary-subtle-hover);
39
+ --_subtle-active: var(--slotted-tone-secondary-subtle-active);
40
+ --_border: var(--slotted-tag-border-color, var(--slotted-tone-secondary-border));
41
+ --_text: var(--slotted-tone-secondary-text);
42
+ /**
43
+ * What a filled chip draws around itself, and for four of the five tones
44
+ * the answer is its own fill: the edge is the ground, so the chip is one
45
+ * shape. `secondary` overrides it below, because its fill is the page's
46
+ * own colour in `high-contrast` and a chip with neither edge nor contrast
47
+ * is a run of text.
48
+ */
49
+ --_edge: var(--_solid);
50
+
51
+ /**
52
+ * Size. Type, glyph and gap come from the control scale, which is the only
53
+ * scale that moves with density, so a tag shrinks beside the controls it
54
+ * sits with. The insets come from the space scale: a density step inside
55
+ * an inset this small would be sub-pixel, and density already moves the
56
+ * type, which moves the box.
57
+ */
58
+ --_font-size: var(--slotted-control-font-size-md, 13px);
59
+ --_icon-size: var(--slotted-control-icon-size-sm, 14px);
60
+ --_inner-size: var(--slotted-control-inner-size-sm, 22px);
61
+ /**
62
+ * The two tokens a host sets on a row of chips and never on a chip: the
63
+ * block inset, so a frame that is shorter than the chip at `dense` can
64
+ * ask it to give up its air rather than its type (`multi-select` and
65
+ * `tags-input` set it from the room their frame has left); and the edge,
66
+ * so a host can mark one chip — the one that answered a duplicate —
67
+ * without reaching into this sheet. Both are read here, once, and a host
68
+ * writes `[data-ui='tag']` nowhere.
69
+ */
70
+ --_inset-block: var(--slotted-tag-inset-block, var(--slotted-space-2, 0.25rem));
71
+ --_inset-inline: var(--slotted-space-4, 0.5rem);
72
+ --_gap: var(--slotted-space-2, 0.25rem);
73
+
74
+ --_line-height: var(--slotted-line-height-xs, 1.4);
75
+ --_edge-width: var(--slotted-tag-border-width, var(--slotted-border-width-thin, 1px));
76
+ --_radius: var(--slotted-radius-full, 9999px);
77
+ /**
78
+ * The corner the fills inside the border box are cut to. A fill drawn to
79
+ * the outer radius bleeds past the border's inner curve on a square chip;
80
+ * the difference is invisible on a pill, where both are round.
81
+ */
82
+ --_inner-radius: max(0px, calc(var(--_radius) - var(--_edge-width)));
83
+ /**
84
+ * The chip's own line box plus its inset, and nothing else. It carried a
85
+ * floor at the WCAG 2.2 2.5.8 minimum for a while, so that the remove
86
+ * control — which stretches to the chip — would be hittable; the floor
87
+ * bound on `sm` alone and it still did not deliver the target, because a
88
+ * control stretched inside a 24px border box is 22px of content between
89
+ * two edges (TG2). The target is the control's own now, taken from a
90
+ * transparent halo below, which is the answer
91
+ * `docs/token-foundation.md` names for a target short in one axis and the
92
+ * answer R2 gives for every inner control. A chip is the height of what it
93
+ * says.
94
+ */
95
+ --_own-size: calc(
96
+ var(--_font-size) * var(--_line-height) + 2 * var(--_inset-block) + 2 * var(--_edge-width)
97
+ );
98
+ /**
99
+ * Inside a control the chip is the height the foundation gives the inside
100
+ * of a control — `--slotted-control-inner-size`, which the host writes on
101
+ * the row of chips from its own size step — and its line and its inset
102
+ * are derived from that height rather than the other way round. On its own
103
+ * the two derivations return exactly the type-and-inset height above, so a
104
+ * chip in running text is unchanged. The scale exists because a chip whose
105
+ * height followed its type shrank one pixel between comfortable and dense
106
+ * while the control around it shrank eight (`docs/token-foundation.md`,
107
+ * Control geometry).
108
+ */
109
+ --_block-size: var(--slotted-control-inner-size, var(--_own-size));
110
+ --_line: min(
111
+ calc(var(--_font-size) * var(--_line-height)),
112
+ calc(var(--_block-size) - 2 * var(--_edge-width))
113
+ );
114
+ --_inset: max(0px, calc((var(--_block-size) - var(--_line) - 2 * var(--_edge-width)) / 2));
115
+
116
+ align-items: stretch;
117
+ border: var(--_edge-width) solid transparent;
118
+ border-radius: var(--_radius);
119
+ box-sizing: border-box;
120
+ display: inline-flex;
121
+ font-family: var(--slotted-tag-font-family, var(--slotted-control-font-family, sans-serif));
122
+ font-size: var(--_font-size);
123
+ font-weight: var(--slotted-tag-font-weight, var(--slotted-font-weight-medium, 500));
124
+ line-height: var(--_line);
125
+ /**
126
+ * One line, always, and no wider than what it is given. A tag holds a
127
+ * name; a tag that reflows into a paragraph has stopped being one. The
128
+ * clipping is visual only — `text-overflow` shortens nothing — so the whole
129
+ * value stays in the DOM, stays in the accessibility tree, and a page
130
+ * search still finds it.
131
+ */
132
+ max-inline-size: 100%;
133
+ min-block-size: var(--_block-size);
134
+ /* Written inside a sentence, a tag sits on the text's centre. */
135
+ vertical-align: middle;
136
+ white-space: nowrap;
137
+ }
138
+
139
+ /**
140
+ * A tag a collapse is hiding. The rule exists because `display: inline-flex`
141
+ * above beats the user agent's own `[hidden] { display: none }` — author
142
+ * styles win over the user agent sheet — so without it every hidden chip
143
+ * rendered and the collapse did nothing at all: six chosen values drew six
144
+ * chips, which ran out of the lane the control gives them and under the
145
+ * controls that end it (SL9). `breadcrumb`, `toolbar`, `tabs`, `alert` and
146
+ * `progress-indicator` each write this rule for the same reason; `tag` is
147
+ * the sheet that was missing it, and the two hosts that collapse a row of
148
+ * chips both write the attribute and neither could have known.
149
+ */
150
+ [data-ui='tag'][data-part='root'][hidden] {
151
+ display: none;
152
+ }
153
+
154
+ /* ── Tone: which of the five semantic colours the tag speaks in ────────── */
155
+
156
+ /**
157
+ * The one tone whose fill is the colour of the page. It keeps the tone's own
158
+ * border, where the other four let their fill be their edge.
159
+ */
160
+ [data-ui='tag'][data-part='root'][data-tone='secondary'] {
161
+ --_edge: var(--_border);
162
+ }
163
+
164
+ [data-ui='tag'][data-part='root'][data-tone='accent'] {
165
+ --_solid: var(--slotted-tone-accent-solid);
166
+ --_solid-hover: var(--slotted-tone-accent-solid-hover);
167
+ --_solid-active: var(--slotted-tone-accent-solid-active);
168
+ --_on-solid: var(--slotted-tone-accent-on-solid);
169
+ --_surface: var(--slotted-tone-accent-surface);
170
+ --_subtle-hover: var(--slotted-tone-accent-subtle-hover);
171
+ --_subtle-active: var(--slotted-tone-accent-subtle-active);
172
+ --_border: var(--slotted-tag-border-color, var(--slotted-tone-accent-border));
173
+ --_text: var(--slotted-tone-accent-text);
174
+ }
175
+
176
+ [data-ui='tag'][data-part='root'][data-tone='success'] {
177
+ --_solid: var(--slotted-tone-success-solid);
178
+ --_solid-hover: var(--slotted-tone-success-solid-hover);
179
+ --_solid-active: var(--slotted-tone-success-solid-active);
180
+ --_on-solid: var(--slotted-tone-success-on-solid);
181
+ --_surface: var(--slotted-tone-success-surface);
182
+ --_subtle-hover: var(--slotted-tone-success-subtle-hover);
183
+ --_subtle-active: var(--slotted-tone-success-subtle-active);
184
+ --_border: var(--slotted-tag-border-color, var(--slotted-tone-success-border));
185
+ --_text: var(--slotted-tone-success-text);
186
+ }
187
+
188
+ [data-ui='tag'][data-part='root'][data-tone='warning'] {
189
+ --_solid: var(--slotted-tone-warning-solid);
190
+ --_solid-hover: var(--slotted-tone-warning-solid-hover);
191
+ --_solid-active: var(--slotted-tone-warning-solid-active);
192
+ --_on-solid: var(--slotted-tone-warning-on-solid);
193
+ --_surface: var(--slotted-tone-warning-surface);
194
+ --_subtle-hover: var(--slotted-tone-warning-subtle-hover);
195
+ --_subtle-active: var(--slotted-tone-warning-subtle-active);
196
+ --_border: var(--slotted-tag-border-color, var(--slotted-tone-warning-border));
197
+ --_text: var(--slotted-tone-warning-text);
198
+ }
199
+
200
+ [data-ui='tag'][data-part='root'][data-tone='danger'] {
201
+ --_solid: var(--slotted-tone-danger-solid);
202
+ --_solid-hover: var(--slotted-tone-danger-solid-hover);
203
+ --_solid-active: var(--slotted-tone-danger-solid-active);
204
+ --_on-solid: var(--slotted-tone-danger-on-solid);
205
+ --_surface: var(--slotted-tone-danger-surface);
206
+ --_subtle-hover: var(--slotted-tone-danger-subtle-hover);
207
+ --_subtle-active: var(--slotted-tone-danger-subtle-active);
208
+ --_border: var(--slotted-tag-border-color, var(--slotted-tone-danger-border));
209
+ --_text: var(--slotted-tone-danger-text);
210
+ }
211
+
212
+ /**
213
+ * ── Variant: three paintings, and only two of them have an edge ────────
214
+ *
215
+ * The same three words, and the same reasoning, `badge` uses: `solid` fills
216
+ * and its edge is its own fill; `soft` fills with the tone's tinted
217
+ * `surface` and draws the tone's `border` around it; `outline` is that edge
218
+ * with nothing behind it. `soft` keeps its edge because in `high-contrast`
219
+ * every tone surface collapses to the page's own white, and there it
220
+ * converges with `outline` — which is what a high-contrast scheme is for.
221
+ */
222
+
223
+ [data-ui='tag'][data-part='root'][data-variant='solid'] {
224
+ background-color: var(--_solid, ButtonFace);
225
+ border-color: var(--_edge, ButtonFace);
226
+ color: var(--_on-solid, ButtonText);
227
+ }
228
+
229
+ [data-ui='tag'][data-part='root'][data-variant='soft'] {
230
+ background-color: var(--_surface, ButtonFace);
231
+ border-color: var(--_border, ButtonBorder);
232
+ color: var(--_text, ButtonText);
233
+ }
234
+
235
+ [data-ui='tag'][data-part='root'][data-variant='outline'] {
236
+ background-color: transparent;
237
+ border-color: var(--_border, ButtonBorder);
238
+ color: var(--_text, ButtonText);
239
+ }
240
+
241
+ /* ── Size ─────────────────────────────────────────────────────────────── */
242
+
243
+ [data-ui='tag'][data-part='root'][data-size='sm'] {
244
+ --_font-size: var(--slotted-control-font-size-sm, 12px);
245
+ --_inset-block: var(--slotted-tag-inset-block, var(--slotted-space-1, 0.125rem));
246
+ --_inset-inline: var(--slotted-space-3, 0.375rem);
247
+ }
248
+
249
+ /**
250
+ * The glyph scale has three steps and this family's three sizes span less of
251
+ * it, so `sm` and `md` land on the same one — the answer `badge` reached for
252
+ * the same reason: a 12px chip and a 13px chip should not carry visibly
253
+ * different glyphs.
254
+ */
255
+ [data-ui='tag'][data-part='root'][data-size='lg'] {
256
+ --_font-size: var(--slotted-control-font-size-lg, 14px);
257
+ --_icon-size: var(--slotted-control-icon-size-md, 16px);
258
+ --_inner-size: var(--slotted-control-inner-size-md, 24px);
259
+ --_inset-block: var(--slotted-tag-inset-block, var(--slotted-space-3, 0.375rem));
260
+ --_inset-inline: var(--slotted-space-5, 0.75rem);
261
+ --_gap: var(--slotted-space-3, 0.375rem);
262
+ }
263
+
264
+ /* ── Shape ────────────────────────────────────────────────────────────── */
265
+
266
+ [data-ui='tag'][data-part='root'][data-shape='square'] {
267
+ --_radius: var(--slotted-radius-sm, 4px);
268
+ }
269
+
270
+ /**
271
+ * ── The content box, and the primary target ────────────────────────────
272
+ *
273
+ * It carries the chip's inset rather than the root, so a hovered or pressed
274
+ * body fills the chip to its edge instead of leaving a ring of untouched
275
+ * ground around itself. It is a `span` when the tag does nothing and the
276
+ * element its member names when it does.
277
+ */
278
+ [data-ui='tag'] [data-part='body'] {
279
+ align-items: center;
280
+ /* The root paints the ground; the body paints only its own states. */
281
+ background-color: transparent;
282
+ border: 0;
283
+ border-end-start-radius: var(--_inner-radius);
284
+ border-start-start-radius: var(--_inner-radius);
285
+ box-sizing: border-box;
286
+ color: inherit;
287
+ display: inline-flex;
288
+ font: inherit;
289
+ gap: var(--_gap);
290
+ letter-spacing: inherit;
291
+ /* What lets a long chip shrink below its content, which is the condition
292
+ `text-overflow` needs to have anything to do. */
293
+ min-inline-size: 0;
294
+ padding-block: var(--_inset);
295
+ padding-inline: var(--_inset-inline);
296
+ text-align: start;
297
+ /* A body that renders as an anchor keeps the chip's shape as its
298
+ affordance; the underline belongs to `link`, on a link. */
299
+ text-decoration: none;
300
+ transition:
301
+ background-color var(--slotted-control-transition-duration)
302
+ var(--slotted-control-transition-easing),
303
+ color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
304
+ }
305
+
306
+ /* The only child rounds both ends, which is every tag that cannot be removed. */
307
+ [data-ui='tag'] [data-part='body']:last-child {
308
+ border-end-end-radius: var(--_inner-radius);
309
+ border-start-end-radius: var(--_inner-radius);
310
+ }
311
+
312
+ /**
313
+ * A body followed by a remove control gives back most of its trailing inset.
314
+ * The control is a square as tall as the chip, so its own centring already
315
+ * puts seven pixels between the words and the glyph at the medium step; the
316
+ * full inset on top of that made the label sit closer to the start edge than
317
+ * to the X, which the capture of a one-character chip showed as a pill made
318
+ * mostly of air. What is left is the gap the chip uses between any two things
319
+ * inside it.
320
+ */
321
+ [data-ui='tag'] [data-part='body']:has(+ [data-part='remove']) {
322
+ padding-inline-end: var(--_gap);
323
+ }
324
+
325
+ [data-ui='tag'] [data-part='body']:is(a, button) {
326
+ cursor: pointer;
327
+ }
328
+
329
+ /* ── The words, and the glyphs on either side of them ─────────────────── */
330
+
331
+ /**
332
+ * Where the line is clipped. `min-inline-size: 0` is what lets the box
333
+ * shrink below its content inside the flex body.
334
+ */
335
+ [data-ui='tag'] [data-part='label'] {
336
+ min-inline-size: 0;
337
+ overflow: hidden;
338
+ text-overflow: ellipsis;
339
+ /**
340
+ * A tag holds a value somebody typed, and its direction is the value's own
341
+ * rather than the page's. `plaintext` is the CSS form of `dir="auto"`: the
342
+ * first strong character decides, so an Arabic name inside an English page
343
+ * reads right to left, a Latin name inside an Arabic page reads left to
344
+ * right, and each one is clipped at its own end rather than at the page's.
345
+ * The right-to-left capture is what asked the question — a Latin value with
346
+ * leading punctuation was reordered by the paragraph around it.
347
+ */
348
+ unicode-bidi: plaintext;
349
+ }
350
+
351
+ @supports (text-box: trim-both cap alphabetic) {
352
+ [data-ui='tag'] [data-part='label'] {
353
+ /**
354
+ * The line box a flex container centres is not symmetric around the
355
+ * letters inside it: the ascender reaches further above the cap than the
356
+ * descender reaches below the baseline, so a word with no descender sits
357
+ * high in its chip and a word with one looks right. `text-box` centres
358
+ * the ink instead of the font's metrics.
359
+ *
360
+ * The padding gives `overflow: hidden` room for the descenders and the
361
+ * tall diacritics that live outside a trimmed box, and the negative
362
+ * margin gives the space straight back — the same correction `badge`
363
+ * needed after a capture showed it beheading a `g`. A proportion of the
364
+ * type rather than a step of any scale, because what has to be cleared
365
+ * is the font's own overshoot.
366
+ */
367
+ margin-block: -0.3em;
368
+ padding-block: 0.3em;
369
+ text-box: trim-both cap alphabetic;
370
+ }
371
+ }
372
+
373
+ /**
374
+ * The slot sizes what it holds: an icon box reads `--slotted-icon-size`
375
+ * from its container, and a bare glyph host such as `ng-icon` reads the
376
+ * slot's font-size, so both are the glyph scale.
377
+ */
378
+ [data-ui='tag'] [data-part='start'],
379
+ [data-ui='tag'] [data-part='end'] {
380
+ --slotted-icon-size: var(--_icon-size);
381
+
382
+ align-items: center;
383
+ block-size: var(--_icon-size);
384
+ box-sizing: border-box;
385
+ display: inline-flex;
386
+ flex: none;
387
+ font-size: var(--_icon-size);
388
+ inline-size: var(--_icon-size);
389
+ justify-content: center;
390
+ line-height: 1;
391
+ }
392
+
393
+ [data-ui='tag'] [data-part='start'] > *,
394
+ [data-ui='tag'] [data-part='end'] > * {
395
+ block-size: 100%;
396
+ display: block;
397
+ inline-size: 100%;
398
+ }
399
+
400
+ /**
401
+ * ── The selection mark ─────────────────────────────────────────────────
402
+ *
403
+ * A selected chip changes its ground, and a ground is a colour. WCAG 2.2
404
+ * 1.4.1 asks for a second signal, so the check is drawn as well — the
405
+ * `check` glyph the binding renders in an icon box, never a character.
406
+ *
407
+ * It arrives by growing from nothing rather than appearing, because the
408
+ * words beside it move to make room and an eye that cannot follow that reads
409
+ * the row as having jumped. Angular Material takes the jump and offers
410
+ * `hideSingleSelectionIndicator` to avoid it; the transition is the third
411
+ * answer, and the theme collapses its duration under reduced motion.
412
+ */
413
+ [data-ui='tag'] [data-part='indicator'] {
414
+ --slotted-icon-size: var(--_icon-size);
415
+
416
+ align-items: center;
417
+ block-size: var(--_icon-size);
418
+ display: inline-flex;
419
+ flex: none;
420
+ inline-size: 0;
421
+ /* The icon keeps its size while the box grows round it, centred and
422
+ clipped, so the check is uncovered from its middle outwards. */
423
+ justify-content: center;
424
+ /* A flex gap is drawn beside a zero-width item as readily as beside a wide
425
+ one, so the mark that is not there would still cost the chip a gap of
426
+ leading space. The negative margin is that gap, given back. */
427
+ margin-inline-end: calc(-1 * var(--_gap));
428
+ opacity: 0;
429
+ overflow: hidden;
430
+ transition:
431
+ inline-size var(--slotted-duration-short) var(--slotted-easing-standard),
432
+ margin-inline-end var(--slotted-duration-short) var(--slotted-easing-standard),
433
+ opacity var(--slotted-duration-short) var(--slotted-easing-standard);
434
+ }
435
+
436
+ [data-ui='tag'][data-part='root'][data-selected] [data-part='indicator'] {
437
+ inline-size: var(--_icon-size);
438
+ margin-inline-end: 0;
439
+ opacity: 1;
440
+ }
441
+
442
+ /**
443
+ * ── The remove control ─────────────────────────────────────────────────
444
+ *
445
+ * A segment as tall as the chip, at its end. That is Carbon's and Fluent's
446
+ * picture, and it is the one geometry that makes the target reach the WCAG
447
+ * 2.2 2.5.8 minimum in the block axis without a hidden hit area — an
448
+ * invisible box taller than the chip would reach past it and take the
449
+ * pointer from the neighbour in a wrapped run. Its width is the inner
450
+ * control's (R2): the glyph plus a step of air on each side, floored at the
451
+ * same minimum, so the segment is a square on the `sm` and `md` chips and
452
+ * a step narrower than tall on `lg`.
453
+ *
454
+ * The cost, on a pill: a hovered remove is a rounded-ended segment rather
455
+ * than a disc. That is the shape of the target, which is the truth.
456
+ *
457
+ * The mark is the `x` glyph the binding renders; the control hands its icon
458
+ * box the chip's glyph size.
459
+ */
460
+ [data-ui='tag'] [data-part='remove'] {
461
+ --slotted-icon-size: var(--_icon-size);
462
+
463
+ align-items: center;
464
+ appearance: none;
465
+ background-color: transparent;
466
+ border: 0;
467
+ border-end-end-radius: var(--_inner-radius);
468
+ border-start-end-radius: var(--_inner-radius);
469
+ box-sizing: border-box;
470
+ color: inherit;
471
+ cursor: pointer;
472
+ display: inline-flex;
473
+ flex: none;
474
+ inline-size: max(
475
+ var(--slotted-target-min, 24px),
476
+ min(calc(var(--_icon-size) + 2 * var(--slotted-space-2, 0.25rem)), var(--_inner-size))
477
+ );
478
+ justify-content: center;
479
+ padding: 0;
480
+ position: relative;
481
+ transition: background-color var(--slotted-control-transition-duration)
482
+ var(--slotted-control-transition-easing);
483
+ }
484
+
485
+ /**
486
+ * The halo that completes the target where the box is shorter than it. The
487
+ * control stretches to the chip's content box, which is the chip less its
488
+ * two edges, so on the shortest chip the box was 24 wide and 22 tall and the
489
+ * press area failed SC 2.5.8 on the axis nobody was measuring. The halo is
490
+ * transparent and it is `min(0px, …)`, so it grows the box only where the box
491
+ * falls short and is inert on the two larger sizes, where the chip is already
492
+ * taller than the minimum.
493
+ */
494
+ [data-ui='tag'] [data-part='remove']::after {
495
+ content: '';
496
+ inset: min(0px, calc((100% - var(--slotted-target-min, 24px)) / 2));
497
+ position: absolute;
498
+ }
499
+
500
+ /**
501
+ * On a finger the target is the comfortable size in both axes, and the
502
+ * control's ground is never taller than it is wide: the box is at least as
503
+ * wide as the chip is tall inside its edges, where a large chip drew a
504
+ * segment 24 wide and 32 tall. The halo above grows to 44 pixels around it.
505
+ */
506
+ @media (pointer: coarse) {
507
+ [data-ui='tag'] [data-part='remove'] {
508
+ inline-size: max(
509
+ var(--slotted-target-min, 24px),
510
+ min(calc(var(--_icon-size) + 2 * var(--slotted-space-2, 0.25rem)), var(--_inner-size)),
511
+ calc(var(--_block-size) - 2 * var(--_edge-width))
512
+ );
513
+ }
514
+
515
+ [data-ui='tag'] [data-part='remove']::after {
516
+ inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
517
+ }
518
+ }
519
+
520
+ /* A tag that is only a remove control is not a tag, but the rounding is one
521
+ rule either way rather than a case the sheet has to know about. */
522
+ [data-ui='tag'] [data-part='remove']:first-child {
523
+ border-end-start-radius: var(--_inner-radius);
524
+ border-start-start-radius: var(--_inner-radius);
525
+ }
526
+
527
+ /* ── Selected, held back for the one state stronger than it ───────────── */
528
+
529
+ /**
530
+ * A chip that is on takes the tone's solid fill whatever its variant, which
531
+ * is the rule `button` set for `pressed`: "on" is never one shade away from
532
+ * "hovered".
533
+ */
534
+ [data-ui='tag'][data-part='root'][data-selected]:not([data-disabled]) {
535
+ background-color: var(--_solid, ButtonFace);
536
+ border-color: var(--_edge, ButtonBorder);
537
+ color: var(--_on-solid, ButtonText);
538
+ }
539
+
540
+ /**
541
+ * ── Hover and press, held back for every stronger state ────────────────
542
+ *
543
+ * Each control answers on its own, because the chip holds two of them and a
544
+ * wash over the whole box could not say which one the pointer is on.
545
+ *
546
+ * Three variants, two mechanisms. `solid` and `outline` step along the
547
+ * tone's own ramp, which is what `button` does with the same two words.
548
+ * `soft` cannot: the tinted ramp ends at `surface` — measured in the light
549
+ * scheme, `subtle-hover` is #f1f5f9 against a #e2e8f0 ground and
550
+ * `subtle-active` is that ground exactly — so a tinted chip hovering to a
551
+ * tinted role either lightened or did nothing, and the first hover capture
552
+ * showed the remove segment reading paler than the chip it sits in.
553
+ *
554
+ * Its step is a state layer instead: the chip's own text colour, at a low
555
+ * strength, over whatever ground it already has. It darkens a tinted chip
556
+ * and never depends on a role the foundation does not carry. The cost is
557
+ * that a theme retunes it by strength rather than by colour, which is what
558
+ * the two component tokens are for.
559
+ */
560
+
561
+ [data-ui='tag'][data-part='root'] {
562
+ --_state-hover: color-mix(
563
+ in oklab,
564
+ currentColor var(--slotted-tag-state-layer-hover, 8%),
565
+ transparent
566
+ );
567
+ --_state-active: color-mix(
568
+ in oklab,
569
+ currentColor var(--slotted-tag-state-layer-active, 14%),
570
+ transparent
571
+ );
572
+ }
573
+
574
+ [data-ui='tag'][data-part='root'][data-variant='soft']:not([data-disabled]):not([data-selected])
575
+ :is([data-part='body']:is(a, button), [data-part='remove']):hover:not(:disabled) {
576
+ background-color: var(--_state-hover);
577
+ }
578
+
579
+ [data-ui='tag'][data-part='root'][data-variant='soft']:not([data-disabled]):not([data-selected])
580
+ :is([data-part='body']:is(a, button), [data-part='remove']):active:not(:disabled) {
581
+ background-color: var(--_state-active);
582
+ }
583
+
584
+ [data-ui='tag'][data-part='root'][data-variant='outline']:not([data-disabled]):not(
585
+ [data-selected]
586
+ )
587
+ :is([data-part='body']:is(a, button), [data-part='remove']):hover:not(:disabled) {
588
+ background-color: var(--_subtle-hover, ButtonFace);
589
+ }
590
+
591
+ [data-ui='tag'][data-part='root'][data-variant='outline']:not([data-disabled]):not(
592
+ [data-selected]
593
+ )
594
+ :is([data-part='body']:is(a, button), [data-part='remove']):active:not(:disabled) {
595
+ background-color: var(--_subtle-active, ButtonFace);
596
+ }
597
+
598
+ /**
599
+ * A filled chip washes along its own ramp, as `button` does — and a selected
600
+ * chip is a filled chip whatever its variant, so the two share these rules.
601
+ */
602
+ [data-ui='tag'][data-part='root'][data-variant='solid']:not([data-disabled])
603
+ :is([data-part='body']:is(a, button), [data-part='remove']):hover:not(:disabled),
604
+ [data-ui='tag'][data-part='root'][data-selected]:not([data-disabled])
605
+ :is([data-part='body']:is(a, button), [data-part='remove']):hover:not(:disabled) {
606
+ background-color: var(--_solid-hover, Highlight);
607
+ }
608
+
609
+ [data-ui='tag'][data-part='root'][data-variant='solid']:not([data-disabled])
610
+ :is([data-part='body']:is(a, button), [data-part='remove']):active:not(:disabled),
611
+ [data-ui='tag'][data-part='root'][data-selected]:not([data-disabled])
612
+ :is([data-part='body']:is(a, button), [data-part='remove']):active:not(:disabled) {
613
+ background-color: var(--_solid-active, Highlight);
614
+ }
615
+
616
+ /* ── Focus ────────────────────────────────────────────────────────────── */
617
+
618
+ /**
619
+ * Drawn on the control rather than on the chip, because the chip can hold
620
+ * two of them and a ring around the whole box could not say which one has
621
+ * focus. It is never held back for `disabled`: a control that keeps its
622
+ * place in the tab sequence while unavailable still has to show where focus
623
+ * is.
624
+ *
625
+ * The offset is negative, so the ring is drawn inside the control's own box.
626
+ * A positive offset on the body would put the ring over the remove control
627
+ * beside it, and on the remove it would spill outside the chip and touch the
628
+ * next tag in a wrapped run.
629
+ *
630
+ * It is two ring widths rather than one. At one the ring's outer edge landed
631
+ * exactly on the chip's own border, and the first zoomed capture showed it
632
+ * reading as a thickened rim rather than as a ring; a second width leaves a
633
+ * sliver of the chip's ground outside it, which is what separates the two.
634
+ *
635
+ * The ring takes the control's own corners, so on a pill the remove's is
636
+ * flat on the inside and round on the outside. That is the shape of the
637
+ * target: a rounded rectangle floating inside the segment would be prettier
638
+ * and would say the hit area is somewhere it is not.
639
+ */
640
+ [data-ui='tag'] [data-part='body']:focus-visible,
641
+ [data-ui='tag'] [data-part='remove']:focus-visible {
642
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
643
+ outline-offset: calc(-2 * var(--slotted-focus-ring-width, 2px));
644
+ }
645
+
646
+ /**
647
+ * The group's own ring sits outside it, because nothing is adjacent to it.
648
+ * It is drawn for one moment: the group takes focus when the last tag it
649
+ * held is removed, so the keyboard is not returned to the top of the page.
650
+ */
651
+ [data-ui='tag'][data-part='group']:focus-visible {
652
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
653
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
654
+ }
655
+
656
+ /* ── Disabled ─────────────────────────────────────────────────────────── */
657
+
658
+ /**
659
+ * Per variant, for the reason `button` records: a flat control that fills
660
+ * with grey on the way to being unavailable reads as a different control
661
+ * rather than as the same one unavailable.
662
+ *
663
+ * `[data-disabled]` rather than `:disabled` alone, because the root is never
664
+ * a control and a control that keeps its place in the tab sequence carries
665
+ * `aria-disabled` and no `:disabled`.
666
+ */
667
+ [data-ui='tag'][data-part='root'][data-disabled] {
668
+ color: var(--slotted-disabled-foreground, GrayText);
669
+ }
670
+
671
+ /**
672
+ * Three variants become two. What survives the loss of the tone is whether
673
+ * the chip is filled, and the rim has to stay on the filled one: in
674
+ * `high-contrast` the disabled ground is the page's own white, so a filled
675
+ * chip drawing its own ground as its edge had no edge at all — the third
676
+ * capture showed "Disabled selected" as a check and two words floating on
677
+ * the page with no box around them.
678
+ */
679
+ [data-ui='tag'][data-part='root'][data-variant='solid'][data-disabled],
680
+ [data-ui='tag'][data-part='root'][data-variant='soft'][data-disabled],
681
+ [data-ui='tag'][data-part='root'][data-selected][data-disabled] {
682
+ background-color: var(--slotted-disabled-background, Canvas);
683
+ border-color: var(--slotted-disabled-border, GrayText);
684
+ }
685
+
686
+ [data-ui='tag'][data-part='root'][data-variant='outline'][data-disabled] {
687
+ background-color: transparent;
688
+ border-color: var(--slotted-disabled-border, GrayText);
689
+ }
690
+
691
+ [data-ui='tag'][data-part='root'][data-disabled] :is([data-part='body'], [data-part='remove']),
692
+ [data-ui='tag'] [data-part='body']:disabled,
693
+ [data-ui='tag'] [data-part='remove']:disabled {
694
+ background-color: transparent;
695
+ cursor: not-allowed;
696
+ }
697
+
698
+ /**
699
+ * A remove control the consumer disabled on its own, inside a chip that is
700
+ * otherwise operable. It loses its colour rather than the whole chip's.
701
+ */
702
+ [data-ui='tag'] [data-part='remove']:disabled {
703
+ color: var(--slotted-disabled-foreground, GrayText);
704
+ }
705
+
706
+ /**
707
+ * ── The run of tags ────────────────────────────────────────────────────
708
+ *
709
+ * It wraps, because a filter bar with eleven filters is the normal case and
710
+ * a row that scrolls sideways hides the eleventh. It is one tab stop, and
711
+ * the arrow keys move between the controls inside it — the APG Toolbar
712
+ * pattern, which is a container for grouping a set of controls.
713
+ */
714
+ [data-ui='tag'][data-part='group'] {
715
+ align-items: center;
716
+ display: flex;
717
+ flex-wrap: wrap;
718
+ gap: var(--slotted-tag-group-gap, var(--slotted-space-2, 0.25rem));
719
+ }
720
+
721
+ [data-ui='tag'][data-part='group'][data-orientation='vertical'] {
722
+ align-items: start;
723
+ flex-direction: column;
724
+ flex-wrap: nowrap;
725
+ inline-size: fit-content;
726
+ }
727
+
728
+ /**
729
+ * An empty group takes no room. An actions area built from a permission
730
+ * filter renders one often, and the empty box still eats a gap in the row
731
+ * that holds it — the defect `button-group` recorded when it found the same
732
+ * thing.
733
+ */
734
+ [data-ui='tag'][data-part='group']:empty {
735
+ display: none;
736
+ }
737
+
738
+ /**
739
+ * ── Forced colours ─────────────────────────────────────────────────────
740
+ *
741
+ * The one place a family may write its own rule. The theme maps every tone
742
+ * ground to `ButtonFace` or `Canvas` and every tone border to
743
+ * `ButtonBorder`, so a `solid`, a `soft` and an `outline` chip become the
744
+ * same rectangle and a chip whose edge was its fill has no edge at all.
745
+ * `currentColor` is the only paint left that still separates the chip from
746
+ * the page.
747
+ *
748
+ * The selected chip is the second case: its whole signal is a ground the
749
+ * system has replaced, so there it is drawn with the system's own selected
750
+ * pair instead.
751
+ */
752
+ @media (forced-colors: active) {
753
+ [data-ui='tag'][data-part='root'] {
754
+ border-color: currentColor;
755
+ }
756
+
757
+ [data-ui='tag'][data-part='root'][data-selected]:not([data-disabled]) {
758
+ background-color: Highlight;
759
+ color: HighlightText;
760
+ forced-color-adjust: none;
761
+ }
762
+
763
+ [data-ui='tag'][data-part='root'][data-disabled] {
764
+ border-color: GrayText;
765
+ color: GrayText;
766
+ }
767
+ }
768
+ }