@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,675 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * Pairs of a term and its description, read rather than edited.
4
+ *
5
+ * The whole family is one grid and one borrowed one. The list declares a set
6
+ * of tracks per column — a term track sized to the widest term, a value track
7
+ * that takes what is left, and an action track that exists only when an
8
+ * action does — and every pair borrows those tracks with `subgrid`. That is
9
+ * what makes the terms line up down the page, which is the first thing a
10
+ * reader of a details panel notices and the one thing a `dl` of independent
11
+ * groups cannot do on its own.
12
+ *
13
+ * Every placement is a custom property set on the list, so the arrangement is
14
+ * decided in one place. The container query then changes the arrangement by
15
+ * setting those same properties, rather than by restating six rules that
16
+ * would have to be kept in step with the six above them.
17
+ */
18
+ [data-ui='description-list'] {
19
+ /**
20
+ * The root is the query container and nothing else. An element with
21
+ * `container-type: inline-size` is a container for its descendants and not
22
+ * for itself, and what the query changes here is the grid — so the grid is
23
+ * the list, one element in.
24
+ */
25
+ container-name: slotted-description-list;
26
+ container-type: inline-size;
27
+ display: block;
28
+ }
29
+
30
+ [data-ui='description-list'] [data-part='list'] {
31
+ /* ── The colours ─────────────────────────────────────────────────── */
32
+ --_ink: var(--slotted-description-list-color, var(--slotted-text, CanvasText));
33
+ --_term-ink: var(--slotted-description-list-term-color, var(--slotted-text-muted, GrayText));
34
+ --_hint-ink: var(--slotted-description-list-hint-color, var(--slotted-text-muted, GrayText));
35
+ --_rule: var(--slotted-description-list-rule-color, var(--slotted-border-subtle, ButtonBorder));
36
+ --_term-surface: var(
37
+ --slotted-description-list-term-surface,
38
+ var(--slotted-surface-sunken, Canvas)
39
+ );
40
+ --_surface: var(--slotted-description-list-surface, var(--slotted-surface, Canvas));
41
+ /**
42
+ * The mark standing in for a missing value, held on the list rather than
43
+ * stated inside the pseudo-element that paints it: an unthemed decoration
44
+ * should disappear rather than shout, which is why
45
+ * `packages/styles/src/fallbacks.test.mjs` refuses a system colour inside a
46
+ * `::before` or `::after` rule. Reading it through one property keeps the
47
+ * last resort where the theme's own tokens are.
48
+ */
49
+ --_placeholder-ink: var(
50
+ --slotted-description-list-placeholder-color,
51
+ var(--slotted-text-muted, GrayText)
52
+ );
53
+ --_control-ink: var(
54
+ --slotted-description-list-control-color,
55
+ var(--slotted-text-muted, GrayText)
56
+ );
57
+ --_control-ink-hover: var(
58
+ --slotted-description-list-control-color-hover,
59
+ var(--slotted-text, CanvasText)
60
+ );
61
+ --_control-ink-done: var(
62
+ --slotted-description-list-control-color-complete,
63
+ var(--slotted-tone-success-text, CanvasText)
64
+ );
65
+ --_link-ink: var(
66
+ --slotted-description-list-toggle-color,
67
+ var(--slotted-tone-accent-text, LinkText)
68
+ );
69
+
70
+ /* ── The measurements ────────────────────────────────────────────── */
71
+ --_term-width: var(--slotted-description-list-term-width, 14rem);
72
+ /**
73
+ * The distance between a term and its own value, and the distance between
74
+ * two pairs standing side by side. They are not the same distance: eight
75
+ * pixels reads as "these two belong together" and twenty-four as "these
76
+ * two are separate pairs", and a single gap would have to be wrong for one
77
+ * of them. A subgrid's own gap overrides the one it inherits, which is what
78
+ * lets the list state the second and each pair state the first.
79
+ */
80
+ --_pair-gap: var(--slotted-description-list-column-gap, var(--slotted-control-gap-md, 8px));
81
+ /**
82
+ * Three times the distance a term stands from its own value, and it follows
83
+ * the density with it: a dense list packs its column groups as tightly as
84
+ * it packs everything else, where a fixed two rem left the one distance on
85
+ * the page that never answered the axis.
86
+ */
87
+ --_group-gap: var(
88
+ --slotted-description-list-group-gap,
89
+ calc(var(--slotted-control-gap-md, 8px) * 3)
90
+ );
91
+ --_row-gap: var(
92
+ --slotted-description-list-row-gap,
93
+ calc(var(--slotted-control-gap-md, 8px) + var(--slotted-space-2, 0.25rem))
94
+ );
95
+ /**
96
+ * The distance between a term and the value under it, which is three times
97
+ * the distance between a term and its own hint: without that ratio the
98
+ * three lines of a stacked pair read as one paragraph and the reader has to
99
+ * find the value by its colour alone.
100
+ */
101
+ --_stack-gap: var(--slotted-description-list-stack-gap, var(--slotted-space-3, 0.375rem));
102
+ --_pad-block: var(
103
+ --slotted-description-list-cell-padding-block,
104
+ var(--slotted-control-gap-md, 8px)
105
+ );
106
+ --_pad-inline: var(
107
+ --slotted-description-list-cell-padding-inline,
108
+ var(--slotted-control-padding-inline-md, 13px)
109
+ );
110
+ --_glyph: var(--slotted-description-list-glyph-size, var(--slotted-control-icon-size-md, 16px));
111
+ --_hit: calc((var(--slotted-target-min, 24px) - var(--_glyph)) / 2);
112
+
113
+ /* ── The arrangement, decided once and read everywhere ───────────── */
114
+ --_pair: fit-content(var(--_term-width)) minmax(0, 1fr);
115
+ --_cols: var(--_pair);
116
+ --_span-1: 2;
117
+ --_span-2: 4;
118
+ --_span-3: 6;
119
+ --_item-cols: subgrid;
120
+ --_item-col-gap: var(--_pair-gap);
121
+ --_term-col: 1;
122
+ --_term-row: auto;
123
+ --_desc-col: 2 / -1;
124
+ --_desc-row: auto;
125
+ --_action-col: -2 / -1;
126
+ --_action-row: auto;
127
+
128
+ color: var(--_ink);
129
+ column-gap: var(--_group-gap);
130
+ display: grid;
131
+ font-family: var(
132
+ --slotted-description-list-font-family,
133
+ var(--slotted-font-family-sans, inherit)
134
+ );
135
+ font-size: var(--slotted-description-list-font-size, var(--slotted-control-font-size-md, 13px));
136
+ grid-template-columns: var(--_cols);
137
+ line-height: var(--slotted-description-list-line-height, var(--slotted-line-height-md, 1.5));
138
+ /* `dl` carries a user-agent margin that no layout here asked for. */
139
+ margin: 0;
140
+ }
141
+
142
+ /**
143
+ * The action track exists only where an action does. A gap applies between
144
+ * two tracks whether or not the second has any width, so declaring the track
145
+ * always would end every row of every actionless list with a distance
146
+ * nothing asked for.
147
+ */
148
+ [data-ui='description-list'] [data-part='list']:has([data-part='action']) {
149
+ --_pair: fit-content(var(--_term-width)) minmax(0, 1fr) auto;
150
+ --_span-1: 3;
151
+ --_span-2: 6;
152
+ --_span-3: 9;
153
+ --_desc-col: 2 / -2;
154
+ }
155
+
156
+ [data-ui='description-list'][data-columns='2'] [data-part='list'] {
157
+ --_cols: repeat(2, var(--_pair));
158
+ }
159
+
160
+ [data-ui='description-list'][data-columns='3'] [data-part='list'] {
161
+ --_cols: repeat(3, var(--_pair));
162
+ }
163
+
164
+ /**
165
+ * The stacked arrangement. The term is above the value and the action stays
166
+ * beside the term, where it is still the row's action rather than a third
167
+ * thing under it — which is what GOV.UK's summary list does at its own narrow
168
+ * width.
169
+ */
170
+ [data-ui='description-list'][data-layout='stack'] [data-part='list'] {
171
+ --_pair: minmax(0, 1fr);
172
+ --_term-floor: 0px;
173
+ --_span-1: 1;
174
+ --_span-2: 2;
175
+ --_span-3: 3;
176
+ --_item-cols: minmax(0, 1fr);
177
+ --_item-col-gap: var(--_pair-gap);
178
+ --_term-col: 1;
179
+ --_desc-col: 1 / -1;
180
+ --_desc-row: 2;
181
+ --_action-col: -1 / -2;
182
+ --_action-row: 1;
183
+ }
184
+
185
+ [data-ui='description-list'][data-layout='stack'] [data-part='list']:has([data-part='action']) {
186
+ --_item-cols: minmax(0, 1fr) auto;
187
+ --_desc-col: 1 / -1;
188
+ }
189
+
190
+ /* ── The pair ──────────────────────────────────────────────────────── */
191
+
192
+ [data-ui='description-list'] [data-part='item'] {
193
+ column-gap: var(--_item-col-gap);
194
+ display: grid;
195
+ grid-column: span var(--_span-1);
196
+ grid-template-columns: var(--_item-cols);
197
+ min-inline-size: 0;
198
+ row-gap: var(--_stack-gap);
199
+ }
200
+
201
+ [data-ui='description-list'] [data-part='item'][data-span='2'] {
202
+ grid-column: span var(--_span-2);
203
+ }
204
+
205
+ [data-ui='description-list'] [data-part='item'][data-span='3'] {
206
+ grid-column: span var(--_span-3);
207
+ }
208
+
209
+ [data-ui='description-list'] [data-part='term'] {
210
+ color: var(--_term-ink);
211
+ font-weight: var(
212
+ --slotted-description-list-term-weight,
213
+ var(--slotted-font-weight-medium, 500)
214
+ );
215
+ grid-column: var(--_term-col);
216
+ grid-row: var(--_term-row);
217
+ /**
218
+ * The floor a hint asks for, and nothing otherwise. Hints are held out of
219
+ * the track's own sizing below, so without a floor a list of one-word terms
220
+ * would wrap every hint one word to a line. Every stacked arrangement puts
221
+ * the floor back to nothing, because a stacked term already has the whole
222
+ * width and a floor there is only something to overflow.
223
+ *
224
+ * It is a length rather than `min(…, 100%)`: a percentage minimum is
225
+ * indefinite while a track is being sized, so the floor resolved to zero
226
+ * during exactly the pass it exists for and the column went on being the
227
+ * width of its longest term.
228
+ */
229
+ min-inline-size: var(--_term-floor, 0px);
230
+ /* A forty-character identifier is a term too, and it wraps rather than
231
+ widening a track every other pair has to live with. */
232
+ overflow-wrap: break-word;
233
+ }
234
+
235
+ /**
236
+ * One line explaining what the term means. PatternFly needs a popover for the
237
+ * same job; a dense back-office panel explains a field far more often than it
238
+ * needs a layer, and the layer is still available when the explanation is
239
+ * longer than a line.
240
+ */
241
+ [data-ui='description-list'] [data-part='list']:has([data-part='hint']) {
242
+ --_term-floor: var(--slotted-description-list-term-min, 12rem);
243
+ }
244
+
245
+ [data-ui='description-list'] [data-part='hint'] {
246
+ color: var(--_hint-ink);
247
+ /**
248
+ * A hint is a sentence and a term is two words, so a hint left to size its
249
+ * own column takes the whole of the fourteen-rem maximum and every value in
250
+ * the list pays for it: the label column stood at two hundred and
251
+ * twenty-four pixels in a four-hundred-and-twenty-pixel panel, for one
252
+ * sentence. Size containment holds the hint out of the track's intrinsic
253
+ * width — the terms decide the column, the floor above keeps it habitable,
254
+ * and the hint wraps inside what those two agreed.
255
+ */
256
+ contain: inline-size;
257
+ display: block;
258
+ font-size: var(--slotted-description-list-hint-font-size, var(--slotted-font-size-xs, 0.75rem));
259
+ font-weight: var(--slotted-font-weight-regular, 400);
260
+ line-height: var(--slotted-line-height-xs, 1.4);
261
+ margin-block-start: var(--slotted-space-1, 0.125rem);
262
+ }
263
+
264
+ /**
265
+ * The value's cell, and the ground its controls stand on. Two tracks: the
266
+ * value, which takes what it needs up to the width available, and the copy
267
+ * control beside it. The reveal toggle takes a line of its own, because a
268
+ * clamped value ends mid-sentence and a control on that line would read as
269
+ * part of it.
270
+ */
271
+ /**
272
+ * A value with no clamp and no toggle is text, and the control that copies it
273
+ * belongs at the end of that text — not at the far edge of the row, which is
274
+ * where a grid track put it the moment the value wrapped. Inline flow is the
275
+ * only thing that follows a last line, so a description with nothing but a
276
+ * value and a copy control is a block, and the grid below is for the ones
277
+ * that have a second row to place.
278
+ */
279
+ [data-ui='description-list'] [data-part='description']:not([data-clamp]) {
280
+ display: block;
281
+ }
282
+
283
+ [data-ui='description-list'] [data-part='description']:not([data-clamp]) [data-part='value'] {
284
+ display: inline;
285
+ }
286
+
287
+ [data-ui='description-list'] [data-part='description']:not([data-clamp]) [data-part='copy'] {
288
+ margin-inline-start: var(--_pair-gap);
289
+ vertical-align: text-bottom;
290
+ }
291
+
292
+ [data-ui='description-list'] [data-part='description'] {
293
+ align-items: baseline;
294
+ /**
295
+ * The distance from a value to the control that reaches it does not follow
296
+ * the density the way the distance from a term to its value does. The focus
297
+ * ring is drawn two pixels outside the control's box, and a dense list's
298
+ * four-pixel gap left the ring two pixels from the last word of the value —
299
+ * a ring that reads as a box around the text it is beside.
300
+ */
301
+ column-gap: max(var(--_pair-gap), var(--slotted-space-4, 0.5rem));
302
+ display: grid;
303
+ grid-column: var(--_desc-col);
304
+ grid-row: var(--_desc-row);
305
+ grid-template-columns: minmax(0, max-content) auto;
306
+ justify-content: start;
307
+ /* `dd` carries a user-agent inline margin of forty pixels. */
308
+ margin: 0;
309
+ min-inline-size: 0;
310
+ row-gap: var(--slotted-space-2, 0.25rem);
311
+ }
312
+
313
+ [data-ui='description-list'] [data-part='value'] {
314
+ grid-column: 1;
315
+ min-inline-size: 0;
316
+ /* An unbroken token — a hash, an ARN, a URL — breaks rather than leaving
317
+ the box it was given. */
318
+ overflow-wrap: break-word;
319
+ }
320
+
321
+ /**
322
+ * Clamping is visual only: every character stays in the DOM, selectable,
323
+ * copyable and readable by a screen reader. `docs/build-briefing.md` decided
324
+ * that for the library and section 10 of the feature guide states it for this
325
+ * family — a long value may be copied or revealed, never truncated without
326
+ * access.
327
+ */
328
+ [data-ui='description-list'] [data-part='description'][data-clamp] [data-part='value'] {
329
+ -webkit-box-orient: vertical;
330
+ -webkit-line-clamp: var(--slotted-description-list-clamp, 2);
331
+ display: -webkit-box;
332
+ overflow: hidden;
333
+ }
334
+
335
+ [data-ui='description-list']
336
+ [data-part='description'][data-clamp][data-revealed]
337
+ [data-part='value'] {
338
+ -webkit-line-clamp: none;
339
+ display: block;
340
+ overflow: visible;
341
+ }
342
+
343
+ /**
344
+ * A value that is missing, in one of two forms.
345
+ *
346
+ * With words, it is those words: a consumer who writes "Not set yet" means a
347
+ * reader to see it, and a row that says what it is missing is worth more than
348
+ * a mark that says only *something*.
349
+ *
350
+ * Without them it is an em dash — `—`, U+2014 — and the accompanying sentence
351
+ * is read rather than shown, because a panel of twelve empty rows saying "Not
352
+ * provided" twelve times is noise, and the mark is what a reader scans past.
353
+ *
354
+ * The mark was a drawn rule of two pixels until DL2: geometry that answered
355
+ * to no font, sitting on a line of text as a bar the reader has no name for,
356
+ * where an em dash is what a table has used for a missing value since tables
357
+ * were set in lead. It is a character, so it is content and both bindings
358
+ * write it — the stylesheet generates no text, which
359
+ * `description-list.styles.test.mjs` holds for the whole family — and the
360
+ * only thing left here is the ink it is drawn in, one step down from the
361
+ * value it stands in for.
362
+ *
363
+ * `—` and never `-`: a hyphen is a word joiner, half the width, and it sits
364
+ * at a different height.
365
+ */
366
+ [data-ui='description-list'] [data-part='placeholder'] {
367
+ color: var(--_placeholder-ink);
368
+ }
369
+
370
+ /* ── The controls ──────────────────────────────────────────────────── */
371
+
372
+ [data-ui='description-list'] :is([data-part='copy'], [data-part='toggle']) {
373
+ appearance: none;
374
+ background: none;
375
+ border: 0;
376
+ border-radius: var(--slotted-description-list-radius, var(--slotted-control-radius, 4px));
377
+ cursor: pointer;
378
+ font: inherit;
379
+ transition:
380
+ color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing),
381
+ background-color var(--slotted-control-transition-duration)
382
+ var(--slotted-control-transition-easing);
383
+ }
384
+
385
+ [data-ui='description-list'] :is([data-part='copy'], [data-part='toggle']):focus-visible {
386
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
387
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
388
+ }
389
+
390
+ /**
391
+ * The copy control is an icon on the value's own line, and its hit area is
392
+ * larger than the mark it draws: padding takes the box to the WCAG minimum of
393
+ * twenty-four pixels and an equal negative margin gives the space back to the
394
+ * line, so the row keeps its rhythm and the target keeps its size.
395
+ */
396
+ [data-ui='description-list'] [data-part='copy'] {
397
+ --slotted-icon-size: var(--_glyph);
398
+ align-items: center;
399
+ block-size: var(--slotted-target-min, 24px);
400
+ color: var(--_control-ink);
401
+ display: inline-flex;
402
+ grid-column: 2;
403
+ inline-size: var(--slotted-target-min, 24px);
404
+ justify-content: center;
405
+ /**
406
+ * Only the block axis gives its padding back. An inline negative margin
407
+ * pulled the control's box under the last word of the value, and the focus
408
+ * ring — which is drawn around the box and not around the mark — was then
409
+ * struck through the text it belonged beside.
410
+ */
411
+ margin-block: calc(var(--_hit) * -1);
412
+ padding: var(--_hit);
413
+ }
414
+
415
+ [data-ui='description-list'] [data-part='copy']:enabled:not([data-complete]):hover {
416
+ background-color: var(
417
+ --slotted-description-list-control-surface-hover,
418
+ var(--slotted-tone-secondary-subtle-hover, ButtonFace)
419
+ );
420
+ color: var(--_control-ink-hover);
421
+ }
422
+
423
+ [data-ui='description-list'] [data-part='copy']:enabled:not([data-complete]):active {
424
+ background-color: var(
425
+ --slotted-description-list-control-surface-active,
426
+ var(--slotted-tone-secondary-subtle-active, ButtonFace)
427
+ );
428
+ }
429
+
430
+ /**
431
+ * A copy that finished. The mark changes as well as the colour — the binding
432
+ * draws the check `Glyph` in place of the copy one — because a green
433
+ * clipboard says nothing to a reader who cannot see the green, and the
434
+ * control returns to rest on its own, so nothing is left claiming a state
435
+ * that has passed.
436
+ */
437
+ [data-ui='description-list'] [data-part='copy'][data-complete] {
438
+ color: var(--_control-ink-done);
439
+ }
440
+
441
+ /* On a finger the target is the comfortable size in both axes and the box
442
+ is the one a mouse sees: a transparent `::before` centred on the control
443
+ reaches 44 pixels, and the ground and the ring stay square. The row keeps
444
+ its rhythm, because the halo takes no room. */
445
+ @media (pointer: coarse) {
446
+ [data-ui='description-list'] [data-part='copy'] {
447
+ position: relative;
448
+ }
449
+
450
+ [data-ui='description-list'] [data-part='copy']::before {
451
+ content: '';
452
+ inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
453
+ position: absolute;
454
+ }
455
+ }
456
+
457
+ /**
458
+ * The control that reveals the rest of a clamped value. It reads as a link
459
+ * rather than as a button because what it does is take the reader further
460
+ * into the text, and it carries the chevron every disclosure in this library
461
+ * carries — the `Glyph` the binding draws after the words, turned, not
462
+ * swapped, so the eye follows one mark rather than catching two.
463
+ */
464
+ [data-ui='description-list'] [data-part='toggle'] {
465
+ --slotted-icon-size: var(--_glyph);
466
+ align-items: center;
467
+ color: var(--_link-ink);
468
+ column-gap: var(--slotted-space-2, 0.25rem);
469
+ display: inline-flex;
470
+ grid-column: 1 / -1;
471
+ justify-self: start;
472
+ min-block-size: var(--slotted-target-min, 24px);
473
+ padding-inline: 0;
474
+ }
475
+
476
+ [data-ui='description-list'] [data-part='toggle'] > [data-ui='icon'] {
477
+ rotate: 0deg;
478
+ transition: rotate var(--slotted-control-transition-duration)
479
+ var(--slotted-control-transition-easing);
480
+ }
481
+
482
+ [data-ui='description-list'] [data-revealed] [data-part='toggle'] > [data-ui='icon'] {
483
+ rotate: 180deg;
484
+ }
485
+
486
+ [data-ui='description-list'] [data-part='toggle']:enabled:hover {
487
+ text-decoration-line: underline;
488
+ text-underline-offset: var(--slotted-description-list-underline-offset, 0.2em);
489
+ }
490
+
491
+ [data-ui='description-list'] [data-part='toggle']:enabled:active {
492
+ color: var(--_control-ink-hover);
493
+ }
494
+
495
+ /* ── The row's own action ──────────────────────────────────────────── */
496
+
497
+ [data-ui='description-list'] [data-part='action'] {
498
+ align-self: start;
499
+ grid-column: var(--_action-col);
500
+ grid-row: var(--_action-row);
501
+ justify-self: end;
502
+ margin: 0;
503
+ white-space: nowrap;
504
+ }
505
+
506
+ /* ── plain ─────────────────────────────────────────────────────────── */
507
+
508
+ /**
509
+ * Nothing between pairs but the distance between them, which is the whole of
510
+ * this variant. It is the form that belongs inside a card, where the card
511
+ * already draws the box and a second frame would be two.
512
+ */
513
+ [data-ui='description-list'][data-variant='plain'] [data-part='list'] {
514
+ row-gap: var(--_row-gap);
515
+ }
516
+
517
+ /* ── ruled ─────────────────────────────────────────────────────────── */
518
+
519
+ /**
520
+ * A rule under every pair, including the last — which is GOV.UK's own summary
521
+ * list, and reads as a finished list rather than as one that stopped. It is
522
+ * also the only form of the rule that survives a pair spanning two columns,
523
+ * because it needs to know nothing about which row a pair is in.
524
+ */
525
+ [data-ui='description-list'][data-variant='ruled'] [data-part='list'] {
526
+ row-gap: 0;
527
+ }
528
+
529
+ [data-ui='description-list'][data-variant='ruled'] [data-part='item'] {
530
+ border-block-end: var(--slotted-border-width-thin, 1px) solid var(--_rule);
531
+ padding-block: var(--_pad-block);
532
+ }
533
+
534
+ /* ── framed ────────────────────────────────────────────────────────── */
535
+
536
+ /**
537
+ * The specification table: an outer frame, a hairline between rows, and the
538
+ * term cell tinted so the two columns read as two kinds of thing. Ant Design
539
+ * calls it `bordered` and Carbon draws the same rules; here the frame is the
540
+ * family's and the surface underneath is the theme's.
541
+ */
542
+ [data-ui='description-list'][data-variant='framed'] [data-part='list'] {
543
+ background-color: var(--_surface);
544
+ border: var(--slotted-border-width-thin, 1px) solid var(--_rule);
545
+ border-radius: var(--slotted-description-list-frame-radius, var(--slotted-radius-md, 6px));
546
+ column-gap: 0;
547
+ /* The tinted term cell would otherwise square off the rounded corners. */
548
+ overflow: clip;
549
+ row-gap: 0;
550
+ }
551
+
552
+ [data-ui='description-list'][data-variant='framed'] [data-part='item'] {
553
+ border-block-start: var(--slotted-border-width-thin, 1px) solid var(--_rule);
554
+ column-gap: 0;
555
+ }
556
+
557
+ [data-ui='description-list'][data-variant='framed'][data-columns='1']
558
+ [data-part='item']:first-child,
559
+ [data-ui='description-list'][data-variant='framed'][data-columns='2']
560
+ [data-part='item']:nth-child(-n + 2),
561
+ [data-ui='description-list'][data-variant='framed'][data-columns='3']
562
+ [data-part='item']:nth-child(-n + 3) {
563
+ border-block-start-width: 0;
564
+ }
565
+
566
+ [data-ui='description-list'][data-variant='framed']
567
+ :is([data-part='term'], [data-part='description'], [data-part='action']) {
568
+ padding-block: var(--_pad-block);
569
+ padding-inline: var(--_pad-inline);
570
+ }
571
+
572
+ [data-ui='description-list'][data-variant='framed'] [data-part='term'] {
573
+ background-color: var(--_term-surface);
574
+ border-inline-end: var(--slotted-border-width-thin, 1px) solid var(--_rule);
575
+ }
576
+
577
+ [data-ui='description-list'][data-variant='framed'][data-layout='stack'] [data-part='term'] {
578
+ /* Stacked, the term is a bar above its value rather than a cell beside it,
579
+ and a rule on its inline edge would point at nothing. */
580
+ border-inline-end: 0;
581
+ }
582
+
583
+ /* ── The container answers its own width ───────────────────────────── */
584
+
585
+ /**
586
+ * The count collapses before the arrangement does. A two-column row list at
587
+ * thirty rem has fifteen rem for each pair, of which the term may take
588
+ * fourteen, and the value would break one word to a line — so the second
589
+ * column goes first and the single-column row form gets the whole width
590
+ * before it gives up on the row.
591
+ *
592
+ * The breakpoints are literals because a container condition cannot read a
593
+ * custom property, which rule 4 of `docs/token-foundation.md` states.
594
+ */
595
+ /**
596
+ * A span is stated in tracks, so it collapses with the count that produced
597
+ * it. A pair asking for two columns of a list that now has one spans past the
598
+ * last track, and grid answers by inventing the tracks it was asked for: the
599
+ * list quietly grew two implicit columns and went on drawing two pairs to a
600
+ * row at every width. The picture said nothing — it was a correct rendering
601
+ * of a four-track grid.
602
+ */
603
+ @container slotted-description-list (max-width: 48rem) {
604
+ [data-ui='description-list'][data-columns='3'] [data-part='list'] {
605
+ --_cols: repeat(2, var(--_pair));
606
+ --_span-3: var(--_span-2);
607
+ }
608
+ }
609
+
610
+ @container slotted-description-list (max-width: 34rem) {
611
+ [data-ui='description-list'][data-columns='2'] [data-part='list'],
612
+ [data-ui='description-list'][data-columns='3'] [data-part='list'] {
613
+ --_cols: var(--_pair);
614
+ --_span-2: var(--_span-1);
615
+ --_span-3: var(--_span-1);
616
+ }
617
+
618
+ /**
619
+ * A list whose terms carry hints gives up the row eight rem earlier than
620
+ * one whose terms do not. A hint is a sentence under a label, and a label
621
+ * column wide enough to hold one leaves a four-hundred-pixel panel with a
622
+ * value column narrower than the label — which is the arrangement inverted
623
+ * rather than compressed. The declarations are the ones below, at
624
+ * twenty-six rem, and they are written twice because two container
625
+ * conditions cannot share one rule.
626
+ */
627
+ [data-ui='description-list'][data-layout='row'] [data-part='list']:has([data-part='hint']) {
628
+ --_pair: minmax(0, 1fr);
629
+ --_term-floor: 0px;
630
+ --_span-1: 1;
631
+ --_span-2: 1;
632
+ --_span-3: 1;
633
+ --_item-cols: minmax(0, 1fr);
634
+ --_desc-col: 1 / -1;
635
+ --_desc-row: 2;
636
+ --_action-col: -1 / -2;
637
+ --_action-row: 1;
638
+ }
639
+
640
+ [data-ui='description-list'][data-layout='row']
641
+ [data-part='list']:has([data-part='hint']):has([data-part='action']) {
642
+ --_item-cols: minmax(0, 1fr) auto;
643
+ }
644
+
645
+ [data-ui='description-list'][data-variant='framed'][data-layout='row']
646
+ [data-part='list']:has([data-part='hint'])
647
+ [data-part='term'] {
648
+ border-inline-end: 0;
649
+ }
650
+ }
651
+
652
+ @container slotted-description-list (max-width: 26rem) {
653
+ [data-ui='description-list'][data-layout='row'] [data-part='list'] {
654
+ --_pair: minmax(0, 1fr);
655
+ --_term-floor: 0px;
656
+ --_span-1: 1;
657
+ --_span-2: 1;
658
+ --_span-3: 1;
659
+ --_item-cols: minmax(0, 1fr);
660
+ --_desc-col: 1 / -1;
661
+ --_desc-row: 2;
662
+ --_action-col: -1 / -2;
663
+ --_action-row: 1;
664
+ }
665
+
666
+ [data-ui='description-list'][data-layout='row'] [data-part='list']:has([data-part='action']) {
667
+ --_item-cols: minmax(0, 1fr) auto;
668
+ --_desc-col: 1 / -1;
669
+ }
670
+
671
+ [data-ui='description-list'][data-variant='framed'][data-layout='row'] [data-part='term'] {
672
+ border-inline-end: 0;
673
+ }
674
+ }
675
+ }