@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,560 @@
1
+ @layer slotted.components {
2
+ /**
3
+ * ── The segmented date control ─────────────────────────────────────────
4
+ *
5
+ * The same frame `text-field` draws, holding a row of spin buttons instead
6
+ * of one `input`. The frame carries no role: `role="group"` is on the row,
7
+ * because the APG's spin-button example names the group as what tells a
8
+ * screen-reader user that three buttons are one date.
9
+ *
10
+ * There is no `input[type=date]` under any of it. The browser's own control
11
+ * cannot be styled, cannot be given a calendar of the application's, and
12
+ * takes its field order from the browser's locale rather than the
13
+ * application's — so the value reaches a form through a hidden input, which
14
+ * is the decision `currency-field` already took for a number.
15
+ */
16
+ [data-ui='date-field'][data-part='root'] {
17
+ /**
18
+ * Type, height, inline padding, gap and glyph size come from the control
19
+ * scales — the only ones the theme restates per density — so a date in a
20
+ * dense table shrinks whole rather than in parts.
21
+ */
22
+ --_font-size: var(--slotted-control-font-size-md, 13px);
23
+ --_height: var(--slotted-control-height-md, 34px);
24
+ --_padding-inline: var(--slotted-control-padding-inline-md, 13px);
25
+ --_gap: var(--slotted-control-gap-md, 8px);
26
+ --_icon-floor: var(--slotted-date-field-icon-size-min, 14px);
27
+ --_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-md, 16px));
28
+
29
+ /* The same inner-control box every family in the library draws: the glyph,
30
+ and one step of air on each side, bounded by the frame's own height. */
31
+ --_action-size: var(
32
+ --slotted-date-field-action-size,
33
+ min(
34
+ calc(var(--_icon-size) + 2 * var(--slotted-space-2, 0.25rem)),
35
+ calc(
36
+ var(--_height) - var(--slotted-control-border-width, 1px) * 2 -
37
+ var(--slotted-space-2, 0.25rem)
38
+ )
39
+ )
40
+ );
41
+
42
+ align-items: center;
43
+ background-color: var(--slotted-date-field-background, var(--slotted-control-surface, Field));
44
+ border: var(--slotted-control-border-width, 1px) solid
45
+ var(--slotted-date-field-border-color, var(--slotted-control-border-color, ButtonBorder));
46
+ border-radius: var(--slotted-date-field-radius, var(--slotted-control-radius, 4px));
47
+ box-shadow: var(--slotted-date-field-shadow, var(--slotted-control-shadow, none));
48
+ box-sizing: border-box;
49
+ color: var(--slotted-date-field-color, var(--slotted-text, CanvasText));
50
+ display: flex;
51
+ font-family: var(--slotted-control-font-family, system-ui, sans-serif);
52
+ font-size: var(--_font-size);
53
+ gap: var(--_gap);
54
+ inline-size: 100%;
55
+ min-block-size: var(--_height);
56
+ min-inline-size: 0;
57
+ padding-inline: var(--_padding-inline);
58
+ transition:
59
+ background-color var(--slotted-control-transition-duration)
60
+ var(--slotted-control-transition-easing),
61
+ border-color var(--slotted-control-transition-duration)
62
+ var(--slotted-control-transition-easing),
63
+ box-shadow var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
64
+ }
65
+
66
+ /**
67
+ * The button inside the frame is inset by its own gutter less than the value
68
+ * is, so the *glyph* ends the same distance from the border as the digits
69
+ * begin from it — the arithmetic `text-field` records, holding at every step
70
+ * and every density.
71
+ */
72
+ [data-ui='date-field'][data-part='root']:has(> [data-part='clear']:last-child) {
73
+ padding-inline-end: max(
74
+ 0px,
75
+ calc(var(--_padding-inline) - (var(--_action-size) - var(--_icon-size)) / 2)
76
+ );
77
+ }
78
+
79
+ /**
80
+ * The row of segments. It takes the whole of the space the adornments leave
81
+ * and puts the date at the reading edge, so an empty field and a full one
82
+ * start in the same place.
83
+ */
84
+ [data-ui='date-field'] [data-part='segments'] {
85
+ align-items: center;
86
+ /**
87
+ * It says what it is before it is pressed. A date is typed, so the pointer
88
+ * over it is a caret — and the row rather than only the segments, because
89
+ * the gap between two fields and the air at either end are part of the
90
+ * control the reader is aiming at.
91
+ */
92
+ cursor: text;
93
+ display: flex;
94
+ flex: 1 1 auto;
95
+ min-inline-size: 0;
96
+ /**
97
+ * One line, whatever the frame's width. The fields keep their digits and
98
+ * the row is clipped at the frame's edge, the way a text input clips a
99
+ * value longer than itself; a field the reader steps into is scrolled into
100
+ * view, because a clipped box is still a scroll container to the focus.
101
+ * Read on a 130-pixel column: the row ran under the button beside it and
102
+ * `dd` was drawn over `yyyy`.
103
+ */
104
+ overflow: hidden;
105
+ /* Digits that do not shift under one another as a value is typed over, and
106
+ a date whose three fields keep their columns while the reader steps. */
107
+ font-variant-numeric: tabular-nums;
108
+ }
109
+
110
+ /**
111
+ * One field of the date.
112
+ *
113
+ * Its width is stated rather than measured, so the row does not move when a
114
+ * single digit becomes two: `1ch` is the advance of a digit in a tabular
115
+ * face, and `--_digits` is how many the field can hold. A segment showing
116
+ * `9` and one showing `09` therefore occupy the same column, and the two
117
+ * separators never step sideways under the pointer.
118
+ */
119
+ [data-ui='date-field'] [data-part='segment'] {
120
+ --_digits: 2;
121
+
122
+ background-color: transparent;
123
+ cursor: text;
124
+ border-radius: var(--slotted-date-field-segment-radius, var(--slotted-radius-xs, 2px));
125
+ box-sizing: content-box;
126
+ color: inherit;
127
+ /* The caret belongs to no segment: the whole field is replaced by typing,
128
+ and a caret between two digits would offer an edit the family refuses. */
129
+ caret-color: transparent;
130
+ font: inherit;
131
+ /* A field never shrinks under its digits: a row narrower than its value
132
+ overflows and is clipped at the frame, the way an input clips text. A
133
+ flex item shrunk to its minimum drew `mm` as `mr`. */
134
+ flex: 0 0 auto;
135
+ min-inline-size: var(--slotted-date-field-segment-min-inline-size, calc(var(--_digits) * 1ch));
136
+ padding-inline: var(
137
+ --slotted-date-field-segment-padding-inline,
138
+ var(--slotted-space-1, 0.125rem)
139
+ );
140
+ text-align: center;
141
+ transition:
142
+ background-color var(--slotted-control-transition-duration)
143
+ var(--slotted-control-transition-easing),
144
+ color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
145
+ /* A spin button is operated by keys and by the pointer; nothing in it is
146
+ text a reader selects, and a drag across it would look like one. */
147
+ user-select: none;
148
+ -webkit-tap-highlight-color: transparent;
149
+ }
150
+
151
+ [data-ui='date-field'] [data-part='segment'][data-field='year'] {
152
+ --_digits: 4;
153
+ }
154
+
155
+ /**
156
+ * A field with no value yet. It is muted rather than hidden, because the
157
+ * placeholder is the format — `dd/mm/aaaa` to a Brazilian reader, in the
158
+ * reader's own words rather than in English — and a date being typed has to
159
+ * keep saying what is still missing.
160
+ */
161
+ [data-ui='date-field'] [data-part='segment'][data-placeholder] {
162
+ color: var(--slotted-date-field-placeholder-color, var(--slotted-text-muted, GrayText));
163
+ }
164
+
165
+ /**
166
+ * The separator the locale writes. It is decoration: the group's accessible
167
+ * name already carries the whole date in words, so a screen reader reading
168
+ * "slash" between two numbers would be reading punctuation aloud.
169
+ */
170
+ [data-ui='date-field'] [data-part='literal'] {
171
+ color: var(--slotted-date-field-literal-color, var(--slotted-text-muted, GrayText));
172
+ flex: 0 0 auto;
173
+ /* Its own bidi run: a slash between two numbers takes the paragraph's
174
+ direction, and in a right-to-left document the date read back to front. */
175
+ unicode-bidi: plaintext;
176
+ user-select: none;
177
+ }
178
+
179
+ /* ── Size ─────────────────────────────────────────────────────────────
180
+ *
181
+ * Three steps, matching the field the control sits in. A `size="sm"` field
182
+ * holding an `md` control is a field and a control disagreeing about one row.
183
+ */
184
+
185
+ [data-ui='date-field'][data-part='root'][data-size='sm'] {
186
+ --_font-size: var(--slotted-control-font-size-sm, 12px);
187
+ --_height: var(--slotted-control-height-sm, 30px);
188
+ --_padding-inline: var(--slotted-control-padding-inline-sm, 10px);
189
+ --_gap: var(--slotted-control-gap-sm, 6px);
190
+ --_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-sm, 14px));
191
+ }
192
+
193
+ [data-ui='date-field'][data-part='root'][data-size='md'] {
194
+ --_font-size: var(--slotted-control-font-size-md, 13px);
195
+ --_height: var(--slotted-control-height-md, 34px);
196
+ --_padding-inline: var(--slotted-control-padding-inline-md, 13px);
197
+ --_gap: var(--slotted-control-gap-md, 8px);
198
+ --_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-md, 16px));
199
+ }
200
+
201
+ [data-ui='date-field'][data-part='root'][data-size='lg'] {
202
+ --_font-size: var(--slotted-control-font-size-lg, 14px);
203
+ --_height: var(--slotted-control-height-lg, 38px);
204
+ --_padding-inline: var(--slotted-control-padding-inline-lg, 16px);
205
+ --_gap: var(--slotted-control-gap-lg, 8px);
206
+ --_icon-size: max(var(--_icon-floor), var(--slotted-control-icon-size-lg, 18px));
207
+ }
208
+
209
+ /* ── Variant ──────────────────────────────────────────────────────────
210
+ *
211
+ * The three steps `text-field` set, so a form holding a name and a date
212
+ * shows one frame twice rather than two frames.
213
+ */
214
+
215
+ [data-ui='date-field'][data-part='root'][data-variant='subtle'] {
216
+ background-color: var(
217
+ --slotted-date-field-subtle-background,
218
+ var(--slotted-surface-sunken, Canvas)
219
+ );
220
+ border-color: var(
221
+ --slotted-date-field-subtle-border-color,
222
+ var(--slotted-border-subtle, ButtonBorder)
223
+ );
224
+ }
225
+
226
+ [data-ui='date-field'][data-part='root'][data-variant='plain'] {
227
+ background-color: transparent;
228
+ border-color: transparent;
229
+ border-radius: var(--slotted-radius-none, 0px);
230
+ box-shadow: none;
231
+ }
232
+
233
+ /* ── Adornments ───────────────────────────────────────────────────────
234
+ *
235
+ * Named for the reading direction rather than for a side, and quieter than
236
+ * the value: an adornment annotates, and a reader looking for the date
237
+ * should not have to step over it.
238
+ */
239
+ [data-ui='date-field'] > [data-part='start'],
240
+ [data-ui='date-field'] > [data-part='end'] {
241
+ --slotted-icon-size: var(--_icon-size);
242
+
243
+ align-items: center;
244
+ color: var(--slotted-date-field-adornment-color, var(--slotted-text-muted, GrayText));
245
+ display: inline-flex;
246
+ flex: 0 0 auto;
247
+ gap: var(--slotted-space-2, 0.25rem);
248
+ line-height: 1;
249
+ unicode-bidi: plaintext;
250
+ }
251
+
252
+ [data-ui='date-field'] > [data-part='start'] > svg,
253
+ [data-ui='date-field'] > [data-part='end'] > svg {
254
+ block-size: var(--_icon-size);
255
+ inline-size: var(--_icon-size);
256
+ }
257
+
258
+ /* ── The clear button ─────────────────────────────────────────────────
259
+ *
260
+ * A real button, with the `Glyph` element the binding renders rather than a
261
+ * character, and held to the target minimum by the family rather than by the
262
+ * page.
263
+ */
264
+ [data-ui='date-field'] > [data-part='clear'] {
265
+ align-items: center;
266
+ appearance: none;
267
+ background-color: transparent;
268
+ block-size: var(--_action-size);
269
+ border: 0;
270
+ border-radius: var(--slotted-date-field-radius, var(--slotted-control-radius, 4px));
271
+ color: var(--slotted-date-field-action-color, var(--slotted-text-muted, GrayText));
272
+ cursor: pointer;
273
+ display: inline-flex;
274
+ flex: 0 0 auto;
275
+ inline-size: var(--_action-size);
276
+ justify-content: center;
277
+ padding: 0;
278
+ position: relative;
279
+ touch-action: manipulation;
280
+ transition:
281
+ background-color var(--slotted-control-transition-duration)
282
+ var(--slotted-control-transition-easing),
283
+ color var(--slotted-control-transition-duration) var(--slotted-control-transition-easing);
284
+ -webkit-tap-highlight-color: transparent;
285
+ }
286
+
287
+ /**
288
+ * The hit area, recovered outside the paint. At `sm` with `dense` the whole
289
+ * control is 24 pixels tall — the WCAG 2.2 minimum — so nothing drawn inside
290
+ * it can also be 24. This grows the target back in both axes and leaves a
291
+ * larger one alone, which is the correction `docs/token-foundation.md`
292
+ * leaves to the family rather than to the theme.
293
+ */
294
+ [data-ui='date-field'] > [data-part='clear']::after {
295
+ content: '';
296
+ inset: min(0px, calc((100% - var(--slotted-target-min, 24px)) / 2));
297
+ position: absolute;
298
+ }
299
+
300
+ /* On a finger the target is the comfortable size in both axes and the box
301
+ is the one a mouse sees: the ground and the focus ring stay square, and
302
+ the hit area above grows to 44 pixels around them. After an end
303
+ adornment — a picker's trigger — it does not reach back across it. */
304
+ @media (pointer: coarse) {
305
+ [data-ui='date-field'] > [data-part='clear']::after {
306
+ inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
307
+ }
308
+
309
+ [data-ui='date-field'] > [data-part='end'] + [data-part='clear']::after {
310
+ inset-inline-start: 0;
311
+ }
312
+ }
313
+
314
+ /* The cross is drawn at the control's own icon step. */
315
+ [data-ui='date-field'] > [data-part='clear'] {
316
+ --slotted-icon-size: var(--_icon-size);
317
+ }
318
+
319
+ [data-ui='date-field'] > [data-part='clear']:hover:not(:disabled):not([data-disabled]) {
320
+ background-color: var(
321
+ --slotted-date-field-action-hover-background,
322
+ var(--slotted-tone-secondary-subtle-hover)
323
+ );
324
+ }
325
+
326
+ [data-ui='date-field'] > [data-part='clear']:active:not(:disabled):not([data-disabled]) {
327
+ background-color: var(
328
+ --slotted-date-field-action-active-background,
329
+ var(--slotted-tone-secondary-subtle-active)
330
+ );
331
+ }
332
+
333
+ /**
334
+ * The button carries its own ring rather than borrowing the frame's. Tabbing
335
+ * from the last segment to the clear button has to move something visible,
336
+ * and a ring around the whole frame would sit still while focus moved inside
337
+ * it.
338
+ */
339
+ [data-ui='date-field'] > [data-part='clear']:focus-visible {
340
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
341
+ outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
342
+ }
343
+
344
+ /* ── States ───────────────────────────────────────────────────────────
345
+ *
346
+ * Written strongest last, and each weaker one guarded against every stronger
347
+ * one it can meet, which is the order `STATE_PRECEDENCE` sets.
348
+ */
349
+
350
+ [data-ui='date-field'][data-part='root']:hover:not([data-disabled]):not([data-readonly]):not(
351
+ [data-invalid]
352
+ ) {
353
+ border-color: var(--slotted-date-field-hover-border-color, var(--slotted-tone-accent-border));
354
+ }
355
+
356
+ [data-ui='date-field'][data-part='root'][data-variant='subtle']:hover:not([data-disabled]):not(
357
+ [data-readonly]
358
+ ):not([data-invalid]) {
359
+ background-color: var(
360
+ --slotted-date-field-subtle-hover-background,
361
+ var(--slotted-tone-secondary-subtle-hover)
362
+ );
363
+ }
364
+
365
+ [data-ui='date-field'][data-part='root'][data-variant='plain']:hover:not([data-disabled]):not(
366
+ [data-readonly]
367
+ ):not([data-invalid]) {
368
+ background-color: var(
369
+ --slotted-date-field-plain-hover-background,
370
+ var(--slotted-tone-secondary-subtle-hover)
371
+ );
372
+ border-color: transparent;
373
+ }
374
+
375
+ /**
376
+ * Focus is two marks and they answer two different questions.
377
+ *
378
+ * The frame's ring says the control has the reader's attention, exactly as
379
+ * every other control in the library says it. The band on one segment says
380
+ * which of the three fields a key will move, and no ring can say that: a
381
+ * second outline two pixels inside the first would be two rings nested, and
382
+ * at `dense` there is not room for two.
383
+ *
384
+ * So the segment takes the accent solid and its own ink. Under forced
385
+ * colours the accent tone maps to `Highlight` and `HighlightText`, which is
386
+ * the one pair the operating system guarantees legible together.
387
+ *
388
+ * Both are `:focus` and not `:focus-visible`, and that is the whole reason a
389
+ * reader could press this control and see nothing happen. A browser matches
390
+ * `:focus-visible` on a text input for a pointer press as well as for a Tab —
391
+ * the caret has to show either way — but it refuses it for a `div` that a
392
+ * pointer focused, and every part of this control is a `div`. Painted on
393
+ * `:focus-visible`, a clicked field answered a keystroke and looked exactly
394
+ * as it had before the press.
395
+ */
396
+ [data-ui='date-field'][data-part='root']:has([data-part='segment']:focus) {
397
+ box-shadow: var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
398
+ var(--slotted-focus-ring-color, Highlight);
399
+ outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
400
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
401
+ }
402
+
403
+ /**
404
+ * The ring of a control whose box is not its own is drawn inside that box,
405
+ * the way the inner controls draw theirs inside the frame: two pixels past
406
+ * the control is two pixels over the next row's rule. No lift either — a
407
+ * shadow that appears only under focus is a cell that changes size when it
408
+ * is used.
409
+ */
410
+ [data-ui='date-field'][data-part='root'][data-variant='plain']:has([data-part='segment']:focus) {
411
+ box-shadow: none;
412
+ outline-offset: calc(var(--slotted-focus-ring-offset, 2px) * -1);
413
+ }
414
+
415
+ [data-ui='date-field'] [data-part='segment']:focus {
416
+ background-color: var(
417
+ --slotted-date-field-segment-focus-background,
418
+ var(--slotted-tone-accent-solid)
419
+ );
420
+ color: var(--slotted-date-field-segment-focus-color, var(--slotted-tone-accent-on-solid));
421
+ /* The frame already draws the ring, so the segment does not draw a second. */
422
+ outline: none;
423
+ }
424
+
425
+ /**
426
+ * Invalid outranks hover and is written after it: a control reporting an
427
+ * error should not stop looking wrong because the pointer is over it. The
428
+ * ring is retargeted rather than repainted, so the frame's outline, the
429
+ * shadow under it and the ring on the clear button all move at once.
430
+ */
431
+ [data-ui='date-field'][data-part='root'][data-invalid] {
432
+ --slotted-focus-ring-color: var(
433
+ --slotted-date-field-invalid-focus-ring-color,
434
+ var(--slotted-focus-ring-color-invalid, Highlight)
435
+ );
436
+ --_invalid-edge-width: var(
437
+ --slotted-date-field-invalid-edge-width,
438
+ var(--slotted-control-invalid-edge-width, 1px)
439
+ );
440
+ --_invalid-edge-color: var(
441
+ --slotted-date-field-invalid-border-color,
442
+ var(--slotted-tone-danger-border)
443
+ );
444
+ --_invalid-edge: inset 0 0 0 var(--_invalid-edge-width) var(--_invalid-edge-color);
445
+
446
+ border-color: var(--slotted-date-field-invalid-border-color, var(--slotted-tone-danger-border));
447
+ /*
448
+ * Width as well as colour (WCAG 1.4.1), the edge `text-field` draws: in
449
+ * `high-contrast` the danger border is the resting edge's black. The line
450
+ * is a shadow inside the border, so neither box nor text moves, and it
451
+ * takes the resting lift's place.
452
+ */
453
+ box-shadow: var(--_invalid-edge);
454
+ }
455
+
456
+ [data-ui='date-field'][data-part='root'][data-invalid]:has([data-part='segment']:focus) {
457
+ box-shadow:
458
+ var(--_invalid-edge),
459
+ var(--slotted-control-shadow-focus-geometry, 0 1px 4px -1px)
460
+ var(--slotted-focus-ring-color, Highlight);
461
+ }
462
+
463
+ [data-ui='date-field'][data-part='root'][data-variant='plain'][data-invalid]:has(
464
+ [data-part='segment']:focus
465
+ ) {
466
+ /* The ring lies inside the box here, over the border and an edge as wide as
467
+ it; the edge reaches past the ring. */
468
+ box-shadow: inset 0 0 0
469
+ calc(
470
+ var(--slotted-focus-ring-offset, 2px) - var(--slotted-control-border-width, 1px) +
471
+ var(--_invalid-edge-width)
472
+ )
473
+ var(--_invalid-edge-color);
474
+ }
475
+
476
+ /*
477
+ * Forced colours remove every box shadow, and the edge with them. The
478
+ * width comes back as an outline inside the border, and a focused invalid
479
+ * control draws its ring double, which a valid ring is not.
480
+ */
481
+ @media (forced-colors: active) {
482
+ [data-ui='date-field'][data-part='root'][data-invalid] {
483
+ outline: var(--_invalid-edge-width) solid CanvasText;
484
+ outline-offset: calc(
485
+ -1 * (var(--slotted-control-border-width, 1px) + var(--_invalid-edge-width))
486
+ );
487
+ }
488
+
489
+ [data-ui='date-field'][data-part='root'][data-invalid]:has([data-part='segment']:focus) {
490
+ outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
491
+ var(--slotted-focus-ring-color, Highlight);
492
+ outline-offset: var(--slotted-focus-ring-offset, 2px);
493
+ }
494
+
495
+ [data-ui='date-field'][data-part='root'][data-variant='plain'][data-invalid]:has(
496
+ [data-part='segment']:focus
497
+ ) {
498
+ outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
499
+ var(--slotted-focus-ring-color, Highlight);
500
+ outline-offset: calc(
501
+ -1 * (var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width))
502
+ );
503
+ }
504
+ }
505
+
506
+ /**
507
+ * Read-only stays focusable, readable and copyable, and must not be
508
+ * mistakable for disabled: the value is still real and still submitted. The
509
+ * ground says "not yours to change" and the ink says nothing at all.
510
+ */
511
+ [data-ui='date-field'][data-part='root'][data-readonly],
512
+ [data-ui='date-field'][data-part='root'][data-readonly] [data-part='segments'],
513
+ [data-ui='date-field'][data-part='root'][data-readonly] [data-part='segment'] {
514
+ cursor: default;
515
+ }
516
+
517
+ [data-ui='date-field'][data-part='root'][data-readonly] {
518
+ background-color: var(
519
+ --slotted-date-field-readonly-background,
520
+ var(--slotted-tone-secondary-subtle-hover)
521
+ );
522
+ }
523
+
524
+ /**
525
+ * Muted to the colour the theme measures rather than faded by opacity: a
526
+ * date nobody can read is a field nobody can check, and a disabled form
527
+ * still has to say what it holds.
528
+ */
529
+ [data-ui='date-field'][data-part='root'][data-disabled] {
530
+ background-color: var(
531
+ --slotted-date-field-disabled-background,
532
+ var(--slotted-disabled-background)
533
+ );
534
+ border-color: var(--slotted-date-field-disabled-border-color, var(--slotted-disabled-border));
535
+ /* Nothing a person cannot reach is lifted off the page. */
536
+ box-shadow: none;
537
+ color: var(--slotted-date-field-disabled-color, var(--slotted-disabled-foreground));
538
+ cursor: not-allowed;
539
+ }
540
+
541
+ [data-ui='date-field'][data-part='root'][data-disabled] [data-part='segments'],
542
+ [data-ui='date-field'][data-part='root'][data-disabled] [data-part='segment'] {
543
+ cursor: not-allowed;
544
+ }
545
+
546
+ [data-ui='date-field'][data-part='root'][data-disabled] > [data-part='start'],
547
+ [data-ui='date-field'][data-part='root'][data-disabled] > [data-part='end'],
548
+ [data-ui='date-field'][data-part='root'][data-disabled] [data-part='literal'],
549
+ [data-ui='date-field'][data-part='root'][data-disabled] [data-part='segment'][data-placeholder] {
550
+ color: var(--slotted-disabled-foreground);
551
+ }
552
+
553
+ @media (forced-colors: active) {
554
+ /* A transparent border has no system colour to be remapped to, so the
555
+ `plain` control would lose its only edge where an edge matters most. */
556
+ [data-ui='date-field'][data-part='root'][data-variant='plain'] {
557
+ border-color: ButtonBorder;
558
+ }
559
+ }
560
+ }
@@ -0,0 +1,80 @@
1
+ [
2
+ "--slotted-border-subtle",
3
+ "--slotted-control-border-color",
4
+ "--slotted-control-border-width",
5
+ "--slotted-control-font-family",
6
+ "--slotted-control-font-size-lg",
7
+ "--slotted-control-font-size-md",
8
+ "--slotted-control-font-size-sm",
9
+ "--slotted-control-gap-lg",
10
+ "--slotted-control-gap-md",
11
+ "--slotted-control-gap-sm",
12
+ "--slotted-control-height-lg",
13
+ "--slotted-control-height-md",
14
+ "--slotted-control-height-sm",
15
+ "--slotted-control-icon-size-lg",
16
+ "--slotted-control-icon-size-md",
17
+ "--slotted-control-icon-size-sm",
18
+ "--slotted-control-invalid-edge-width",
19
+ "--slotted-control-padding-inline-lg",
20
+ "--slotted-control-padding-inline-md",
21
+ "--slotted-control-padding-inline-sm",
22
+ "--slotted-control-radius",
23
+ "--slotted-control-shadow",
24
+ "--slotted-control-shadow-focus-geometry",
25
+ "--slotted-control-surface",
26
+ "--slotted-control-transition-duration",
27
+ "--slotted-control-transition-easing",
28
+ "--slotted-date-field-action-active-background",
29
+ "--slotted-date-field-action-color",
30
+ "--slotted-date-field-action-hover-background",
31
+ "--slotted-date-field-action-size",
32
+ "--slotted-date-field-adornment-color",
33
+ "--slotted-date-field-background",
34
+ "--slotted-date-field-border-color",
35
+ "--slotted-date-field-color",
36
+ "--slotted-date-field-disabled-background",
37
+ "--slotted-date-field-disabled-border-color",
38
+ "--slotted-date-field-disabled-color",
39
+ "--slotted-date-field-hover-border-color",
40
+ "--slotted-date-field-icon-size-min",
41
+ "--slotted-date-field-invalid-border-color",
42
+ "--slotted-date-field-invalid-edge-width",
43
+ "--slotted-date-field-invalid-focus-ring-color",
44
+ "--slotted-date-field-literal-color",
45
+ "--slotted-date-field-placeholder-color",
46
+ "--slotted-date-field-plain-hover-background",
47
+ "--slotted-date-field-radius",
48
+ "--slotted-date-field-readonly-background",
49
+ "--slotted-date-field-segment-focus-background",
50
+ "--slotted-date-field-segment-focus-color",
51
+ "--slotted-date-field-segment-min-inline-size",
52
+ "--slotted-date-field-segment-padding-inline",
53
+ "--slotted-date-field-segment-radius",
54
+ "--slotted-date-field-shadow",
55
+ "--slotted-date-field-subtle-background",
56
+ "--slotted-date-field-subtle-border-color",
57
+ "--slotted-date-field-subtle-hover-background",
58
+ "--slotted-disabled-background",
59
+ "--slotted-disabled-border",
60
+ "--slotted-disabled-foreground",
61
+ "--slotted-focus-ring-color",
62
+ "--slotted-focus-ring-color-invalid",
63
+ "--slotted-focus-ring-offset",
64
+ "--slotted-focus-ring-width",
65
+ "--slotted-radius-none",
66
+ "--slotted-radius-xs",
67
+ "--slotted-space-1",
68
+ "--slotted-space-2",
69
+ "--slotted-surface-sunken",
70
+ "--slotted-target-comfortable",
71
+ "--slotted-target-min",
72
+ "--slotted-text",
73
+ "--slotted-text-muted",
74
+ "--slotted-tone-accent-border",
75
+ "--slotted-tone-accent-on-solid",
76
+ "--slotted-tone-accent-solid",
77
+ "--slotted-tone-danger-border",
78
+ "--slotted-tone-secondary-subtle-active",
79
+ "--slotted-tone-secondary-subtle-hover"
80
+ ]