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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/package.json +276 -3
  4. package/src/accordion/accordion.css +96 -0
  5. package/src/accordion/accordion.tokens.json +14 -0
  6. package/src/action-bar/action-bar.css +455 -0
  7. package/src/action-bar/action-bar.tokens.json +50 -0
  8. package/src/action-sheet/action-sheet.css +462 -0
  9. package/src/action-sheet/action-sheet.tokens.json +59 -0
  10. package/src/alert/alert.css +764 -0
  11. package/src/alert/alert.tokens.json +77 -0
  12. package/src/app-shell/app-shell.css +1899 -0
  13. package/src/app-shell/app-shell.tokens.json +88 -0
  14. package/src/aspect-ratio/aspect-ratio.css +131 -0
  15. package/src/aspect-ratio/aspect-ratio.tokens.json +1 -0
  16. package/src/attachment/attachment.css +906 -0
  17. package/src/attachment/attachment.tokens.json +85 -0
  18. package/src/avatar/avatar.css +598 -0
  19. package/src/avatar/avatar.tokens.json +64 -0
  20. package/src/avatar-group/avatar-group.css +268 -0
  21. package/src/avatar-group/avatar-group.tokens.json +16 -0
  22. package/src/badge/badge.css +462 -0
  23. package/src/badge/badge.tokens.json +58 -0
  24. package/src/breadcrumb/breadcrumb.css +441 -0
  25. package/src/breadcrumb/breadcrumb.tokens.json +50 -0
  26. package/src/button/button.css +754 -0
  27. package/src/button/button.tokens.json +72 -0
  28. package/src/button-group/button-group.css +455 -0
  29. package/src/button-group/button-group.tokens.json +11 -0
  30. package/src/calendar/calendar.css +846 -0
  31. package/src/calendar/calendar.tokens.json +67 -0
  32. package/src/card/card.css +602 -0
  33. package/src/card/card.tokens.json +68 -0
  34. package/src/carousel/carousel.css +860 -0
  35. package/src/carousel/carousel.tokens.json +62 -0
  36. package/src/cascader/cascader.css +1320 -0
  37. package/src/cascader/cascader.tokens.json +103 -0
  38. package/src/chart/chart.css +1473 -0
  39. package/src/chart/chart.tokens.json +107 -0
  40. package/src/checkbox/checkbox.css +1011 -0
  41. package/src/checkbox/checkbox.tokens.json +102 -0
  42. package/src/checkbox-group/checkbox-group.css +70 -0
  43. package/src/checkbox-group/checkbox-group.tokens.json +6 -0
  44. package/src/code-block/code-block.css +555 -0
  45. package/src/code-block/code-block.tokens.json +69 -0
  46. package/src/collapsible/collapsible.css +546 -0
  47. package/src/collapsible/collapsible.tokens.json +55 -0
  48. package/src/color-picker/color-picker.css +607 -0
  49. package/src/color-picker/color-picker.tokens.json +58 -0
  50. package/src/column-manager/column-manager.css +452 -0
  51. package/src/column-manager/column-manager.tokens.json +43 -0
  52. package/src/combobox/combobox.css +1048 -0
  53. package/src/combobox/combobox.tokens.json +112 -0
  54. package/src/command-palette/command-palette.css +1000 -0
  55. package/src/command-palette/command-palette.tokens.json +75 -0
  56. package/src/container/container.css +198 -0
  57. package/src/container/container.tokens.json +18 -0
  58. package/src/context-menu/context-menu.css +104 -0
  59. package/src/context-menu/context-menu.tokens.json +11 -0
  60. package/src/currency-field/currency-field.css +787 -0
  61. package/src/currency-field/currency-field.tokens.json +80 -0
  62. package/src/dashboard-grid/dashboard-grid.css +748 -0
  63. package/src/dashboard-grid/dashboard-grid.tokens.json +67 -0
  64. package/src/data-grid/data-grid.css +2484 -0
  65. package/src/data-grid/data-grid.tokens.json +100 -0
  66. package/src/data-list/data-list.css +455 -0
  67. package/src/data-list/data-list.tokens.json +35 -0
  68. package/src/date-field/date-field.css +560 -0
  69. package/src/date-field/date-field.tokens.json +80 -0
  70. package/src/date-picker/date-picker.css +420 -0
  71. package/src/date-picker/date-picker.tokens.json +49 -0
  72. package/src/date-range-picker/date-range-picker.css +983 -0
  73. package/src/date-range-picker/date-range-picker.tokens.json +109 -0
  74. package/src/datetime-field/datetime-field.css +850 -0
  75. package/src/datetime-field/datetime-field.tokens.json +91 -0
  76. package/src/datetime-picker/datetime-picker.css +843 -0
  77. package/src/datetime-picker/datetime-picker.tokens.json +78 -0
  78. package/src/datetime-range-picker/datetime-range-picker.css +1375 -0
  79. package/src/datetime-range-picker/datetime-range-picker.tokens.json +135 -0
  80. package/src/description-list/description-list.css +675 -0
  81. package/src/description-list/description-list.tokens.json +66 -0
  82. package/src/detail-panel/detail-panel.css +329 -0
  83. package/src/detail-panel/detail-panel.tokens.json +33 -0
  84. package/src/dialog/dialog.css +968 -0
  85. package/src/dialog/dialog.tokens.json +66 -0
  86. package/src/divider/divider.css +131 -0
  87. package/src/divider/divider.tokens.json +18 -0
  88. package/src/drawer/drawer.css +1303 -0
  89. package/src/drawer/drawer.tokens.json +75 -0
  90. package/src/entity-picker/entity-picker.css +1367 -0
  91. package/src/entity-picker/entity-picker.tokens.json +118 -0
  92. package/src/event-calendar/event-calendar.css +2148 -0
  93. package/src/event-calendar/event-calendar.tokens.json +87 -0
  94. package/src/field/field.css +707 -0
  95. package/src/field/field.tokens.json +58 -0
  96. package/src/field-group/field-group.css +226 -0
  97. package/src/field-group/field-group.tokens.json +33 -0
  98. package/src/filter-bar/filter-bar.css +1306 -0
  99. package/src/filter-bar/filter-bar.tokens.json +78 -0
  100. package/src/form/form.css +218 -0
  101. package/src/form/form.tokens.json +32 -0
  102. package/src/fullscreen/fullscreen.css +376 -0
  103. package/src/fullscreen/fullscreen.tokens.json +50 -0
  104. package/src/grid/grid.css +173 -0
  105. package/src/grid/grid.tokens.json +20 -0
  106. package/src/highlight/highlight.css +135 -0
  107. package/src/highlight/highlight.tokens.json +16 -0
  108. package/src/hover-card/hover-card.css +93 -0
  109. package/src/hover-card/hover-card.tokens.json +17 -0
  110. package/src/icon/icon.css +136 -0
  111. package/src/icon/icon.tokens.json +14 -0
  112. package/src/image/image.css +449 -0
  113. package/src/image/image.tokens.json +27 -0
  114. package/src/import-export-center/import-export-center.css +1175 -0
  115. package/src/import-export-center/import-export-center.tokens.json +84 -0
  116. package/src/inline/inline.css +149 -0
  117. package/src/inline/inline.tokens.json +14 -0
  118. package/src/inline-message/inline-message.css +396 -0
  119. package/src/inline-message/inline-message.tokens.json +19 -0
  120. package/src/kbd/kbd.css +490 -0
  121. package/src/kbd/kbd.tokens.json +40 -0
  122. package/src/link/link.css +237 -0
  123. package/src/link/link.tokens.json +25 -0
  124. package/src/list/list.css +240 -0
  125. package/src/list/list.tokens.json +42 -0
  126. package/src/list-item/list-item.css +937 -0
  127. package/src/list-item/list-item.tokens.json +114 -0
  128. package/src/listbox/listbox.css +674 -0
  129. package/src/listbox/listbox.tokens.json +72 -0
  130. package/src/loading-overlay/loading-overlay.css +730 -0
  131. package/src/loading-overlay/loading-overlay.tokens.json +48 -0
  132. package/src/markdown/markdown.css +168 -0
  133. package/src/markdown/markdown.tokens.json +18 -0
  134. package/src/menu/menu.css +817 -0
  135. package/src/menu/menu.tokens.json +78 -0
  136. package/src/menubar/menubar.css +170 -0
  137. package/src/menubar/menubar.tokens.json +32 -0
  138. package/src/message/message.css +1453 -0
  139. package/src/message/message.tokens.json +85 -0
  140. package/src/message-scroller/message-scroller.css +371 -0
  141. package/src/message-scroller/message-scroller.tokens.json +47 -0
  142. package/src/multi-select/multi-select.css +1427 -0
  143. package/src/multi-select/multi-select.tokens.json +114 -0
  144. package/src/navigation-menu/navigation-menu.css +1029 -0
  145. package/src/navigation-menu/navigation-menu.tokens.json +70 -0
  146. package/src/notification-center/notification-center.css +856 -0
  147. package/src/notification-center/notification-center.tokens.json +84 -0
  148. package/src/number-field/number-field.css +794 -0
  149. package/src/number-field/number-field.tokens.json +80 -0
  150. package/src/otp-input/otp-input.css +525 -0
  151. package/src/otp-input/otp-input.tokens.json +69 -0
  152. package/src/page/page.css +179 -0
  153. package/src/page/page.tokens.json +20 -0
  154. package/src/page-header/page-header.css +1181 -0
  155. package/src/page-header/page-header.tokens.json +71 -0
  156. package/src/pagination/pagination.css +500 -0
  157. package/src/pagination/pagination.tokens.json +56 -0
  158. package/src/popover/popover.css +526 -0
  159. package/src/popover/popover.tokens.json +60 -0
  160. package/src/progress-indicator/progress-indicator.css +1584 -0
  161. package/src/progress-indicator/progress-indicator.tokens.json +50 -0
  162. package/src/prompt-composer/prompt-composer.css +680 -0
  163. package/src/prompt-composer/prompt-composer.tokens.json +99 -0
  164. package/src/prose/prose.css +733 -0
  165. package/src/prose/prose.tokens.json +79 -0
  166. package/src/radio-group/radio-group.css +778 -0
  167. package/src/radio-group/radio-group.tokens.json +103 -0
  168. package/src/rating/rating.css +1071 -0
  169. package/src/rating/rating.tokens.json +88 -0
  170. package/src/result-state/result-state.css +980 -0
  171. package/src/result-state/result-state.tokens.json +63 -0
  172. package/src/runtime-properties.mjs +321 -0
  173. package/src/saved-views/saved-views.css +394 -0
  174. package/src/saved-views/saved-views.tokens.json +41 -0
  175. package/src/scroll-area/scroll-area.css +481 -0
  176. package/src/scroll-area/scroll-area.tokens.json +15 -0
  177. package/src/section/section.css +177 -0
  178. package/src/section/section.tokens.json +39 -0
  179. package/src/segmented-control/segmented-control.css +564 -0
  180. package/src/segmented-control/segmented-control.tokens.json +67 -0
  181. package/src/select/select.css +1593 -0
  182. package/src/select/select.tokens.json +110 -0
  183. package/src/side-navigation/side-navigation.css +1096 -0
  184. package/src/side-navigation/side-navigation.tokens.json +87 -0
  185. package/src/skeleton/skeleton.css +431 -0
  186. package/src/skeleton/skeleton.tokens.json +29 -0
  187. package/src/slider/slider.css +792 -0
  188. package/src/slider/slider.tokens.json +75 -0
  189. package/src/sparkline/sparkline.css +282 -0
  190. package/src/sparkline/sparkline.tokens.json +45 -0
  191. package/src/spinner/spinner.css +224 -0
  192. package/src/spinner/spinner.tokens.json +8 -0
  193. package/src/split-button/split-button.css +253 -0
  194. package/src/split-button/split-button.tokens.json +12 -0
  195. package/src/splitter/splitter.css +336 -0
  196. package/src/splitter/splitter.tokens.json +24 -0
  197. package/src/stack/stack.css +128 -0
  198. package/src/stack/stack.tokens.json +14 -0
  199. package/src/stat-card/stat-card.css +641 -0
  200. package/src/stat-card/stat-card.tokens.json +95 -0
  201. package/src/status-indicator/status-indicator.css +481 -0
  202. package/src/status-indicator/status-indicator.tokens.json +38 -0
  203. package/src/stepper/stepper.css +629 -0
  204. package/src/stepper/stepper.tokens.json +72 -0
  205. package/src/switch/switch.css +703 -0
  206. package/src/switch/switch.tokens.json +75 -0
  207. package/src/table/table.css +1482 -0
  208. package/src/table/table.tokens.json +69 -0
  209. package/src/table-of-contents/table-of-contents.css +533 -0
  210. package/src/table-of-contents/table-of-contents.tokens.json +53 -0
  211. package/src/tabs/tabs.css +998 -0
  212. package/src/tabs/tabs.tokens.json +82 -0
  213. package/src/tag/tag.css +768 -0
  214. package/src/tag/tag.tokens.json +85 -0
  215. package/src/tags-input/tags-input.css +757 -0
  216. package/src/tags-input/tags-input.tokens.json +84 -0
  217. package/src/text-field/text-field.css +900 -0
  218. package/src/text-field/text-field.tokens.json +87 -0
  219. package/src/textarea/textarea.css +365 -0
  220. package/src/textarea/textarea.tokens.json +59 -0
  221. package/src/time-field/time-field.css +719 -0
  222. package/src/time-field/time-field.tokens.json +86 -0
  223. package/src/time-picker/time-picker.css +665 -0
  224. package/src/time-picker/time-picker.tokens.json +66 -0
  225. package/src/time-range-picker/time-range-picker.css +1287 -0
  226. package/src/time-range-picker/time-range-picker.tokens.json +134 -0
  227. package/src/timeline/timeline.css +1596 -0
  228. package/src/timeline/timeline.tokens.json +96 -0
  229. package/src/toast/toast.css +943 -0
  230. package/src/toast/toast.tokens.json +90 -0
  231. package/src/toggle/toggle.css +290 -0
  232. package/src/toggle/toggle.tokens.json +54 -0
  233. package/src/toggle-group/toggle-group.css +463 -0
  234. package/src/toggle-group/toggle-group.tokens.json +54 -0
  235. package/src/toolbar/toolbar.css +434 -0
  236. package/src/toolbar/toolbar.tokens.json +49 -0
  237. package/src/tooltip/tooltip.css +368 -0
  238. package/src/tooltip/tooltip.tokens.json +39 -0
  239. package/src/top-navigation/top-navigation.css +1287 -0
  240. package/src/top-navigation/top-navigation.tokens.json +91 -0
  241. package/src/tour/tour.css +680 -0
  242. package/src/tour/tour.tokens.json +67 -0
  243. package/src/transfer/transfer.css +571 -0
  244. package/src/transfer/transfer.tokens.json +49 -0
  245. package/src/tree/tree.css +1000 -0
  246. package/src/tree/tree.tokens.json +80 -0
  247. package/src/typography/typography.css +211 -0
  248. package/src/typography/typography.tokens.json +31 -0
  249. package/src/upload/upload.css +1706 -0
  250. package/src/upload/upload.tokens.json +123 -0
  251. package/src/visually-hidden/visually-hidden.css +52 -0
  252. package/src/visually-hidden/visually-hidden.tokens.json +1 -0
  253. package/src/wizard/wizard.css +740 -0
  254. package/src/wizard/wizard.tokens.json +63 -0
@@ -0,0 +1,67 @@
1
+ [
2
+ "--slotted-border-subtle",
3
+ "--slotted-border-width-thin",
4
+ "--slotted-control-gap-md",
5
+ "--slotted-control-height-sm",
6
+ "--slotted-control-padding-inline-sm",
7
+ "--slotted-control-radius",
8
+ "--slotted-control-transition-duration",
9
+ "--slotted-control-transition-easing",
10
+ "--slotted-duration-long",
11
+ "--slotted-duration-short",
12
+ "--slotted-easing-exit",
13
+ "--slotted-easing-standard",
14
+ "--slotted-focus-ring-color",
15
+ "--slotted-focus-ring-width",
16
+ "--slotted-font-family-heading",
17
+ "--slotted-font-family-sans",
18
+ "--slotted-font-size-lg",
19
+ "--slotted-font-size-md",
20
+ "--slotted-font-size-sm",
21
+ "--slotted-font-size-xl",
22
+ "--slotted-font-size-xs",
23
+ "--slotted-font-weight-medium",
24
+ "--slotted-font-weight-semibold",
25
+ "--slotted-line-height-lg",
26
+ "--slotted-line-height-md",
27
+ "--slotted-line-height-xs",
28
+ "--slotted-radius-lg",
29
+ "--slotted-radius-md",
30
+ "--slotted-radius-sm",
31
+ "--slotted-radius-xs",
32
+ "--slotted-scrim",
33
+ "--slotted-shadow-lg",
34
+ "--slotted-space-2",
35
+ "--slotted-space-3",
36
+ "--slotted-space-4",
37
+ "--slotted-space-5",
38
+ "--slotted-space-6",
39
+ "--slotted-space-7",
40
+ "--slotted-surface-raised",
41
+ "--slotted-text",
42
+ "--slotted-text-muted",
43
+ "--slotted-tone-secondary-subtle-active",
44
+ "--slotted-tone-secondary-subtle-hover",
45
+ "--slotted-tour-arrow-size",
46
+ "--slotted-tour-arrow-tip-radius",
47
+ "--slotted-tour-border-color",
48
+ "--slotted-tour-gap",
49
+ "--slotted-tour-measure",
50
+ "--slotted-tour-measure-compact",
51
+ "--slotted-tour-measure-lg",
52
+ "--slotted-tour-measure-sm",
53
+ "--slotted-tour-padding-block",
54
+ "--slotted-tour-padding-block-lg",
55
+ "--slotted-tour-padding-block-sm",
56
+ "--slotted-tour-padding-inline",
57
+ "--slotted-tour-padding-inline-lg",
58
+ "--slotted-tour-padding-inline-sm",
59
+ "--slotted-tour-radius",
60
+ "--slotted-tour-scrim",
61
+ "--slotted-tour-shadow",
62
+ "--slotted-tour-spotlight-padding",
63
+ "--slotted-tour-spotlight-radius",
64
+ "--slotted-tour-surface",
65
+ "--slotted-tour-text",
66
+ "--slotted-z-index-overlay"
67
+ ]
@@ -0,0 +1,571 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * Two lists and the moves between them.
4
+ *
5
+ * root ▸ switch (steps only)
6
+ * body ▸ ┌ pane source ──────┐ actions ┌ pane target ──────┐
7
+ * │ pane-header │ Add › │ pane-header │
8
+ * │ search │ Add all »│ search │
9
+ * ├────────────────────┤ ├────────────────────┤
10
+ * │ list ▸ listbox │ ‹ Remove │ list ▸ listbox │
11
+ * │ drop-indicator │ « … │ │
12
+ * ├────────────────────┤ reorder ├────────────────────┤
13
+ * │ pane-footer │ ⌃ Up ⌄ │ pane-footer │
14
+ * └────────────────────┘ └────────────────────┘
15
+ *
16
+ * The listbox, the checkbox, the text field, the buttons and the switch are
17
+ * their families'. This sheet places them and draws what none of them owns:
18
+ * the pane's frame, the header's alignment with the listbox's check column,
19
+ * the chevrons on the moves, the drop line and the narrow layout. Every
20
+ * part is reached from the root with child combinators, because the
21
+ * composed families have parts named `label`, `root` and `empty` of their
22
+ * own and a descendant rule would restyle theirs.
23
+ *
24
+ * Density is answered through the control geometry: every inset here is a
25
+ * control's padding or gap at the family's size step, and the list is a
26
+ * number of control heights tall.
27
+ */
28
+ [data-ui='transfer'] {
29
+ --_text: var(--slotted-text, CanvasText);
30
+ --_muted: var(--slotted-text-muted, GrayText);
31
+ --_rule: var(--slotted-border-subtle, ButtonBorder);
32
+ --_edge: var(--slotted-control-border-color, ButtonBorder);
33
+ --_surface: var(--slotted-control-surface, Field);
34
+ --_shadow: var(--slotted-control-shadow, none);
35
+ --_radius: var(--slotted-radius-md, 6px);
36
+ --_pane-min: var(--slotted-transfer-pane-min-inline-size, 13rem);
37
+ --_gap: var(--slotted-space-5, 0.75rem);
38
+ --_rows: var(--slotted-transfer-rows, 8);
39
+ --_duration: var(--slotted-control-transition-duration);
40
+ --_easing: var(--slotted-control-transition-easing);
41
+
42
+ /* The step the family is at, restated per size below. */
43
+ --_option-height: var(--slotted-control-height-md, 34px);
44
+ --_option-inset: var(--slotted-control-padding-inline-md, 13px);
45
+ --_mark: var(--slotted-control-icon-size-md, 16px);
46
+ --_box: var(--slotted-selection-size-md, 16px);
47
+ --_font-size: var(--slotted-control-font-size-md, 13px);
48
+ /* The listbox's own inset, so the header lines up with its options. */
49
+ --_list-inset: var(--slotted-listbox-padding-block, var(--slotted-space-2, 0.25rem));
50
+
51
+ box-sizing: border-box;
52
+ color: var(--_text);
53
+ display: grid;
54
+ font-family: var(--slotted-font-family-sans, ui-sans-serif, system-ui, sans-serif);
55
+ font-size: var(--_font-size);
56
+ line-height: var(--slotted-line-height-md, 1.5);
57
+ min-inline-size: 0;
58
+ row-gap: var(--_gap);
59
+ text-align: start;
60
+ /* Below 36rem the body becomes steps; see the end of this sheet. */
61
+ container-name: transfer;
62
+ container-type: inline-size;
63
+ }
64
+
65
+ [data-ui='transfer'][data-size='sm'] {
66
+ --_option-height: var(--slotted-control-height-sm, 30px);
67
+ --_option-inset: var(--slotted-control-padding-inline-sm, 10px);
68
+ --_mark: var(--slotted-control-icon-size-sm, 14px);
69
+ --_box: var(--slotted-selection-size-sm, 14px);
70
+ --_font-size: var(--slotted-control-font-size-sm, 12px);
71
+ }
72
+
73
+ [data-ui='transfer'][data-size='lg'] {
74
+ --_option-height: var(--slotted-control-height-lg, 38px);
75
+ --_option-inset: var(--slotted-control-padding-inline-lg, 16px);
76
+ --_mark: var(--slotted-control-icon-size-lg, 18px);
77
+ --_box: var(--slotted-selection-size-lg, 18px);
78
+ --_font-size: var(--slotted-control-font-size-lg, 14px);
79
+ }
80
+
81
+ /* ── The switch, which only steps lay out ─────────────────────────────── */
82
+
83
+ [data-ui='transfer'] > [data-part='switch'] {
84
+ display: none;
85
+ }
86
+
87
+ [data-ui='transfer'] > [data-part='switch'] > [data-ui='segmented-control'] {
88
+ inline-size: 100%;
89
+ }
90
+
91
+ /* ── The body ─────────────────────────────────────────────────────────── */
92
+
93
+ /**
94
+ * Two panes of equal share and the actions between them at their own width.
95
+ * The actions centre on the panes' block size, which is the lists' middle
96
+ * give or take the header, and the eye reads them as belonging to both.
97
+ */
98
+ [data-ui='transfer'] > [data-part='body'] {
99
+ align-items: center;
100
+ column-gap: var(--_gap);
101
+ display: grid;
102
+ grid-template-columns:
103
+ minmax(var(--_pane-min), 1fr)
104
+ max-content
105
+ minmax(var(--_pane-min), 1fr);
106
+ min-inline-size: 0;
107
+ }
108
+
109
+ /* ── A pane ───────────────────────────────────────────────────────────── */
110
+
111
+ /**
112
+ * The frame a standalone listbox would draw, moved out one element so the
113
+ * header, the search and the footer stand inside it with the list. The
114
+ * listbox inside is `plain`: a box inside a box is what the variant exists
115
+ * to prevent.
116
+ */
117
+ [data-ui='transfer'] > [data-part='body'] > [data-part='pane'] {
118
+ align-self: stretch;
119
+ background: var(--_surface);
120
+ border: var(--slotted-border-width-thin, 1px) solid var(--_edge);
121
+ border-radius: var(--_radius);
122
+ box-shadow: var(--_shadow);
123
+ box-sizing: border-box;
124
+ display: grid;
125
+ grid-template-rows: auto auto minmax(0, 1fr) auto;
126
+ min-inline-size: 0;
127
+ /* A row's ground is square and would reach past the rounded corner. */
128
+ overflow: clip;
129
+ transition:
130
+ border-color var(--_duration) var(--_easing),
131
+ box-shadow var(--_duration) var(--_easing);
132
+ }
133
+
134
+ /**
135
+ * The header's start is the listbox's check column: the list's own inset,
136
+ * then the option's, less half of what the select-all box is wider than
137
+ * the check. The box then stands centred over the marks it selects.
138
+ */
139
+ [data-ui='transfer'] > [data-part='body'] > [data-part='pane'] > [data-part='pane-header'] {
140
+ align-items: center;
141
+ /* A stated step rather than the control gap: the box's focus ring is
142
+ drawn four pixels out, and at dense the control gap is four and six
143
+ pixels, so the ring touched the title. */
144
+ column-gap: var(--slotted-space-4, 0.5rem);
145
+ display: flex;
146
+ min-block-size: var(--_option-height);
147
+ padding-block: var(--slotted-space-3, 0.375rem);
148
+ padding-inline-end: calc(var(--_list-inset) + var(--_option-inset));
149
+ padding-inline-start: calc(
150
+ var(--_list-inset) + var(--_option-inset) - (var(--_box) - var(--_mark)) / 2
151
+ );
152
+ }
153
+
154
+ [data-ui='transfer']
155
+ > [data-part='body']
156
+ > [data-part='pane']
157
+ > [data-part='pane-header']
158
+ > [data-part='select-all'] {
159
+ display: inline-flex;
160
+ flex: none;
161
+ }
162
+
163
+ /* The box stands alone: its name is on the input, and the Angular binding's
164
+ empty label would otherwise keep the grid's gap after the box. */
165
+ [data-ui='transfer']
166
+ > [data-part='body']
167
+ > [data-part='pane']
168
+ > [data-part='pane-header']
169
+ > [data-part='select-all']
170
+ > [data-ui='checkbox'] {
171
+ column-gap: 0;
172
+ }
173
+
174
+ [data-ui='transfer']
175
+ > [data-part='body']
176
+ > [data-part='pane']
177
+ > [data-part='pane-header']
178
+ > [data-part='title'] {
179
+ color: var(--_text);
180
+ font-weight: var(--slotted-font-weight-semibold, 600);
181
+ min-inline-size: 0;
182
+ overflow-wrap: anywhere;
183
+ }
184
+
185
+ /**
186
+ * The count holds its line: a pane narrow enough to push it would wrap the
187
+ * title instead, and a figure that jumps as it counts is read as a change of
188
+ * meaning. Tabular figures keep "9 of 12" and "10 of 12" the same width.
189
+ */
190
+ [data-ui='transfer']
191
+ > [data-part='body']
192
+ > [data-part='pane']
193
+ > [data-part='pane-header']
194
+ > [data-part='count'] {
195
+ color: var(--_muted);
196
+ flex: none;
197
+ font-size: var(--slotted-font-size-xs, 0.75rem);
198
+ font-variant-numeric: tabular-nums;
199
+ line-height: var(--slotted-line-height-xs, 1.4);
200
+ margin-inline-start: auto;
201
+ white-space: nowrap;
202
+ }
203
+
204
+ [data-ui='transfer'] > [data-part='body'] > [data-part='pane'] > [data-part='search'] {
205
+ padding-block-end: var(--slotted-space-4, 0.5rem);
206
+ padding-inline: var(--slotted-space-4, 0.5rem);
207
+ }
208
+
209
+ [data-ui='transfer']
210
+ > [data-part='body']
211
+ > [data-part='pane']
212
+ > [data-part='search']
213
+ > [data-ui='text-field'] {
214
+ inline-size: 100%;
215
+ }
216
+
217
+ [data-ui='transfer']
218
+ > [data-part='body']
219
+ > [data-part='pane']
220
+ > [data-part='search']
221
+ [data-part='search-icon'] {
222
+ /* Holds the search `Glyph` the binding draws, at the icon size the text
223
+ field's start slot states. */
224
+ display: inline-flex;
225
+ flex: none;
226
+ }
227
+
228
+ /**
229
+ * The list is a stated number of options tall whatever it holds, so the two
230
+ * panes stand level when one is full and the other empty, and a move does
231
+ * not change the height of the page. The listbox fills it and scrolls
232
+ * inside it; its measure cap is lifted, because the pane is the measure.
233
+ */
234
+ [data-ui='transfer'] > [data-part='body'] > [data-part='pane'] > [data-part='list'] {
235
+ block-size: calc(var(--_rows) * var(--_option-height) + 2 * var(--_list-inset));
236
+ border-block-start: var(--slotted-border-width-thin, 1px) solid var(--_rule);
237
+ box-sizing: content-box;
238
+ min-block-size: 0;
239
+ position: relative;
240
+ }
241
+
242
+ [data-ui='transfer']
243
+ > [data-part='body']
244
+ > [data-part='pane']
245
+ > [data-part='list']
246
+ > [data-ui='listbox'] {
247
+ --slotted-listbox-measure: none;
248
+
249
+ block-size: 100%;
250
+ max-block-size: 100%;
251
+ }
252
+
253
+ /**
254
+ * An empty list says so in the middle of the space it would fill, rather
255
+ * than in a row at the top that reads as the first option.
256
+ */
257
+ [data-ui='transfer']
258
+ > [data-part='body']
259
+ > [data-part='pane']
260
+ > [data-part='list']
261
+ > [data-ui='listbox']:has(> [data-part='empty']) {
262
+ align-content: center;
263
+ }
264
+
265
+ [data-ui='transfer']
266
+ > [data-part='body']
267
+ > [data-part='pane']
268
+ > [data-part='list']
269
+ > [data-ui='listbox']
270
+ > [data-part='empty']
271
+ > [data-part='empty'] {
272
+ /* The mark above the words is the `Glyph` the binding draws: an empty tray,
273
+ or a failed search while a query is typed. */
274
+ --slotted-icon-size: var(--_mark);
275
+ display: grid;
276
+ justify-items: center;
277
+ row-gap: var(--slotted-space-3, 0.375rem);
278
+ }
279
+
280
+ /** An option the collection does not hold: the key, in the muted ink. */
281
+ [data-ui='transfer']
282
+ > [data-part='body']
283
+ > [data-part='pane']
284
+ > [data-part='list']
285
+ > [data-ui='listbox']
286
+ [data-part='option']:has(> [data-part='indicator'][data-unresolved]) {
287
+ color: var(--_muted);
288
+ font-family: var(--slotted-font-family-mono, ui-monospace, monospace);
289
+ }
290
+
291
+ /**
292
+ * Where a pointer drop would land: a line of no height between two options,
293
+ * so nothing moves while the reader aims. Its offset is measured by script,
294
+ * which is the one thing the stylesheet cannot know.
295
+ */
296
+ [data-ui='transfer']
297
+ > [data-part='body']
298
+ > [data-part='pane']
299
+ > [data-part='list']
300
+ > [data-part='drop-indicator'] {
301
+ block-size: 0;
302
+ inset-block-start: var(--_drop-offset, 0);
303
+ inset-inline: calc(var(--_list-inset) + var(--slotted-space-2, 0.25rem));
304
+ pointer-events: none;
305
+ position: absolute;
306
+ }
307
+
308
+ [data-ui='transfer']
309
+ > [data-part='body']
310
+ > [data-part='pane']
311
+ > [data-part='list']
312
+ > [data-part='drop-indicator']::before {
313
+ background-color: var(--slotted-tone-accent-solid);
314
+ block-size: var(--slotted-border-width-thick, 2px);
315
+ border-radius: var(--slotted-radius-full, 9999px);
316
+ content: '';
317
+ inset-block-start: calc(var(--slotted-border-width-thick, 2px) / -2);
318
+ inset-inline: 0;
319
+ position: absolute;
320
+ }
321
+
322
+ /* An option being carried is the ghost of itself where it came from. */
323
+ [data-ui='transfer']
324
+ > [data-part='body']
325
+ > [data-part='pane']
326
+ > [data-part='list']
327
+ > [data-ui='listbox']
328
+ [data-part='option']:has(> [data-part='indicator'][data-dragging]) {
329
+ opacity: 0.5;
330
+ }
331
+
332
+ /**
333
+ * The pane a drop would land in. The accent edge at 3:1 is the signal; the
334
+ * ring doubles it, so the edge reads at a glance without the pane moving.
335
+ */
336
+ [data-ui='transfer'] > [data-part='body'] > [data-part='pane'][data-drop-target] {
337
+ border-color: var(--slotted-tone-accent-border, Highlight);
338
+ box-shadow: 0 0 0 var(--slotted-border-width-thin, 1px)
339
+ var(--slotted-tone-accent-border, Highlight);
340
+ }
341
+
342
+ [data-ui='transfer'] > [data-part='body'] > [data-part='pane'] > [data-part='pane-footer'] {
343
+ border-block-start: var(--slotted-border-width-thin, 1px) solid var(--_rule);
344
+ color: var(--_muted);
345
+ font-size: var(--slotted-font-size-xs, 0.75rem);
346
+ line-height: var(--slotted-line-height-xs, 1.4);
347
+ padding-block: var(--slotted-space-4, 0.5rem);
348
+ padding-inline: calc(var(--_list-inset) + var(--_option-inset));
349
+ }
350
+
351
+ /* ── The pane's states ────────────────────────────────────────────────── */
352
+
353
+ [data-ui='transfer'][data-invalid] > [data-part='body'] > [data-part='pane'] {
354
+ --_edge: var(--slotted-tone-danger-border, Mark);
355
+ /* Width as well as colour (WCAG 1.4.1): in `high-contrast` the danger
356
+ border is the resting edge's black. An edge inside the border, so
357
+ nothing moves, in place of the resting lift — the one `text-field`
358
+ draws. */
359
+ --_invalid-edge-width: var(--slotted-control-invalid-edge-width, 1px);
360
+ --_shadow: inset 0 0 0 var(--_invalid-edge-width) var(--_edge);
361
+ }
362
+
363
+ [data-ui='transfer'][data-disabled] {
364
+ --_surface: var(--slotted-disabled-background, Canvas);
365
+ --_edge: var(--slotted-disabled-border, GrayText);
366
+ --_text: var(--slotted-disabled-foreground, GrayText);
367
+ --_muted: var(--slotted-disabled-foreground, GrayText);
368
+ --_shadow: none;
369
+ }
370
+
371
+ /* ── The actions ──────────────────────────────────────────────────────── */
372
+
373
+ /**
374
+ * One column of equal widths, so the four words line up as a list and the
375
+ * widest sets the rest. The two directions stand apart by more than the
376
+ * buttons inside each, which is how the eye tells "toward Chosen" from
377
+ * "toward Available" before reading either.
378
+ */
379
+ [data-ui='transfer'] > [data-part='body'] > [data-part='actions'] {
380
+ display: grid;
381
+ gap: var(--slotted-space-3, 0.375rem);
382
+ grid-auto-rows: auto;
383
+ min-inline-size: 0;
384
+ }
385
+
386
+ [data-ui='transfer'] > [data-part='body'] > [data-part='actions'] > [data-part='move-to-source'],
387
+ [data-ui='transfer'] > [data-part='body'] > [data-part='actions'] > [data-part='reorder'] {
388
+ margin-block-start: var(--slotted-space-4, 0.5rem);
389
+ }
390
+
391
+ [data-ui='transfer'] > [data-part='body'] > [data-part='actions'] > [data-ui='button'] {
392
+ inline-size: 100%;
393
+ }
394
+
395
+ [data-ui='transfer'] > [data-part='body'] > [data-part='actions'] > [data-part='reorder'] {
396
+ display: grid;
397
+ gap: var(--slotted-space-3, 0.375rem);
398
+ }
399
+
400
+ [data-ui='transfer']
401
+ > [data-part='body']
402
+ > [data-part='actions']
403
+ > [data-part='reorder']
404
+ > [data-ui='button'] {
405
+ inline-size: 100%;
406
+ }
407
+
408
+ /**
409
+ * The chevrons. A move toward the target carries its mark after the word,
410
+ * pointing where the items go; a move toward the source carries it before.
411
+ * The glyph is the `Glyph` the binding draws in the button's own start or
412
+ * end slot — one chevron for a selection, two for everything, a chevron
413
+ * down for a reorder — so the button family's slot geometry and inset decide
414
+ * its size and air. What is left here is which way the box points.
415
+ *
416
+ * Toward the source is the other way along the inline axis, and a
417
+ * right-to-left document turns both.
418
+ */
419
+ [data-ui='transfer']
420
+ > [data-part='body']
421
+ > [data-part='actions']
422
+ > :is([data-part='move-to-source'], [data-part='move-all-to-source'])
423
+ > [data-part='start']
424
+ > [data-ui='icon'],
425
+ [data-ui='transfer']:dir(rtl)
426
+ > [data-part='body']
427
+ > [data-part='actions']
428
+ > :is([data-part='move-to-target'], [data-part='move-all-to-target'])
429
+ > [data-part='end']
430
+ > [data-ui='icon'] {
431
+ scale: -1 1;
432
+ }
433
+
434
+ [data-ui='transfer']:dir(rtl)
435
+ > [data-part='body']
436
+ > [data-part='actions']
437
+ > :is([data-part='move-to-source'], [data-part='move-all-to-source'])
438
+ > [data-part='start']
439
+ > [data-ui='icon'] {
440
+ scale: 1 1;
441
+ }
442
+
443
+ [data-ui='transfer']
444
+ > [data-part='body']
445
+ > [data-part='actions']
446
+ > [data-part='reorder']
447
+ > [data-part='move-up']
448
+ > [data-part='start']
449
+ > [data-ui='icon'] {
450
+ scale: 1 -1;
451
+ }
452
+
453
+ /* ── Steps ────────────────────────────────────────────────────────────── */
454
+
455
+ /**
456
+ * One pane at a time, chosen by the switch. The body becomes one column, the
457
+ * pane the switch does not name leaves the layout, and the actions become a
458
+ * row of the current pane's two moves in the DOM's order: under the source,
459
+ * above the target. Moving the actions to one place for both would put them
460
+ * out of the tab order the reader walks.
461
+ *
462
+ * The rules are written twice, once for `layout="steps"` and once for
463
+ * `layout="auto"` under the container step, because a container condition
464
+ * cannot be a selector.
465
+ */
466
+ [data-ui='transfer'][data-layout='steps'] > [data-part='switch'] {
467
+ display: block;
468
+ }
469
+
470
+ [data-ui='transfer'][data-layout='steps'] > [data-part='body'] {
471
+ grid-template-columns: minmax(0, 1fr);
472
+ row-gap: var(--slotted-space-4, 0.5rem);
473
+ }
474
+
475
+ [data-ui='transfer'][data-layout='steps']
476
+ > [data-part='body']
477
+ > [data-part='pane']:not([data-current]) {
478
+ display: none;
479
+ }
480
+
481
+ [data-ui='transfer'][data-layout='steps'] > [data-part='body'] > [data-part='actions'] {
482
+ grid-template-columns: repeat(2, minmax(0, 1fr));
483
+ }
484
+
485
+ [data-ui='transfer'][data-layout='steps']
486
+ > [data-part='body']
487
+ > [data-part='actions']
488
+ > :is([data-part='move-to-source'], [data-part='reorder']) {
489
+ margin-block-start: 0;
490
+ }
491
+
492
+ [data-ui='transfer'][data-layout='steps'][data-pane='source']
493
+ > [data-part='body']
494
+ > [data-part='actions']
495
+ > :is([data-part='move-to-source'], [data-part='move-all-to-source'], [data-part='reorder']),
496
+ [data-ui='transfer'][data-layout='steps'][data-pane='target']
497
+ > [data-part='body']
498
+ > [data-part='actions']
499
+ > :is([data-part='move-to-target'], [data-part='move-all-to-target']) {
500
+ display: none;
501
+ }
502
+
503
+ [data-ui='transfer'][data-layout='steps']
504
+ > [data-part='body']
505
+ > [data-part='actions']
506
+ > [data-part='reorder'] {
507
+ grid-column: 1 / -1;
508
+ grid-template-columns: repeat(2, minmax(0, 1fr));
509
+ }
510
+
511
+ @container transfer (inline-size < 36rem) {
512
+ [data-ui='transfer'][data-layout='auto'] > [data-part='switch'] {
513
+ display: block;
514
+ }
515
+
516
+ [data-ui='transfer'][data-layout='auto'] > [data-part='body'] {
517
+ grid-template-columns: minmax(0, 1fr);
518
+ row-gap: var(--slotted-space-4, 0.5rem);
519
+ }
520
+
521
+ [data-ui='transfer'][data-layout='auto']
522
+ > [data-part='body']
523
+ > [data-part='pane']:not([data-current]) {
524
+ display: none;
525
+ }
526
+
527
+ [data-ui='transfer'][data-layout='auto'] > [data-part='body'] > [data-part='actions'] {
528
+ grid-template-columns: repeat(2, minmax(0, 1fr));
529
+ }
530
+
531
+ [data-ui='transfer'][data-layout='auto']
532
+ > [data-part='body']
533
+ > [data-part='actions']
534
+ > :is([data-part='move-to-source'], [data-part='reorder']) {
535
+ margin-block-start: 0;
536
+ }
537
+
538
+ [data-ui='transfer'][data-layout='auto'][data-pane='source']
539
+ > [data-part='body']
540
+ > [data-part='actions']
541
+ > :is([data-part='move-to-source'], [data-part='move-all-to-source'], [data-part='reorder']),
542
+ [data-ui='transfer'][data-layout='auto'][data-pane='target']
543
+ > [data-part='body']
544
+ > [data-part='actions']
545
+ > :is([data-part='move-to-target'], [data-part='move-all-to-target']) {
546
+ display: none;
547
+ }
548
+
549
+ [data-ui='transfer'][data-layout='auto']
550
+ > [data-part='body']
551
+ > [data-part='actions']
552
+ > [data-part='reorder'] {
553
+ grid-column: 1 / -1;
554
+ grid-template-columns: repeat(2, minmax(0, 1fr));
555
+ }
556
+ }
557
+
558
+ /*
559
+ * Forced colours remove every box shadow, and the edge with them. The width
560
+ * comes back as an outline inside the border; a pane
561
+ * draws no focus ring of its own.
562
+ */
563
+ @media (forced-colors: active) {
564
+ [data-ui='transfer'][data-invalid] > [data-part='body'] > [data-part='pane'] {
565
+ outline: var(--_invalid-edge-width) solid CanvasText;
566
+ outline-offset: calc(
567
+ -1 * (var(--slotted-border-width-thin, 1px) + var(--_invalid-edge-width))
568
+ );
569
+ }
570
+ }
571
+ }
@@ -0,0 +1,49 @@
1
+ [
2
+ "--slotted-border-subtle",
3
+ "--slotted-border-width-thick",
4
+ "--slotted-border-width-thin",
5
+ "--slotted-control-border-color",
6
+ "--slotted-control-font-size-lg",
7
+ "--slotted-control-font-size-md",
8
+ "--slotted-control-font-size-sm",
9
+ "--slotted-control-height-lg",
10
+ "--slotted-control-height-md",
11
+ "--slotted-control-height-sm",
12
+ "--slotted-control-icon-size-lg",
13
+ "--slotted-control-icon-size-md",
14
+ "--slotted-control-icon-size-sm",
15
+ "--slotted-control-invalid-edge-width",
16
+ "--slotted-control-padding-inline-lg",
17
+ "--slotted-control-padding-inline-md",
18
+ "--slotted-control-padding-inline-sm",
19
+ "--slotted-control-shadow",
20
+ "--slotted-control-surface",
21
+ "--slotted-control-transition-duration",
22
+ "--slotted-control-transition-easing",
23
+ "--slotted-disabled-background",
24
+ "--slotted-disabled-border",
25
+ "--slotted-disabled-foreground",
26
+ "--slotted-font-family-mono",
27
+ "--slotted-font-family-sans",
28
+ "--slotted-font-size-xs",
29
+ "--slotted-font-weight-semibold",
30
+ "--slotted-line-height-md",
31
+ "--slotted-line-height-xs",
32
+ "--slotted-listbox-padding-block",
33
+ "--slotted-radius-full",
34
+ "--slotted-radius-md",
35
+ "--slotted-selection-size-lg",
36
+ "--slotted-selection-size-md",
37
+ "--slotted-selection-size-sm",
38
+ "--slotted-space-2",
39
+ "--slotted-space-3",
40
+ "--slotted-space-4",
41
+ "--slotted-space-5",
42
+ "--slotted-text",
43
+ "--slotted-text-muted",
44
+ "--slotted-tone-accent-border",
45
+ "--slotted-tone-accent-solid",
46
+ "--slotted-tone-danger-border",
47
+ "--slotted-transfer-pane-min-inline-size",
48
+ "--slotted-transfer-rows"
49
+ ]