@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,87 @@
1
+ [
2
+ "--slotted-app-shell-row-font-size",
3
+ "--slotted-app-shell-row-gap",
4
+ "--slotted-app-shell-row-height",
5
+ "--slotted-app-shell-row-inset",
6
+ "--slotted-app-shell-row-line-height",
7
+ "--slotted-app-shell-row-mark",
8
+ "--slotted-border-subtle",
9
+ "--slotted-border-width-thin",
10
+ "--slotted-control-font-family",
11
+ "--slotted-control-gap-lg",
12
+ "--slotted-control-gap-md",
13
+ "--slotted-control-gap-sm",
14
+ "--slotted-control-height-lg",
15
+ "--slotted-control-height-md",
16
+ "--slotted-control-height-sm",
17
+ "--slotted-control-icon-size-lg",
18
+ "--slotted-control-icon-size-md",
19
+ "--slotted-control-icon-size-sm",
20
+ "--slotted-control-transition-duration",
21
+ "--slotted-control-transition-easing",
22
+ "--slotted-current-edge",
23
+ "--slotted-disabled-foreground",
24
+ "--slotted-duration-instant",
25
+ "--slotted-duration-medium",
26
+ "--slotted-duration-short",
27
+ "--slotted-easing-enter",
28
+ "--slotted-easing-exit",
29
+ "--slotted-easing-standard",
30
+ "--slotted-focus-ring-color",
31
+ "--slotted-focus-ring-offset",
32
+ "--slotted-focus-ring-width",
33
+ "--slotted-font-size-md",
34
+ "--slotted-font-size-sm",
35
+ "--slotted-font-size-xs",
36
+ "--slotted-font-weight-medium",
37
+ "--slotted-font-weight-regular",
38
+ "--slotted-font-weight-semibold",
39
+ "--slotted-line-height-md",
40
+ "--slotted-line-height-sm",
41
+ "--slotted-line-height-xs",
42
+ "--slotted-radius-full",
43
+ "--slotted-radius-lg",
44
+ "--slotted-radius-md",
45
+ "--slotted-shadow-md",
46
+ "--slotted-side-navigation-active-background",
47
+ "--slotted-side-navigation-color",
48
+ "--slotted-side-navigation-current-background",
49
+ "--slotted-side-navigation-current-color",
50
+ "--slotted-side-navigation-current-description-color",
51
+ "--slotted-side-navigation-current-edge",
52
+ "--slotted-side-navigation-description-color",
53
+ "--slotted-side-navigation-description-gap",
54
+ "--slotted-side-navigation-dot-color",
55
+ "--slotted-side-navigation-dot-size",
56
+ "--slotted-side-navigation-flyout-border-color",
57
+ "--slotted-side-navigation-flyout-measure",
58
+ "--slotted-side-navigation-flyout-min-measure",
59
+ "--slotted-side-navigation-flyout-radius",
60
+ "--slotted-side-navigation-flyout-shadow",
61
+ "--slotted-side-navigation-flyout-surface",
62
+ "--slotted-side-navigation-guide-color",
63
+ "--slotted-side-navigation-hover-background",
64
+ "--slotted-side-navigation-hover-color",
65
+ "--slotted-side-navigation-indent",
66
+ "--slotted-side-navigation-indent-step",
67
+ "--slotted-side-navigation-radius",
68
+ "--slotted-side-navigation-row-gap",
69
+ "--slotted-side-navigation-section-color",
70
+ "--slotted-side-navigation-section-gap",
71
+ "--slotted-side-navigation-section-label-gap",
72
+ "--slotted-space-1",
73
+ "--slotted-space-2",
74
+ "--slotted-space-3",
75
+ "--slotted-space-4",
76
+ "--slotted-space-5",
77
+ "--slotted-space-7",
78
+ "--slotted-surface-raised",
79
+ "--slotted-text",
80
+ "--slotted-text-muted",
81
+ "--slotted-tone-accent-solid",
82
+ "--slotted-tone-accent-surface",
83
+ "--slotted-tone-accent-text",
84
+ "--slotted-tone-secondary-subtle-active",
85
+ "--slotted-tone-secondary-subtle-hover",
86
+ "--slotted-z-index-popover"
87
+ ]
@@ -0,0 +1,431 @@
1
+ @layer slotted.components {
2
+ /* ── The box, and the row inside a paragraph ────────────────────────────
3
+ *
4
+ * One fill, one rim, one highlight, shared by the standalone placeholder and
5
+ * by every line of a text placeholder. They are the same object drawn at two
6
+ * scales, so they resolve their paint in one place.
7
+ *
8
+ * `--slotted-disabled-background` is the fill because it already means the
9
+ * one thing a placeholder means: a surface that is not available yet. It
10
+ * carries a cost, and the rim is what pays it — in the `high-contrast`
11
+ * scheme that token is the page's own white, so a fill alone would be an
12
+ * invisible box. `--slotted-border-subtle` is the fill's own colour in
13
+ * light, a faint step in dark, and black in high contrast: a rim that
14
+ * appears exactly where the fill stops working and adds no noise where it
15
+ * does.
16
+ */
17
+ /**
18
+ * `[data-loading]` on the paint rather than on the geometry, and the
19
+ * difference is not cosmetic: `user-select` and `color` inherit, so a
20
+ * placeholder that kept them after the content arrived handed the consumer
21
+ * unselectable, invisible text. The first capture of this family showed a
22
+ * loaded row as an empty line beside its avatar for exactly that reason.
23
+ * Geometry is left unguarded because a loaded placeholder is
24
+ * `display: contents` and has no box for it to describe.
25
+ */
26
+ [data-ui='skeleton'][data-part='root'][data-loading],
27
+ [data-ui='skeleton'][data-part='text'][data-loading] [data-part='line'] {
28
+ /**
29
+ * The unavailable surface, pushed a little toward the text colour. The
30
+ * token alone is not enough and the first dark capture is why: in the dark
31
+ * scheme `--slotted-disabled-background` is `#18181b` over a `#131316`
32
+ * ground, one step apart, and a page of placeholders read as an empty
33
+ * page. Mixing toward `--slotted-text` moves away from the ground in every
34
+ * scheme, because the text colour is the far end of each scheme's own
35
+ * range — darker in light, lighter in dark, black in high contrast.
36
+ *
37
+ * Eight per cent, measured rather than chosen. In oklab lightness the
38
+ * unmixed token sits 0.071 from the light surface, 0.022 from the dark one
39
+ * and 0.000 from the high-contrast one; at this ratio the three are 0.129,
40
+ * 0.086 and 0.081, which is the closest the one number gets to treating
41
+ * the three schemes alike without making the light placeholder shout. For
42
+ * scale, MUI's light skeleton sits about 0.07 from its ground.
43
+ */
44
+ --_fill: var(
45
+ --slotted-skeleton-fill,
46
+ color-mix(
47
+ in oklab,
48
+ var(--slotted-disabled-background, ButtonFace) 92%,
49
+ var(--slotted-text, CanvasText)
50
+ )
51
+ );
52
+ --_edge: var(--slotted-skeleton-border-color, var(--slotted-border-subtle, ButtonBorder));
53
+ /**
54
+ * A shimmer needs a second colour, and in August this family declined to
55
+ * have one on the grounds that the theme did not own it. It does: the band
56
+ * is the fill carried further along the same axis the fill was derived on,
57
+ * so it separates from the fill in every scheme without a token of its own.
58
+ * The band is darker than the fill in light and lighter in dark, which is
59
+ * Ant Design's answer to the same problem — its gradient runs from
60
+ * `rgba(0,0,0,.06)` to `rgba(0,0,0,.15)` — and it is the only direction
61
+ * that is a direction at all in three schemes rather than two.
62
+ */
63
+ --_highlight: var(
64
+ --slotted-skeleton-highlight-color,
65
+ color-mix(in oklab, var(--_fill) 86%, var(--slotted-text, CanvasText))
66
+ );
67
+ /**
68
+ * The dimmed end of the pulse: the fill carried toward the deepest surface
69
+ * the scheme holds, so it is a step away from the fill in every scheme
70
+ * without a token of its own. `surface-sunken` rather than `surface`
71
+ * because the two are the same white in light and a full step apart in
72
+ * dark, which is where the pulse was too quiet to see.
73
+ *
74
+ * A colour rather than an opacity, and that is a correction rather than a
75
+ * preference. The pulse used to fade the whole box, which flickered in the
76
+ * dark scheme: the rim faded with the fill, so once every cycle the shape
77
+ * came within a hair of the ground and then came back. Painting the
78
+ * background alone leaves the rim at full strength, and the box never
79
+ * leaves the page.
80
+ */
81
+ --_trough: var(
82
+ --slotted-skeleton-trough-color,
83
+ color-mix(in oklab, var(--_fill) 60%, var(--slotted-surface-sunken, Canvas))
84
+ );
85
+ background-color: var(--_fill);
86
+ border: var(--slotted-skeleton-border-width, var(--slotted-border-width-thin, 1px)) solid
87
+ var(--_edge);
88
+ /* The rim is inside the reserved geometry, or the placeholder is two
89
+ pixels taller than the content it stands for. */
90
+ box-sizing: border-box;
91
+ /* A placeholder is furniture, not text: nothing in it should be
92
+ selectable, and a drag across a loading list should not highlight it. */
93
+ user-select: none;
94
+ }
95
+
96
+ /* ── Shapes ─────────────────────────────────────────────────────────────
97
+ *
98
+ * Four relationships to the surrounding layout rather than four points on
99
+ * one scale: a line of type, a block of content, and the two boxes an avatar
100
+ * can be.
101
+ */
102
+
103
+ [data-ui='skeleton'][data-part='root'] {
104
+ display: inline-block;
105
+ /* Never a negative or zero box, whatever the consumer's value resolves
106
+ to. A placeholder that cannot be seen cannot be corrected. */
107
+ min-block-size: var(--slotted-skeleton-border-width, var(--slotted-border-width-thin, 1px));
108
+ }
109
+
110
+ /**
111
+ * A bar the height of the type it is placed in, sitting on that type's
112
+ * optical centre rather than on its baseline — the correction `link` derives
113
+ * for the marker it draws beside a word, for the same reason: an inline box
114
+ * is aligned by its bottom edge, and centring it on the cap line is what
115
+ * puts it where the reader expects the word to be.
116
+ *
117
+ * There is no size axis here on purpose. `1em` is the size of whatever type
118
+ * surrounds it, at whatever density, including a scale this library does not
119
+ * own — an axis would have been a coarser second copy of the type scale that
120
+ * a consumer could set to the wrong value.
121
+ */
122
+ [data-ui='skeleton'][data-part='root'][data-shape='text'] {
123
+ --_line: var(--slotted-skeleton-line-size, 1cap);
124
+
125
+ block-size: var(--slotted-skeleton-block-size, var(--_line));
126
+ border-radius: var(--slotted-radius-full, 9999px);
127
+ inline-size: var(--slotted-skeleton-inline-size, 100%);
128
+ /**
129
+ * Zero for the default bar, and that is the point rather than an accident:
130
+ * a box one cap tall, aligned on the baseline, occupies exactly the band a
131
+ * capital letter occupies. The expression stays because a consumer who
132
+ * overrides the height still wants it centred on the same band.
133
+ */
134
+ vertical-align: calc(0.5cap - 0.5 * var(--_line));
135
+ }
136
+
137
+ /**
138
+ * The block of content: an image, a chart, a map, a card. Its height is the
139
+ * consumer's or its content's, and with neither it is one line tall — a
140
+ * placeholder that resolved to nothing would be a hole in the page that no
141
+ * capture and no reader could point at.
142
+ */
143
+ [data-ui='skeleton'][data-part='root'][data-shape='block'] {
144
+ block-size: var(--slotted-skeleton-block-size, auto);
145
+ border-radius: var(--slotted-skeleton-radius, var(--slotted-radius-md, 6px));
146
+ display: block;
147
+ inline-size: var(--slotted-skeleton-inline-size, 100%);
148
+ min-block-size: var(--slotted-skeleton-min-block-size, 1lh);
149
+ }
150
+
151
+ /**
152
+ * The two shapes an avatar can be, taking Avatar's own two words and Avatar's
153
+ * own scale. `--slotted-skeleton-size` is the unstepped escape hatch `icon`
154
+ * established and `avatar` reuses, and it is the family's own rather than
155
+ * `--slotted-avatar-size`: setting it on a container must not resize the real
156
+ * avatars standing beside the placeholders.
157
+ */
158
+ [data-ui='skeleton'][data-part='root'][data-shape='circle'],
159
+ [data-ui='skeleton'][data-part='root'][data-shape='square'] {
160
+ --_size: var(--slotted-skeleton-size, var(--slotted-avatar-size-md, 36px));
161
+
162
+ block-size: var(--slotted-skeleton-block-size, var(--_size));
163
+ inline-size: var(--slotted-skeleton-inline-size, var(--_size));
164
+ }
165
+
166
+ [data-ui='skeleton'][data-part='root'][data-shape='circle'] {
167
+ border-radius: var(--slotted-radius-full, 9999px);
168
+ }
169
+
170
+ /**
171
+ * A sixth of the box, which is the proportion `avatar` derives rather than a
172
+ * step of the radius scale: six pixels is a gentle round on a 64-pixel square
173
+ * and a quarter-circle on a 20-pixel one.
174
+ */
175
+ [data-ui='skeleton'][data-part='root'][data-shape='square'] {
176
+ border-radius: var(--slotted-skeleton-radius, calc(var(--_size) / 6));
177
+ }
178
+
179
+ /* ── The size steps, which mean something only for the two round shapes ── */
180
+
181
+ [data-ui='skeleton'][data-part='root'][data-shape='circle'][data-size='xs'],
182
+ [data-ui='skeleton'][data-part='root'][data-shape='square'][data-size='xs'] {
183
+ --_size: var(--slotted-skeleton-size, var(--slotted-avatar-size-xs, 24px));
184
+ }
185
+
186
+ [data-ui='skeleton'][data-part='root'][data-shape='circle'][data-size='sm'],
187
+ [data-ui='skeleton'][data-part='root'][data-shape='square'][data-size='sm'] {
188
+ --_size: var(--slotted-skeleton-size, var(--slotted-avatar-size-sm, 28px));
189
+ }
190
+
191
+ [data-ui='skeleton'][data-part='root'][data-shape='circle'][data-size='md'],
192
+ [data-ui='skeleton'][data-part='root'][data-shape='square'][data-size='md'] {
193
+ --_size: var(--slotted-skeleton-size, var(--slotted-avatar-size-md, 36px));
194
+ }
195
+
196
+ [data-ui='skeleton'][data-part='root'][data-shape='circle'][data-size='lg'],
197
+ [data-ui='skeleton'][data-part='root'][data-shape='square'][data-size='lg'] {
198
+ --_size: var(--slotted-skeleton-size, var(--slotted-avatar-size-lg, 48px));
199
+ }
200
+
201
+ [data-ui='skeleton'][data-part='root'][data-shape='circle'][data-size='xl'],
202
+ [data-ui='skeleton'][data-part='root'][data-shape='square'][data-size='xl'] {
203
+ --_size: var(--slotted-skeleton-size, var(--slotted-avatar-size-xl, 64px));
204
+ }
205
+
206
+ /* ── The placeholder that covers real content ───────────────────────────
207
+ *
208
+ * The only form in which the reserved geometry cannot disagree with what
209
+ * replaces it, because it is that content's own geometry. MUI infers the box
210
+ * from `children` and Spectrum clones the child with a skeleton class; both
211
+ * arrive here, and neither hides the text a bare text node carries.
212
+ *
213
+ * `:not(:empty)` is what tells the two apart, so no attribute has to be
214
+ * invented for a fact the DOM already states. Every stated size stays
215
+ * available: a consumer covering a paragraph that has not been measured
216
+ * still sets one.
217
+ */
218
+ [data-ui='skeleton'][data-part='root'][data-loading]:not(:empty) {
219
+ block-size: var(--slotted-skeleton-block-size, auto);
220
+ /* An element child is hidden by `visibility`; a bare text node is not an
221
+ element and can only be hidden by taking the colour away. */
222
+ color: transparent;
223
+ inline-size: var(--slotted-skeleton-inline-size, auto);
224
+ }
225
+
226
+ [data-ui='skeleton'][data-part='root'][data-loading]:not(:empty) > * {
227
+ visibility: hidden;
228
+ }
229
+
230
+ /* ── The paragraph ──────────────────────────────────────────────────────
231
+ *
232
+ * Rows of exactly one line box, so `n` rows occupy exactly the `n` lines of
233
+ * the paragraph they stand in and nothing moves when the words arrive. Every
234
+ * surveyed implementation types a pixel height here instead and is therefore
235
+ * wrong at every density but one.
236
+ *
237
+ * The bar inside the row is one cap rather than one em, which is the second
238
+ * half of the same idea and was found by measuring rather than by reading:
239
+ * at `1em` the bar filled sixteen pixels of a twenty-pixel line box, and a
240
+ * paragraph of them read as a barcode because real prose fills a little over
241
+ * half its leading. A capital's height is where the ink actually is.
242
+ */
243
+ [data-ui='skeleton'][data-part='text'] {
244
+ align-items: center;
245
+ display: grid;
246
+ grid-auto-rows: var(--slotted-skeleton-row-size, 1lh);
247
+ inline-size: var(--slotted-skeleton-inline-size, 100%);
248
+ }
249
+
250
+ [data-ui='skeleton'] [data-part='line'] {
251
+ block-size: var(--slotted-skeleton-line-size, 1cap);
252
+ border-radius: var(--slotted-radius-full, 9999px);
253
+ inline-size: 100%;
254
+ }
255
+
256
+ /**
257
+ * The short last line is what makes a stack of bars read as prose rather
258
+ * than as a barcode. `:not(:only-child)` is the case Chakra guards in
259
+ * TypeScript and Carbon does not guard at all: one line shortened by itself
260
+ * stands for a sentence that was never there.
261
+ */
262
+ [data-ui='skeleton'] [data-part='line']:last-child:not(:only-child) {
263
+ inline-size: var(--slotted-skeleton-last-line-size, 62%);
264
+ }
265
+
266
+ /* ── Loaded ─────────────────────────────────────────────────────────────
267
+ *
268
+ * The element stays and stops taking part in layout, so the content it was
269
+ * covering lands exactly where it would have landed with no placeholder at
270
+ * all — and an empty placeholder, having nothing to lay out, renders
271
+ * nothing. One declaration answers both, and neither answer remounts the
272
+ * consumer's content on the way through.
273
+ */
274
+ [data-ui='skeleton'][data-part='root']:not([data-loading]),
275
+ [data-ui='skeleton'][data-part='text']:not([data-loading]) {
276
+ display: contents;
277
+ }
278
+
279
+ /* ── The region ─────────────────────────────────────────────────────────
280
+ *
281
+ * A region stands for a block of content, so it takes the inline size of
282
+ * whatever holds it. Without this it is a flex item with no definite size,
283
+ * and a flex item that shrinks to its content while the placeholders inside
284
+ * it are a percentage of that content resolves to nothing: measured at two
285
+ * pixels inside a 599-pixel column, every placeholder in it two pixels wide.
286
+ * The token is the way out for a region that really is inline.
287
+ */
288
+ [data-ui='skeleton'][data-part='region'] {
289
+ inline-size: var(--slotted-skeleton-inline-size, 100%);
290
+ min-inline-size: 0;
291
+ }
292
+
293
+ /* ── Motion ─────────────────────────────────────────────────────────────
294
+ *
295
+ * Both loops run on a layer drawn over the fill, and animate only `opacity`
296
+ * and `transform`, which the compositor runs without the page. The first
297
+ * version animated a registered, inherited custom property, which restyled
298
+ * every placeholder — and every descendant of a region — on every frame:
299
+ * on the docs' data-grid page the 72 boxes of one loading grid took 2.7
300
+ * seconds of style in every 3 with nothing else moving.
301
+ *
302
+ * The layer sits inside the rim (`inset: 0` of an absolute box is the
303
+ * padding box), and the box clips it to its own corners, so neither loop
304
+ * touches the edge or the outline of the shape.
305
+ *
306
+ * Boxes drawn in one render start their loops in one frame and move as one
307
+ * surface. A box mounted later starts its own cycle; `--slotted-skeleton-phase`
308
+ * (0 to 1, a point in the cycle) is where a box starts, so a consumer that
309
+ * needs a late box in step, and a capture that needs one moment, can name it.
310
+ */
311
+ [data-ui='skeleton'][data-part='root'][data-loading]:not([data-animation='none']),
312
+ [data-ui='skeleton'][data-part='text'][data-loading]:not([data-animation='none'])
313
+ [data-part='line'] {
314
+ overflow: clip;
315
+ position: relative;
316
+ }
317
+
318
+ [data-ui='skeleton'][data-part='root'][data-animation='pulse'][data-loading]::after,
319
+ [data-ui='skeleton'][data-part='root'][data-animation='shimmer'][data-loading]::after,
320
+ [data-ui='skeleton'][data-animation='pulse'][data-loading] [data-part='line']::after,
321
+ [data-ui='skeleton'][data-animation='shimmer'][data-loading] [data-part='line']::after {
322
+ animation-delay: calc(
323
+ var(--slotted-skeleton-phase, 0) * var(--slotted-duration-loop-slow) * -1
324
+ );
325
+ animation-duration: var(--slotted-duration-loop-slow);
326
+ animation-iteration-count: infinite;
327
+ content: '';
328
+ inset-block: 0;
329
+ inset-inline: 0;
330
+ pointer-events: none;
331
+ position: absolute;
332
+ }
333
+
334
+ /**
335
+ * The quiet one: the trough laid over the fill, faded in and out. The box
336
+ * itself never fades, for the reason recorded on `--_trough` — the rim stays
337
+ * at full strength and the shape never leaves the page. Zero at both ends of
338
+ * the cycle, so the seam where it wraps carries nothing to see.
339
+ */
340
+ [data-ui='skeleton'][data-part='root'][data-animation='pulse'][data-loading]::after,
341
+ [data-ui='skeleton'][data-animation='pulse'][data-loading] [data-part='line']::after {
342
+ animation-timing-function: ease-in-out;
343
+ background-color: var(--_trough);
344
+ opacity: 0;
345
+ }
346
+
347
+ /**
348
+ * A band crossing the box, and the geometry is the whole of it. The band is
349
+ * the middle 72 per cent of a layer the size of the box, and the layer
350
+ * travels from one box before it to one box past it, so the band comes in at
351
+ * one edge, crosses, and leaves at the other, with a rest between passes.
352
+ * That rest is what makes it read as something crossing the placeholder
353
+ * rather than as a gradient painted on it.
354
+ *
355
+ * The travel is symmetric about the box, so a right-to-left box runs the same
356
+ * travel backwards; `transform` and the gradient have no logical form.
357
+ */
358
+ [data-ui='skeleton'][data-part='root'][data-animation='shimmer'][data-loading]::after,
359
+ [data-ui='skeleton'][data-animation='shimmer'][data-loading] [data-part='line']::after {
360
+ animation-timing-function: linear;
361
+ background-image: linear-gradient(
362
+ 90deg,
363
+ transparent 14%,
364
+ var(--_highlight) 50%,
365
+ transparent 86%
366
+ );
367
+ }
368
+
369
+ [data-ui='skeleton'][data-part='root'][data-animation='shimmer'][data-loading]:dir(rtl)::after,
370
+ [data-ui='skeleton'][data-animation='shimmer'][data-loading]:dir(rtl) [data-part='line']::after {
371
+ animation-direction: reverse;
372
+ }
373
+
374
+ /* Started only here: a reset under `reduce` is one attribute against the
375
+ four that select a layer, and lost, so the loop ran under reduced motion. */
376
+ @media (prefers-reduced-motion: no-preference) {
377
+ [data-ui='skeleton'][data-part='root'][data-animation='pulse'][data-loading]::after,
378
+ [data-ui='skeleton'][data-animation='pulse'][data-loading] [data-part='line']::after {
379
+ animation-name: slotted-skeleton-pulse;
380
+ }
381
+
382
+ [data-ui='skeleton'][data-part='root'][data-animation='shimmer'][data-loading]::after,
383
+ [data-ui='skeleton'][data-animation='shimmer'][data-loading] [data-part='line']::after {
384
+ animation-name: slotted-skeleton-sweep;
385
+ }
386
+ }
387
+
388
+ @keyframes slotted-skeleton-pulse {
389
+ 50% {
390
+ opacity: 1;
391
+ }
392
+ }
393
+
394
+ @keyframes slotted-skeleton-sweep {
395
+ from {
396
+ transform: translateX(-100%);
397
+ }
398
+
399
+ to {
400
+ transform: translateX(100%);
401
+ }
402
+ }
403
+
404
+ /**
405
+ * The loop stops rather than hurries. A spinner reports through its motion
406
+ * and has nothing left to say once it is still; a placeholder reports
407
+ * through its shape, which does not move — so stillness costs this family
408
+ * nothing, and `docs/token-foundation.md` requires it of every infinite
409
+ * animation regardless. Still, the pulse layer is transparent and the band
410
+ * stands outside the box, so the reader sees the fill alone.
411
+ */
412
+ @media (prefers-reduced-motion: reduce) {
413
+ [data-ui='skeleton']::after,
414
+ [data-ui='skeleton'] [data-part='line']::after {
415
+ animation: none;
416
+ }
417
+ }
418
+
419
+ /**
420
+ * The theme remaps the fill to `Canvas` and the rim to `ButtonBorder`, so
421
+ * the box survives on its own. What does not survive is the gradient: a
422
+ * `background-image` is not replaced by the system palette, so a shimmer
423
+ * would go on painting a mixed colour over a forced one.
424
+ */
425
+ @media (forced-colors: active) {
426
+ [data-ui='skeleton'][data-part='root'][data-loading]::after,
427
+ [data-ui='skeleton'][data-part='text'][data-loading] [data-part='line']::after {
428
+ background-image: none;
429
+ }
430
+ }
431
+ }
@@ -0,0 +1,29 @@
1
+ [
2
+ "--slotted-avatar-size-lg",
3
+ "--slotted-avatar-size-md",
4
+ "--slotted-avatar-size-sm",
5
+ "--slotted-avatar-size-xl",
6
+ "--slotted-avatar-size-xs",
7
+ "--slotted-border-subtle",
8
+ "--slotted-border-width-thin",
9
+ "--slotted-disabled-background",
10
+ "--slotted-duration-loop-slow",
11
+ "--slotted-radius-full",
12
+ "--slotted-radius-md",
13
+ "--slotted-skeleton-block-size",
14
+ "--slotted-skeleton-border-color",
15
+ "--slotted-skeleton-border-width",
16
+ "--slotted-skeleton-fill",
17
+ "--slotted-skeleton-highlight-color",
18
+ "--slotted-skeleton-inline-size",
19
+ "--slotted-skeleton-last-line-size",
20
+ "--slotted-skeleton-line-size",
21
+ "--slotted-skeleton-min-block-size",
22
+ "--slotted-skeleton-phase",
23
+ "--slotted-skeleton-radius",
24
+ "--slotted-skeleton-row-size",
25
+ "--slotted-skeleton-size",
26
+ "--slotted-skeleton-trough-color",
27
+ "--slotted-surface-sunken",
28
+ "--slotted-text"
29
+ ]