@lar-works/design-system 0.0.0-stage → 0.1.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 (555) hide show
  1. package/README.md +24 -2
  2. package/dist/actions/Button.d.ts +25 -0
  3. package/dist/actions/Button.js +55 -0
  4. package/dist/actions/Button.js.map +1 -0
  5. package/dist/actions/ButtonLink.d.ts +21 -0
  6. package/dist/actions/ButtonLink.js +40 -0
  7. package/dist/actions/ButtonLink.js.map +1 -0
  8. package/dist/actions/IconButton.d.ts +14 -0
  9. package/dist/actions/IconButton.js +29 -0
  10. package/dist/actions/IconButton.js.map +1 -0
  11. package/dist/actions/ThemeSwitch.d.ts +7 -0
  12. package/dist/actions/ThemeSwitch.js +42 -0
  13. package/dist/actions/ThemeSwitch.js.map +1 -0
  14. package/dist/actions/index.d.ts +5 -0
  15. package/dist/collections/CollectionSectionHeader.d.ts +5 -0
  16. package/dist/collections/CollectionSectionHeader.js +18 -0
  17. package/dist/collections/CollectionSectionHeader.js.map +1 -0
  18. package/dist/collections/CollectionState.d.ts +37 -0
  19. package/dist/collections/CollectionState.js +69 -0
  20. package/dist/collections/CollectionState.js.map +1 -0
  21. package/dist/collections/CollectionTokens.d.ts +16 -0
  22. package/dist/collections/CollectionTokens.js +19 -0
  23. package/dist/collections/CollectionTokens.js.map +1 -0
  24. package/dist/collections/CollectionViewport.js +36 -0
  25. package/dist/collections/CollectionViewport.js.map +1 -0
  26. package/dist/collections/DataRow.d.ts +23 -0
  27. package/dist/collections/DataRow.js +57 -0
  28. package/dist/collections/DataRow.js.map +1 -0
  29. package/dist/collections/ResultList.d.ts +29 -0
  30. package/dist/collections/ResultList.js +128 -0
  31. package/dist/collections/ResultList.js.map +1 -0
  32. package/dist/collections/ScrollRow.d.ts +23 -0
  33. package/dist/collections/ScrollRow.js +59 -0
  34. package/dist/collections/ScrollRow.js.map +1 -0
  35. package/dist/collections/VirtualGrid.d.ts +14 -0
  36. package/dist/collections/VirtualGrid.js +71 -0
  37. package/dist/collections/VirtualGrid.js.map +1 -0
  38. package/dist/collections/VirtualList.d.ts +34 -0
  39. package/dist/collections/VirtualList.js +128 -0
  40. package/dist/collections/VirtualList.js.map +1 -0
  41. package/dist/collections/index.d.ts +10 -0
  42. package/dist/collections/useCollectionMotion.d.ts +3 -0
  43. package/dist/collections/useCollectionMotion.js +34 -0
  44. package/dist/collections/useCollectionMotion.js.map +1 -0
  45. package/dist/collections/useScrollRow.d.ts +17 -0
  46. package/dist/collections/useScrollRow.js +63 -0
  47. package/dist/collections/useScrollRow.js.map +1 -0
  48. package/dist/display/ActivityCard.d.ts +17 -0
  49. package/dist/display/ActivityCard.js +58 -0
  50. package/dist/display/ActivityCard.js.map +1 -0
  51. package/dist/display/Artwork.d.ts +25 -0
  52. package/dist/display/Artwork.js +97 -0
  53. package/dist/display/Artwork.js.map +1 -0
  54. package/dist/display/Avatar.d.ts +5 -0
  55. package/dist/display/Avatar.js +13 -0
  56. package/dist/display/Avatar.js.map +1 -0
  57. package/dist/display/Badge.d.ts +10 -0
  58. package/dist/display/Badge.js +28 -0
  59. package/dist/display/Badge.js.map +1 -0
  60. package/dist/display/BadgeList.d.ts +11 -0
  61. package/dist/display/BadgeList.js +20 -0
  62. package/dist/display/BadgeList.js.map +1 -0
  63. package/dist/display/BrandMark.d.ts +21 -0
  64. package/dist/display/BrandMark.js +60 -0
  65. package/dist/display/BrandMark.js.map +1 -0
  66. package/dist/display/ChangeList.d.ts +16 -0
  67. package/dist/display/ChangeList.js +56 -0
  68. package/dist/display/ChangeList.js.map +1 -0
  69. package/dist/display/CheckList.d.ts +10 -0
  70. package/dist/display/CheckList.js +25 -0
  71. package/dist/display/CheckList.js.map +1 -0
  72. package/dist/display/CodeBlock.d.ts +6 -0
  73. package/dist/display/CodeBlock.js +12 -0
  74. package/dist/display/CodeBlock.js.map +1 -0
  75. package/dist/display/CopyButton.d.ts +9 -0
  76. package/dist/display/CopyButton.js +59 -0
  77. package/dist/display/CopyButton.js.map +1 -0
  78. package/dist/display/DataTable.d.ts +35 -0
  79. package/dist/display/DataTable.js +53 -0
  80. package/dist/display/DataTable.js.map +1 -0
  81. package/dist/display/DetailHero.d.ts +39 -0
  82. package/dist/display/DetailHero.js +146 -0
  83. package/dist/display/DetailHero.js.map +1 -0
  84. package/dist/display/DetailList.d.ts +15 -0
  85. package/dist/display/DetailList.js +53 -0
  86. package/dist/display/DetailList.js.map +1 -0
  87. package/dist/display/DeviceCard.d.ts +18 -0
  88. package/dist/display/DeviceCard.js +48 -0
  89. package/dist/display/DeviceCard.js.map +1 -0
  90. package/dist/display/Identity.d.ts +14 -0
  91. package/dist/display/Identity.js +54 -0
  92. package/dist/display/Identity.js.map +1 -0
  93. package/dist/display/ImageCard.d.ts +22 -0
  94. package/dist/display/ImageCard.js +63 -0
  95. package/dist/display/ImageCard.js.map +1 -0
  96. package/dist/display/ImagePicker.d.ts +30 -0
  97. package/dist/display/ImagePicker.js +108 -0
  98. package/dist/display/ImagePicker.js.map +1 -0
  99. package/dist/display/InfoBox.d.ts +15 -0
  100. package/dist/display/InfoBox.js +41 -0
  101. package/dist/display/InfoBox.js.map +1 -0
  102. package/dist/display/InsetPanel.d.ts +13 -0
  103. package/dist/display/InsetPanel.js +26 -0
  104. package/dist/display/InsetPanel.js.map +1 -0
  105. package/dist/display/ItemAction.d.ts +10 -0
  106. package/dist/display/ItemAction.js +35 -0
  107. package/dist/display/ItemAction.js.map +1 -0
  108. package/dist/display/Kbd.d.ts +6 -0
  109. package/dist/display/Kbd.js +12 -0
  110. package/dist/display/Kbd.js.map +1 -0
  111. package/dist/display/KindIcon.d.ts +8 -0
  112. package/dist/display/KindIcon.js +15 -0
  113. package/dist/display/KindIcon.js.map +1 -0
  114. package/dist/display/NoticeCard.d.ts +24 -0
  115. package/dist/display/NoticeCard.js +59 -0
  116. package/dist/display/NoticeCard.js.map +1 -0
  117. package/dist/display/PairingList.d.ts +19 -0
  118. package/dist/display/PairingList.js +53 -0
  119. package/dist/display/PairingList.js.map +1 -0
  120. package/dist/display/PathList.d.ts +9 -0
  121. package/dist/display/PathList.js +21 -0
  122. package/dist/display/PathList.js.map +1 -0
  123. package/dist/display/PeoplePreview.d.ts +16 -0
  124. package/dist/display/PeoplePreview.js +41 -0
  125. package/dist/display/PeoplePreview.js.map +1 -0
  126. package/dist/display/PropertySheet.d.ts +56 -0
  127. package/dist/display/PropertySheet.js +150 -0
  128. package/dist/display/PropertySheet.js.map +1 -0
  129. package/dist/display/QrCode.d.ts +6 -0
  130. package/dist/display/QrCode.js +47 -0
  131. package/dist/display/QrCode.js.map +1 -0
  132. package/dist/display/RadioChoice.d.ts +9 -0
  133. package/dist/display/RadioChoice.js +28 -0
  134. package/dist/display/RadioChoice.js.map +1 -0
  135. package/dist/display/RatingLink.d.ts +10 -0
  136. package/dist/display/RatingLink.js +80 -0
  137. package/dist/display/RatingLink.js.map +1 -0
  138. package/dist/display/ResourceCard.d.ts +20 -0
  139. package/dist/display/ResourceCard.js +200 -0
  140. package/dist/display/ResourceCard.js.map +1 -0
  141. package/dist/display/RowList.d.ts +28 -0
  142. package/dist/display/RowList.js +76 -0
  143. package/dist/display/RowList.js.map +1 -0
  144. package/dist/display/StackedMeter.d.ts +28 -0
  145. package/dist/display/StackedMeter.js +48 -0
  146. package/dist/display/StackedMeter.js.map +1 -0
  147. package/dist/display/StatTile.d.ts +13 -0
  148. package/dist/display/StatTile.js +35 -0
  149. package/dist/display/StatTile.js.map +1 -0
  150. package/dist/display/StepList.d.ts +5 -0
  151. package/dist/display/StepList.js +12 -0
  152. package/dist/display/StepList.js.map +1 -0
  153. package/dist/display/TextPreview.d.ts +14 -0
  154. package/dist/display/TextPreview.js +46 -0
  155. package/dist/display/TextPreview.js.map +1 -0
  156. package/dist/display/TimeSeriesChart.d.ts +19 -0
  157. package/dist/display/TimeSeriesChart.js +163 -0
  158. package/dist/display/TimeSeriesChart.js.map +1 -0
  159. package/dist/display/ToneTile.js +12 -0
  160. package/dist/display/ToneTile.js.map +1 -0
  161. package/dist/display/index.d.ts +38 -0
  162. package/dist/feedback/Alert.d.ts +15 -0
  163. package/dist/feedback/Alert.js +19 -0
  164. package/dist/feedback/Alert.js.map +1 -0
  165. package/dist/feedback/AsyncState.d.ts +16 -0
  166. package/dist/feedback/AsyncState.js +29 -0
  167. package/dist/feedback/AsyncState.js.map +1 -0
  168. package/dist/feedback/ErrorNotification.d.ts +8 -0
  169. package/dist/feedback/ErrorNotification.js +20 -0
  170. package/dist/feedback/ErrorNotification.js.map +1 -0
  171. package/dist/feedback/Notifications.d.ts +2 -0
  172. package/dist/feedback/Notifications.js +9 -0
  173. package/dist/feedback/Notifications.js.map +1 -0
  174. package/dist/feedback/ProgressStatusRow.d.ts +23 -0
  175. package/dist/feedback/ProgressStatusRow.js +74 -0
  176. package/dist/feedback/ProgressStatusRow.js.map +1 -0
  177. package/dist/feedback/SkeletonLoader.d.ts +19 -0
  178. package/dist/feedback/SkeletonLoader.js +59 -0
  179. package/dist/feedback/SkeletonLoader.js.map +1 -0
  180. package/dist/feedback/StatusIndicator.d.ts +9 -0
  181. package/dist/feedback/StatusIndicator.js +28 -0
  182. package/dist/feedback/StatusIndicator.js.map +1 -0
  183. package/dist/feedback/StatusPopoverContent.d.ts +13 -0
  184. package/dist/feedback/StatusPopoverContent.js +50 -0
  185. package/dist/feedback/StatusPopoverContent.js.map +1 -0
  186. package/dist/feedback/StatusRow.d.ts +16 -0
  187. package/dist/feedback/StatusRow.js +60 -0
  188. package/dist/feedback/StatusRow.js.map +1 -0
  189. package/dist/feedback/index.d.ts +11 -0
  190. package/dist/feedback/index.js +11 -0
  191. package/dist/forms/Checkbox.d.ts +10 -0
  192. package/dist/forms/Checkbox.js +48 -0
  193. package/dist/forms/Checkbox.js.map +1 -0
  194. package/dist/forms/Field.d.ts +5 -0
  195. package/dist/forms/Field.js +15 -0
  196. package/dist/forms/Field.js.map +1 -0
  197. package/dist/forms/FormControlStyles.js +14 -0
  198. package/dist/forms/FormControlStyles.js.map +1 -0
  199. package/dist/forms/FormSection.d.ts +48 -0
  200. package/dist/forms/FormSection.js +142 -0
  201. package/dist/forms/FormSection.js.map +1 -0
  202. package/dist/forms/InlineFields.d.ts +13 -0
  203. package/dist/forms/InlineFields.js +24 -0
  204. package/dist/forms/InlineFields.js.map +1 -0
  205. package/dist/forms/Input.d.ts +5 -0
  206. package/dist/forms/Input.js +18 -0
  207. package/dist/forms/Input.js.map +1 -0
  208. package/dist/forms/OptionSelect.d.ts +21 -0
  209. package/dist/forms/OptionSelect.js +28 -0
  210. package/dist/forms/OptionSelect.js.map +1 -0
  211. package/dist/forms/RadioGroup.d.ts +5 -0
  212. package/dist/forms/RadioGroup.js +35 -0
  213. package/dist/forms/RadioGroup.js.map +1 -0
  214. package/dist/forms/Select.d.ts +6 -0
  215. package/dist/forms/Select.js +36 -0
  216. package/dist/forms/Select.js.map +1 -0
  217. package/dist/forms/Switch.d.ts +4 -0
  218. package/dist/forms/Switch.js +16 -0
  219. package/dist/forms/Switch.js.map +1 -0
  220. package/dist/forms/TagInput.d.ts +19 -0
  221. package/dist/forms/TagInput.js +60 -0
  222. package/dist/forms/TagInput.js.map +1 -0
  223. package/dist/forms/Textarea.d.ts +4 -0
  224. package/dist/forms/Textarea.js +15 -0
  225. package/dist/forms/Textarea.js.map +1 -0
  226. package/dist/forms/index.d.ts +12 -0
  227. package/dist/foundations/DesignSystemProvider.d.ts +64 -0
  228. package/dist/foundations/DesignSystemProvider.js +66 -0
  229. package/dist/foundations/DesignSystemProvider.js.map +1 -0
  230. package/dist/foundations/KeyboardFocus.d.ts +9 -0
  231. package/dist/foundations/KeyboardFocus.js +10 -0
  232. package/dist/foundations/KeyboardFocus.js.map +1 -0
  233. package/dist/foundations/KeyboardShortcut.d.ts +5 -0
  234. package/dist/foundations/KeyboardShortcut.js +10 -0
  235. package/dist/foundations/KeyboardShortcut.js.map +1 -0
  236. package/dist/foundations/Theme.d.ts +14 -0
  237. package/dist/foundations/Theme.js +54 -0
  238. package/dist/foundations/Theme.js.map +1 -0
  239. package/dist/foundations/index.d.ts +5 -0
  240. package/dist/icons/BrandIcons.d.ts +3 -0
  241. package/dist/icons/BrandIcons.js +14 -0
  242. package/dist/icons/BrandIcons.js.map +1 -0
  243. package/dist/icons/index.d.ts +3 -0
  244. package/dist/icons/index.js +2 -0
  245. package/dist/icons.d.ts +4 -0
  246. package/dist/icons.js +2 -0
  247. package/dist/index.d.ts +133 -0
  248. package/dist/index.js +125 -0
  249. package/dist/layout/AppShell.d.ts +11 -0
  250. package/dist/layout/AppShell.js +46 -0
  251. package/dist/layout/AppShell.js.map +1 -0
  252. package/dist/layout/AuthLayout.d.ts +11 -0
  253. package/dist/layout/AuthLayout.js +48 -0
  254. package/dist/layout/AuthLayout.js.map +1 -0
  255. package/dist/layout/ContentContainer.d.ts +9 -0
  256. package/dist/layout/ContentContainer.js +15 -0
  257. package/dist/layout/ContentContainer.js.map +1 -0
  258. package/dist/layout/Flow.d.ts +26 -0
  259. package/dist/layout/Flow.js +65 -0
  260. package/dist/layout/Flow.js.map +1 -0
  261. package/dist/layout/PageLayout.d.ts +12 -0
  262. package/dist/layout/PageLayout.js +31 -0
  263. package/dist/layout/PageLayout.js.map +1 -0
  264. package/dist/layout/PageSection.d.ts +43 -0
  265. package/dist/layout/PageSection.js +63 -0
  266. package/dist/layout/PageSection.js.map +1 -0
  267. package/dist/layout/ScrollArea.d.ts +4 -0
  268. package/dist/layout/ScrollArea.js +11 -0
  269. package/dist/layout/ScrollArea.js.map +1 -0
  270. package/dist/layout/Section.d.ts +12 -0
  271. package/dist/layout/Section.js +36 -0
  272. package/dist/layout/Section.js.map +1 -0
  273. package/dist/layout/Site.d.ts +41 -0
  274. package/dist/layout/Site.js +157 -0
  275. package/dist/layout/Site.js.map +1 -0
  276. package/dist/layout/TitleBar.d.ts +28 -0
  277. package/dist/layout/TitleBar.js +83 -0
  278. package/dist/layout/TitleBar.js.map +1 -0
  279. package/dist/layout/WorkspaceActionsHeader.d.ts +8 -0
  280. package/dist/layout/WorkspaceActionsHeader.js +18 -0
  281. package/dist/layout/WorkspaceActionsHeader.js.map +1 -0
  282. package/dist/layout/index.d.ts +19 -0
  283. package/dist/layout/index.js +19 -0
  284. package/dist/layout/sidebar/SidebarNavigationItem.d.ts +10 -0
  285. package/dist/layout/sidebar/SidebarNavigationItem.js +36 -0
  286. package/dist/layout/sidebar/SidebarNavigationItem.js.map +1 -0
  287. package/dist/layout/sidebar/SidebarPane.d.ts +13 -0
  288. package/dist/layout/sidebar/SidebarPane.js +30 -0
  289. package/dist/layout/sidebar/SidebarPane.js.map +1 -0
  290. package/dist/layout/toolbar/CommandPaletteTrigger.d.ts +11 -0
  291. package/dist/layout/toolbar/CommandPaletteTrigger.js +46 -0
  292. package/dist/layout/toolbar/CommandPaletteTrigger.js.map +1 -0
  293. package/dist/layout/toolbar/ToolbarStatusGroup.d.ts +5 -0
  294. package/dist/layout/toolbar/ToolbarStatusGroup.js +14 -0
  295. package/dist/layout/toolbar/ToolbarStatusGroup.js.map +1 -0
  296. package/dist/layout/toolbar/ToolbarStatusItem.d.ts +9 -0
  297. package/dist/layout/toolbar/ToolbarStatusItem.js +18 -0
  298. package/dist/layout/toolbar/ToolbarStatusItem.js.map +1 -0
  299. package/dist/navigation/ArtworkTabs.d.ts +18 -0
  300. package/dist/navigation/ArtworkTabs.js +72 -0
  301. package/dist/navigation/ArtworkTabs.js.map +1 -0
  302. package/dist/navigation/Breadcrumbs.d.ts +13 -0
  303. package/dist/navigation/Breadcrumbs.js +32 -0
  304. package/dist/navigation/Breadcrumbs.js.map +1 -0
  305. package/dist/navigation/CollectionBrowseSelector.d.ts +22 -0
  306. package/dist/navigation/CollectionBrowseSelector.js +70 -0
  307. package/dist/navigation/CollectionBrowseSelector.js.map +1 -0
  308. package/dist/navigation/CollectionViewToggle.d.ts +12 -0
  309. package/dist/navigation/CollectionViewToggle.js +36 -0
  310. package/dist/navigation/CollectionViewToggle.js.map +1 -0
  311. package/dist/navigation/DrilldownBrowseSelector.d.ts +31 -0
  312. package/dist/navigation/DrilldownBrowseSelector.js +174 -0
  313. package/dist/navigation/DrilldownBrowseSelector.js.map +1 -0
  314. package/dist/navigation/FolderSelector.d.ts +24 -0
  315. package/dist/navigation/FolderSelector.js +142 -0
  316. package/dist/navigation/FolderSelector.js.map +1 -0
  317. package/dist/navigation/TabKeys.js +13 -0
  318. package/dist/navigation/TabKeys.js.map +1 -0
  319. package/dist/navigation/ViewTabs.d.ts +19 -0
  320. package/dist/navigation/ViewTabs.js +48 -0
  321. package/dist/navigation/ViewTabs.js.map +1 -0
  322. package/dist/navigation/index.d.ts +8 -0
  323. package/dist/overlays/ActionModal.d.ts +21 -0
  324. package/dist/overlays/ActionModal.js +48 -0
  325. package/dist/overlays/ActionModal.js.map +1 -0
  326. package/dist/overlays/CommandPalette.d.ts +43 -0
  327. package/dist/overlays/CommandPalette.js +163 -0
  328. package/dist/overlays/CommandPalette.js.map +1 -0
  329. package/dist/overlays/Drawer.d.ts +19 -0
  330. package/dist/overlays/Drawer.js +83 -0
  331. package/dist/overlays/Drawer.js.map +1 -0
  332. package/dist/overlays/DropdownMenu.d.ts +47 -0
  333. package/dist/overlays/DropdownMenu.js +58 -0
  334. package/dist/overlays/DropdownMenu.js.map +1 -0
  335. package/dist/overlays/ImageViewer.d.ts +21 -0
  336. package/dist/overlays/ImageViewer.js +82 -0
  337. package/dist/overlays/ImageViewer.js.map +1 -0
  338. package/dist/overlays/Modal.d.ts +36 -0
  339. package/dist/overlays/Modal.js +149 -0
  340. package/dist/overlays/Modal.js.map +1 -0
  341. package/dist/overlays/Popover.d.ts +19 -0
  342. package/dist/overlays/Popover.js +26 -0
  343. package/dist/overlays/Popover.js.map +1 -0
  344. package/dist/overlays/Tooltip.d.ts +12 -0
  345. package/dist/overlays/Tooltip.js +54 -0
  346. package/dist/overlays/Tooltip.js.map +1 -0
  347. package/dist/overlays/index.d.ts +9 -0
  348. package/dist/overlays/useModalAutoFocus.js +84 -0
  349. package/dist/overlays/useModalAutoFocus.js.map +1 -0
  350. package/dist/overlays/useScrollFade.js +43 -0
  351. package/dist/overlays/useScrollFade.js.map +1 -0
  352. package/dist/showcase/CallToAction.d.ts +11 -0
  353. package/dist/showcase/CallToAction.js +54 -0
  354. package/dist/showcase/CallToAction.js.map +1 -0
  355. package/dist/showcase/Cards.d.ts +34 -0
  356. package/dist/showcase/Cards.js +122 -0
  357. package/dist/showcase/Cards.js.map +1 -0
  358. package/dist/showcase/Devices.d.ts +72 -0
  359. package/dist/showcase/Devices.js +249 -0
  360. package/dist/showcase/Devices.js.map +1 -0
  361. package/dist/showcase/FeatureRow.d.ts +30 -0
  362. package/dist/showcase/FeatureRow.js +91 -0
  363. package/dist/showcase/FeatureRow.js.map +1 -0
  364. package/dist/showcase/Hero.d.ts +15 -0
  365. package/dist/showcase/Hero.js +73 -0
  366. package/dist/showcase/Hero.js.map +1 -0
  367. package/dist/showcase/PhotoSearchConcept.d.ts +14 -0
  368. package/dist/showcase/PhotoSearchConcept.js +43 -0
  369. package/dist/showcase/PhotoSearchConcept.js.map +1 -0
  370. package/dist/showcase/Platforms.d.ts +15 -0
  371. package/dist/showcase/Platforms.js +48 -0
  372. package/dist/showcase/Platforms.js.map +1 -0
  373. package/dist/showcase/ProductBand.d.ts +38 -0
  374. package/dist/showcase/ProductBand.js +120 -0
  375. package/dist/showcase/ProductBand.js.map +1 -0
  376. package/dist/showcase/Roadmap.d.ts +21 -0
  377. package/dist/showcase/Roadmap.js +111 -0
  378. package/dist/showcase/Roadmap.js.map +1 -0
  379. package/dist/showcase/RouteDiagram.d.ts +14 -0
  380. package/dist/showcase/RouteDiagram.js +57 -0
  381. package/dist/showcase/RouteDiagram.js.map +1 -0
  382. package/dist/showcase/ServerUnit.d.ts +50 -0
  383. package/dist/showcase/ServerUnit.js +175 -0
  384. package/dist/showcase/ServerUnit.js.map +1 -0
  385. package/dist/showcase/Stage.d.ts +46 -0
  386. package/dist/showcase/Stage.js +106 -0
  387. package/dist/showcase/Stage.js.map +1 -0
  388. package/dist/showcase/Status.d.ts +30 -0
  389. package/dist/showcase/Status.js +84 -0
  390. package/dist/showcase/Status.js.map +1 -0
  391. package/dist/showcase/StepFlow.d.ts +13 -0
  392. package/dist/showcase/StepFlow.js +47 -0
  393. package/dist/showcase/StepFlow.js.map +1 -0
  394. package/dist/showcase/index.d.ts +15 -0
  395. package/dist/testing.d.ts +5 -0
  396. package/dist/testing.js +43 -0
  397. package/dist/testing.js.map +1 -0
  398. package/dist/typography/Link.d.ts +21 -0
  399. package/dist/typography/Link.js +60 -0
  400. package/dist/typography/Link.js.map +1 -0
  401. package/dist/typography/Typography.d.ts +53 -0
  402. package/dist/typography/Typography.js +67 -0
  403. package/dist/typography/Typography.js.map +1 -0
  404. package/dist/typography/index.d.ts +4 -0
  405. package/dist/typography/index.js +4 -0
  406. package/package.json +80 -3
  407. package/src/actions/Button.tsx +68 -0
  408. package/src/actions/ButtonLink.tsx +75 -0
  409. package/src/actions/IconButton.tsx +55 -0
  410. package/src/actions/ThemeSwitch.tsx +46 -0
  411. package/src/actions/index.ts +4 -0
  412. package/src/collections/CollectionSectionHeader.tsx +13 -0
  413. package/src/collections/CollectionState.tsx +76 -0
  414. package/src/collections/CollectionTokens.ts +12 -0
  415. package/src/collections/CollectionViewport.ts +40 -0
  416. package/src/collections/DataRow.tsx +79 -0
  417. package/src/collections/ResultList.tsx +164 -0
  418. package/src/collections/ScrollRow.tsx +90 -0
  419. package/src/collections/VirtualGrid.tsx +92 -0
  420. package/src/collections/VirtualList.tsx +224 -0
  421. package/src/collections/index.ts +10 -0
  422. package/src/collections/useCollectionMotion.ts +42 -0
  423. package/src/collections/useScrollRow.ts +64 -0
  424. package/src/display/ActivityCard.tsx +76 -0
  425. package/src/display/Artwork.tsx +140 -0
  426. package/src/display/Avatar.tsx +7 -0
  427. package/src/display/Badge.tsx +33 -0
  428. package/src/display/BadgeList.tsx +25 -0
  429. package/src/display/BrandMark.tsx +72 -0
  430. package/src/display/ChangeList.tsx +41 -0
  431. package/src/display/CheckList.tsx +27 -0
  432. package/src/display/CodeBlock.tsx +12 -0
  433. package/src/display/CopyButton.tsx +77 -0
  434. package/src/display/DataTable.tsx +80 -0
  435. package/src/display/DetailHero.tsx +191 -0
  436. package/src/display/DetailList.tsx +74 -0
  437. package/src/display/DeviceCard.tsx +49 -0
  438. package/src/display/Identity.tsx +56 -0
  439. package/src/display/ImageCard.tsx +102 -0
  440. package/src/display/ImagePicker.tsx +149 -0
  441. package/src/display/InfoBox.tsx +48 -0
  442. package/src/display/InsetPanel.tsx +37 -0
  443. package/src/display/ItemAction.tsx +53 -0
  444. package/src/display/Kbd.tsx +6 -0
  445. package/src/display/KindIcon.tsx +15 -0
  446. package/src/display/NoticeCard.tsx +77 -0
  447. package/src/display/PairingList.tsx +55 -0
  448. package/src/display/PathList.tsx +16 -0
  449. package/src/display/PeoplePreview.tsx +66 -0
  450. package/src/display/PropertySheet.tsx +180 -0
  451. package/src/display/QrCode.tsx +47 -0
  452. package/src/display/RadioChoice.tsx +34 -0
  453. package/src/display/RatingLink.tsx +76 -0
  454. package/src/display/ResourceCard.tsx +201 -0
  455. package/src/display/RowList.tsx +110 -0
  456. package/src/display/StackedMeter.tsx +72 -0
  457. package/src/display/StatTile.tsx +39 -0
  458. package/src/display/StepList.tsx +10 -0
  459. package/src/display/TextPreview.tsx +66 -0
  460. package/src/display/TimeSeriesChart.tsx +191 -0
  461. package/src/display/ToneTile.ts +10 -0
  462. package/src/display/index.ts +37 -0
  463. package/src/feedback/Alert.tsx +35 -0
  464. package/src/feedback/AsyncState.tsx +56 -0
  465. package/src/feedback/ErrorNotification.ts +24 -0
  466. package/src/feedback/Notifications.tsx +5 -0
  467. package/src/feedback/ProgressStatusRow.tsx +104 -0
  468. package/src/feedback/SkeletonLoader.tsx +88 -0
  469. package/src/feedback/StatusIndicator.tsx +28 -0
  470. package/src/feedback/StatusPopoverContent.tsx +54 -0
  471. package/src/feedback/StatusRow.tsx +70 -0
  472. package/src/feedback/index.ts +15 -0
  473. package/src/forms/Checkbox.tsx +61 -0
  474. package/src/forms/Field.tsx +17 -0
  475. package/src/forms/FormControlStyles.ts +9 -0
  476. package/src/forms/FormSection.tsx +175 -0
  477. package/src/forms/InlineFields.tsx +22 -0
  478. package/src/forms/Input.tsx +22 -0
  479. package/src/forms/OptionSelect.tsx +49 -0
  480. package/src/forms/RadioGroup.tsx +48 -0
  481. package/src/forms/Select.tsx +46 -0
  482. package/src/forms/Switch.tsx +10 -0
  483. package/src/forms/TagInput.tsx +76 -0
  484. package/src/forms/Textarea.tsx +14 -0
  485. package/src/forms/index.ts +11 -0
  486. package/src/foundations/DesignSystemProvider.tsx +79 -0
  487. package/src/foundations/KeyboardFocus.ts +6 -0
  488. package/src/foundations/KeyboardShortcut.ts +12 -0
  489. package/src/foundations/Theme.ts +71 -0
  490. package/src/foundations/index.ts +10 -0
  491. package/src/foundations/theme.css +425 -0
  492. package/src/icons/BrandIcons.tsx +8 -0
  493. package/src/icons/index.ts +4 -0
  494. package/src/icons.ts +1 -0
  495. package/src/index.ts +13 -0
  496. package/src/layout/AppShell.tsx +63 -0
  497. package/src/layout/AuthLayout.tsx +40 -0
  498. package/src/layout/ContentContainer.tsx +16 -0
  499. package/src/layout/Flow.tsx +56 -0
  500. package/src/layout/PageLayout.tsx +35 -0
  501. package/src/layout/PageSection.tsx +103 -0
  502. package/src/layout/ScrollArea.tsx +7 -0
  503. package/src/layout/Section.tsx +36 -0
  504. package/src/layout/Site.tsx +205 -0
  505. package/src/layout/TitleBar.tsx +97 -0
  506. package/src/layout/WorkspaceActionsHeader.tsx +17 -0
  507. package/src/layout/index.ts +18 -0
  508. package/src/layout/sidebar/SidebarNavigationItem.tsx +45 -0
  509. package/src/layout/sidebar/SidebarPane.tsx +37 -0
  510. package/src/layout/toolbar/CommandPaletteTrigger.tsx +53 -0
  511. package/src/layout/toolbar/ToolbarStatusGroup.tsx +9 -0
  512. package/src/layout/toolbar/ToolbarStatusItem.tsx +18 -0
  513. package/src/navigation/ArtworkTabs.tsx +107 -0
  514. package/src/navigation/Breadcrumbs.tsx +31 -0
  515. package/src/navigation/CollectionBrowseSelector.tsx +90 -0
  516. package/src/navigation/CollectionViewToggle.tsx +52 -0
  517. package/src/navigation/DrilldownBrowseSelector.tsx +229 -0
  518. package/src/navigation/FolderSelector.tsx +172 -0
  519. package/src/navigation/TabKeys.ts +21 -0
  520. package/src/navigation/ViewTabs.tsx +85 -0
  521. package/src/navigation/index.ts +15 -0
  522. package/src/overlays/ActionModal.tsx +81 -0
  523. package/src/overlays/CommandPalette.tsx +199 -0
  524. package/src/overlays/Drawer.tsx +107 -0
  525. package/src/overlays/DropdownMenu.tsx +122 -0
  526. package/src/overlays/ImageViewer.tsx +96 -0
  527. package/src/overlays/Modal.tsx +234 -0
  528. package/src/overlays/Popover.tsx +40 -0
  529. package/src/overlays/Tooltip.tsx +56 -0
  530. package/src/overlays/index.ts +8 -0
  531. package/src/overlays/useModalAutoFocus.ts +119 -0
  532. package/src/overlays/useScrollFade.ts +49 -0
  533. package/src/showcase/CallToAction.tsx +46 -0
  534. package/src/showcase/Cards.tsx +133 -0
  535. package/src/showcase/Devices.tsx +259 -0
  536. package/src/showcase/FeatureRow.tsx +107 -0
  537. package/src/showcase/Hero.tsx +70 -0
  538. package/src/showcase/PhotoSearchConcept.tsx +50 -0
  539. package/src/showcase/Platforms.tsx +49 -0
  540. package/src/showcase/ProductBand.tsx +148 -0
  541. package/src/showcase/Roadmap.tsx +115 -0
  542. package/src/showcase/RouteDiagram.tsx +56 -0
  543. package/src/showcase/ServerUnit.tsx +191 -0
  544. package/src/showcase/Stage.tsx +160 -0
  545. package/src/showcase/Status.tsx +107 -0
  546. package/src/showcase/StepFlow.tsx +48 -0
  547. package/src/showcase/devices.css +441 -0
  548. package/src/showcase/index.ts +34 -0
  549. package/src/showcase/server-unit.css +258 -0
  550. package/src/showcase/stage.css +175 -0
  551. package/src/styles.css +5 -0
  552. package/src/testing.ts +34 -0
  553. package/src/typography/Link.tsx +105 -0
  554. package/src/typography/Typography.tsx +113 -0
  555. package/src/typography/index.ts +3 -0
@@ -0,0 +1,148 @@
1
+ import { ArrowRightIcon } from 'lucide-react';
2
+ import { type CSSProperties, type ReactNode, useId } from 'react';
3
+
4
+ import { tabbable } from '../foundations/KeyboardFocus';
5
+ import { Heading, Text } from '../typography/Typography';
6
+
7
+ export interface ProductEntry {
8
+ name: string;
9
+ icon: ReactNode;
10
+ status: ReactNode;
11
+ summary: string;
12
+ href: string;
13
+ }
14
+
15
+ /** The family of products under a hero, one compact entry each, wrapping as the family grows. */
16
+ export function ProductIndex({
17
+ products,
18
+ label,
19
+ onNavigate,
20
+ }: {
21
+ products: readonly ProductEntry[];
22
+ label: string;
23
+ onNavigate: (href: string) => void;
24
+ }) {
25
+ return (
26
+ <ul aria-label={label} className="mx-auto flex max-w-[880px] flex-wrap justify-center gap-3">
27
+ {products.map((product) => (
28
+ <li key={product.href} className="w-full sm:w-[calc(50%-0.375rem)] lg:w-[calc(50%-0.375rem)]">
29
+ <a
30
+ {...tabbable}
31
+ href={product.href}
32
+ onClick={(event) => {
33
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;
34
+
35
+ event.preventDefault();
36
+ onNavigate(product.href);
37
+ }}
38
+ className="group/entry border-base-300 bg-base-100/70 hover:border-base-400 focus-visible:outline-primary dark:bg-base-100/50 flex h-full items-center gap-3 rounded-2xl border px-4 py-3 text-left shadow-xs/5 backdrop-blur transition-[border-color,background-color] focus-visible:outline-2"
39
+ >
40
+ {product.icon}
41
+ <span className="flex min-w-0 flex-1 flex-col gap-1">
42
+ <span className="flex flex-wrap items-center gap-2">
43
+ <span className="text-base-content text-[15px] font-semibold tracking-[-0.01em]">
44
+ {product.name}
45
+ </span>
46
+ {product.status}
47
+ </span>
48
+ <span className="text-base-700 text-sm leading-5">{product.summary}</span>
49
+ </span>
50
+ <span className="text-base-600 inline-flex transition-transform duration-200 group-hover/entry:translate-x-0.5 [&_svg]:size-4">
51
+ <ArrowRightIcon />
52
+ </span>
53
+ </a>
54
+ </li>
55
+ ))}
56
+ </ul>
57
+ );
58
+ }
59
+
60
+ interface ProductBandProps {
61
+ /** The band's colour world: a hue and how strongly it shows. */
62
+ hue: number;
63
+ chroma?: number;
64
+ icon: ReactNode;
65
+ name: string;
66
+ status: ReactNode;
67
+ title: string;
68
+ description: string;
69
+ actions: ReactNode;
70
+ media: ReactNode;
71
+ /** Puts the media on the left. */
72
+ reverse?: boolean;
73
+ /** A short line under the actions, such as requirements. */
74
+ note?: ReactNode;
75
+ }
76
+
77
+ /** One product's own space on a page that presents several: its colour, its devices, its way in. */
78
+ export function ProductBand({
79
+ hue,
80
+ chroma = 0.13,
81
+ icon,
82
+ name,
83
+ status,
84
+ title,
85
+ description,
86
+ actions,
87
+ media,
88
+ reverse,
89
+ note,
90
+ }: ProductBandProps) {
91
+ const id = useId();
92
+
93
+ return (
94
+ <article
95
+ aria-labelledby={id}
96
+ className="border-base-300 bg-base-100 dark:bg-base-100/70 relative isolate overflow-hidden rounded-[2rem] border"
97
+ style={{ '--lar-band-hue': hue, '--lar-band-chroma': chroma } as CSSProperties}
98
+ >
99
+ <div
100
+ aria-hidden="true"
101
+ className="absolute inset-0 -z-10 bg-[radial-gradient(70%_90%_at_var(--lar-band-x)_50%,oklch(0.6_var(--lar-band-chroma)_var(--lar-band-hue)/0.24),transparent_70%)] dark:bg-[radial-gradient(70%_90%_at_var(--lar-band-x)_50%,oklch(0.42_var(--lar-band-chroma)_var(--lar-band-hue)/0.45),transparent_70%)]"
102
+ style={{ '--lar-band-x': reverse ? '20%' : '80%' } as CSSProperties}
103
+ />
104
+ {/* On narrow screens the text wrapper dissolves, so the product's picture sits right under its
105
+ heading, before the description and actions. */}
106
+ <div
107
+ className={`grid items-center gap-5 p-6 sm:p-10 lg:gap-12 lg:p-12 ${reverse ? 'lg:grid-cols-[minmax(0,8fr)_minmax(0,4fr)]' : 'lg:grid-cols-[minmax(0,4fr)_minmax(0,8fr)]'}`}
108
+ >
109
+ <div className={`contents lg:flex lg:flex-col lg:gap-5 ${reverse ? 'lg:order-2' : ''}`}>
110
+ <div className="order-1 flex items-center gap-3 lg:order-none">
111
+ {icon}
112
+ <Text as="span" variant="label">
113
+ {name}
114
+ </Text>
115
+ {status}
116
+ </div>
117
+ <Heading
118
+ id={id}
119
+ as="h2"
120
+ variant="feature"
121
+ className="order-2 lg:order-none lg:text-[1.875rem] lg:leading-[1.15]"
122
+ >
123
+ {title}
124
+ </Heading>
125
+ <Text variant="lead" tone="muted" className="order-4 lg:order-none">
126
+ {description}
127
+ </Text>
128
+ <div className="order-5 mt-1 flex flex-col gap-3 lg:order-none">
129
+ <div className="flex flex-wrap items-center gap-3 max-sm:flex-col max-sm:[&>a]:w-full">
130
+ {actions}
131
+ </div>
132
+ {note ? (
133
+ <Text variant="caption" tone="muted" className="dark:text-[#96969f]">
134
+ {note}
135
+ </Text>
136
+ ) : null}
137
+ </div>
138
+ </div>
139
+ <div className={`order-3 my-3 lg:my-0 ${reverse ? 'lg:order-1' : 'lg:order-none'}`}>{media}</div>
140
+ </div>
141
+ </article>
142
+ );
143
+ }
144
+
145
+ /** Product bands one after another, as many as the family has. */
146
+ export function ProductBands({ children }: { children: ReactNode }) {
147
+ return <div className="flex flex-col gap-6 sm:gap-8">{children}</div>;
148
+ }
@@ -0,0 +1,115 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+
3
+ import { StatusPill } from './Status';
4
+
5
+ export interface RoadmapItem {
6
+ icon: ReactNode;
7
+ title: string;
8
+ body: string;
9
+ /** The next big thing: a card of its own above the list, in an app's hue, with its highlights and an
10
+ * illustration of the idea. */
11
+ featured?: { hue: number; highlights: readonly string[]; visual?: ReactNode; steps?: readonly string[] };
12
+ }
13
+
14
+ /** What is planned: a featured card for the next big thing, then quiet dashed cards that read like promises. */
15
+ export function Roadmap({
16
+ items,
17
+ label,
18
+ statusLabel,
19
+ }: {
20
+ items: readonly RoadmapItem[];
21
+ label: string;
22
+ statusLabel: string;
23
+ }) {
24
+ const featured = items.filter((item) => item.featured);
25
+ const rest = items.filter((item) => !item.featured);
26
+
27
+ return (
28
+ <div aria-label={label} role="group" className="flex flex-col gap-3">
29
+ {featured.map((item) => (
30
+ <FeaturedCard key={item.title} item={item} statusLabel={statusLabel} />
31
+ ))}
32
+ <ul className="divide-base-300/70 border-base-400/80 bg-base-100/50 dark:bg-base-100/30 grid divide-y rounded-2xl border border-dashed sm:gap-3 sm:divide-y-0 sm:rounded-none sm:border-0 sm:bg-transparent md:grid-cols-2 lg:grid-cols-3 sm:dark:bg-transparent">
33
+ {rest.map((item) => (
34
+ <li
35
+ key={item.title}
36
+ className="sm:border-base-400/80 flex gap-3 p-4 sm:gap-4 sm:rounded-2xl sm:border sm:border-dashed sm:p-5"
37
+ >
38
+ <RoadmapIcon>{item.icon}</RoadmapIcon>
39
+ <div className="flex min-w-0 flex-1 flex-col gap-1">
40
+ <span className="flex items-start justify-between gap-3">
41
+ <span className="text-base-content text-[15px] font-semibold tracking-[-0.01em] text-balance">
42
+ {item.title}
43
+ </span>
44
+ <span className="shrink-0">
45
+ <StatusPill status="planned">{statusLabel}</StatusPill>
46
+ </span>
47
+ </span>
48
+ <span className="text-base-700 text-sm leading-6">{item.body}</span>
49
+ </div>
50
+ </li>
51
+ ))}
52
+ </ul>
53
+ </div>
54
+ );
55
+ }
56
+
57
+ function FeaturedCard({ item, statusLabel }: { item: RoadmapItem; statusLabel: string }) {
58
+ return (
59
+ <article
60
+ style={{ '--lar-kind-hue': item.featured?.hue } as CSSProperties}
61
+ className="flex flex-col gap-4 rounded-2xl border border-[oklch(0.62_0.1_var(--lar-kind-hue)/0.45)] bg-[radial-gradient(60%_120%_at_85%_50%,oklch(0.62_0.12_var(--lar-kind-hue)/0.14),transparent_70%)] p-5 sm:flex-row sm:p-7"
62
+ >
63
+ <span className="flex items-center justify-between gap-3 sm:block">
64
+ <RoadmapIcon>{item.icon}</RoadmapIcon>
65
+ <span className="sm:hidden">
66
+ <StatusPill status="planned">{statusLabel}</StatusPill>
67
+ </span>
68
+ </span>
69
+ <div className="flex min-w-0 flex-1 flex-col gap-2">
70
+ <span className="flex items-start justify-between gap-3">
71
+ <span className="text-base-content text-lg font-semibold tracking-[-0.01em] text-balance sm:text-xl">
72
+ {item.title}
73
+ </span>
74
+ <span className="hidden shrink-0 sm:block">
75
+ <StatusPill status="planned">{statusLabel}</StatusPill>
76
+ </span>
77
+ </span>
78
+ <span className="text-base-700 max-w-[620px] text-[15px] leading-6">{item.body}</span>
79
+ {item.featured?.steps ? (
80
+ <ol className="text-base-800 mt-2 flex flex-col gap-2.5 text-sm">
81
+ {item.featured.steps.map((step, index) => (
82
+ <li key={step} className="flex items-center gap-2">
83
+ <span className="bg-base-200 text-base-800 dark:bg-base-300 inline-flex size-5 shrink-0 items-center justify-center rounded-full text-[11px] font-semibold tabular-nums">
84
+ {index + 1}
85
+ </span>
86
+ {step}
87
+ </li>
88
+ ))}
89
+ </ol>
90
+ ) : null}
91
+ <span className="mt-2 hidden flex-wrap gap-2 sm:flex">
92
+ {item.featured?.highlights.map((highlight) => (
93
+ <span
94
+ key={highlight}
95
+ className="kind-badge inline-flex h-7 items-center rounded-full px-3 text-xs font-medium"
96
+ >
97
+ {highlight}
98
+ </span>
99
+ ))}
100
+ </span>
101
+ </div>
102
+ {item.featured?.visual ? (
103
+ <div className="shrink-0 sm:w-[300px] lg:w-[340px]">{item.featured.visual}</div>
104
+ ) : null}
105
+ </article>
106
+ );
107
+ }
108
+
109
+ function RoadmapIcon({ children }: { children: ReactNode }) {
110
+ return (
111
+ <span className="bg-base-200 text-base-800 ring-base-300/70 dark:bg-base-300/40 inline-flex size-8 shrink-0 items-center justify-center rounded-[0.6rem] ring-1 ring-inset sm:size-10 sm:rounded-[0.7rem] [&>svg]:size-4 sm:[&>svg]:size-5">
112
+ {children}
113
+ </span>
114
+ );
115
+ }
@@ -0,0 +1,56 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export interface RouteNode {
4
+ icon: ReactNode;
5
+ title: string;
6
+ detail: string;
7
+ }
8
+
9
+ /** One connection from end to end, drawn as a line of travelling light through every node it passes, with
10
+ * what the connection is labelled once above it. */
11
+ export function RouteDiagram({
12
+ nodes,
13
+ label,
14
+ caption,
15
+ }: {
16
+ nodes: readonly RouteNode[];
17
+ label: string;
18
+ caption: ReactNode;
19
+ }) {
20
+ return (
21
+ <figure className="border-base-300 bg-base-100/70 dark:bg-base-100/50 relative isolate overflow-hidden rounded-[1.5rem] border px-6 py-8 sm:px-10 sm:py-12">
22
+ <div
23
+ aria-hidden="true"
24
+ className="absolute inset-0 -z-10 bg-[radial-gradient(60%_70%_at_50%_40%,var(--lar-glow-soft),transparent_70%)]"
25
+ />
26
+ <div className="mb-8 flex sm:justify-center">
27
+ <span className="border-primary/30 bg-primary/8 text-primary dark:bg-primary/16 inline-flex items-center gap-2 rounded-full border px-3 py-1 text-xs font-medium dark:text-[color-mix(in_srgb,var(--color-primary)_45%,white)]">
28
+ <span aria-hidden="true" className="size-1.5 rounded-full bg-current" />
29
+ {label}
30
+ </span>
31
+ </div>
32
+ <div className="relative">
33
+ <span
34
+ aria-hidden="true"
35
+ className="lar-route-line absolute top-6 bottom-6 left-[23px] w-[1.5px] sm:top-8 sm:right-[calc(100%/6)] sm:bottom-auto sm:left-[calc(100%/6)] sm:h-[1.5px] sm:w-auto"
36
+ />
37
+ <ol className="relative flex flex-col gap-6 sm:grid sm:grid-cols-3 sm:gap-4">
38
+ {nodes.map((node) => (
39
+ <li key={node.title} className="flex items-center gap-4 sm:flex-col sm:gap-3 sm:text-center">
40
+ <span className="border-base-300 bg-base-50 text-base-content inline-flex size-12 shrink-0 items-center justify-center rounded-[0.9rem] border shadow-[0_14px_30px_-16px_rgb(0_0_0/50%)] sm:size-16 sm:rounded-[1.1rem] [&>svg]:size-6 sm:[&>svg]:size-7">
41
+ {node.icon}
42
+ </span>
43
+ <span className="flex flex-col gap-0.5">
44
+ <span className="text-base-content text-sm font-semibold">{node.title}</span>
45
+ <span className="text-base-700 text-xs">{node.detail}</span>
46
+ </span>
47
+ </li>
48
+ ))}
49
+ </ol>
50
+ </div>
51
+ <figcaption className="text-base-700 mt-8 text-sm leading-6 text-pretty sm:mt-10 sm:text-center">
52
+ {caption}
53
+ </figcaption>
54
+ </figure>
55
+ );
56
+ }
@@ -0,0 +1,191 @@
1
+ import { type KeyboardEvent, type ReactNode, useId, useRef, useState } from 'react';
2
+
3
+ import { Heading, Text } from '../typography/Typography';
4
+ import { type Readiness, StatusLight, StatusPill } from './Status';
5
+
6
+ export type MediaApp = 'music' | 'video' | 'photos' | 'books';
7
+
8
+ export interface ServerBay {
9
+ id: MediaApp;
10
+ name: string;
11
+ status: Readiness;
12
+ statusLabel: string;
13
+ panel: ReactNode;
14
+ }
15
+
16
+ interface ServerUnitProps {
17
+ label: string;
18
+ /** The key for the bays' lights, set under the unit. */
19
+ legend?: ReactNode;
20
+ display: { name: string; state: string };
21
+ bays: readonly ServerBay[];
22
+ }
23
+
24
+ const MARK_L = 'M0 0H27.52V72.48H100V100H3a3 3 0 0 1-3-3z';
25
+ const MARK_S =
26
+ 'M50.68 0H91.97a8.03 8.03 0 0 1 8.03 8.03V49.32a8.03 8.03 0 0 1-8.03 8.03H50.68a8.03 8.03 0 0 1-8.03-8.03V8.03a8.03 8.03 0 0 1 8.03-8.03z';
27
+
28
+ /** The server as a four-bay box, one drive sled per media app. Choosing a sled pulls it forward and shows what
29
+ * that app can do today and what is still to come. */
30
+ export function ServerUnit({ label, display, bays, legend }: ServerUnitProps) {
31
+ const [selected, setSelected] = useState<MediaApp>(bays[0]?.id ?? 'music');
32
+ const tabs = useRef<(HTMLButtonElement | null)[]>([]);
33
+ const baseId = useId();
34
+ const current = bays.find((bay) => bay.id === selected) ?? bays[0];
35
+
36
+ function move(event: KeyboardEvent<HTMLButtonElement>, index: number) {
37
+ const keys: Record<string, number> = {
38
+ ArrowRight: 1,
39
+ ArrowDown: 1,
40
+ ArrowLeft: -1,
41
+ ArrowUp: -1,
42
+ };
43
+ const step = keys[event.key];
44
+ let next: number | undefined;
45
+
46
+ if (step !== undefined) next = (index + step + bays.length) % bays.length;
47
+
48
+ if (event.key === 'Home') next = 0;
49
+
50
+ if (event.key === 'End') next = bays.length - 1;
51
+
52
+ if (next === undefined) return;
53
+
54
+ event.preventDefault();
55
+
56
+ const bay = bays[next];
57
+
58
+ if (!bay) return;
59
+
60
+ setSelected(bay.id);
61
+ tabs.current[next]?.focus();
62
+ }
63
+
64
+ return (
65
+ <div className="grid items-start gap-10 lg:grid-cols-[minmax(0,7fr)_minmax(0,5fr)] lg:items-center lg:gap-14">
66
+ <div className="flex flex-col gap-8 [perspective:1600px]">
67
+ <div className="lar-unit [transform:rotateX(2deg)_rotateY(5deg)] transition-transform duration-700 hover:[transform:rotateX(1deg)_rotateY(3deg)]">
68
+ <div className="lar-unit__top" aria-hidden="true">
69
+ <svg viewBox="0 0 100 100" className="lar-unit__mark">
70
+ <path d={MARK_L} fill="#f4f4f5" />
71
+ <path d={MARK_S} fill="#355292" />
72
+ </svg>
73
+ <div className="lar-unit__lcd">
74
+ <span>{display.name}</span>
75
+ <b>{display.state}</b>
76
+ </div>
77
+ <div className="lar-unit__lights">
78
+ <i />
79
+ <i className="lar-led-pulse" />
80
+ </div>
81
+ </div>
82
+ <div role="tablist" aria-label={label} className="lar-unit__bays">
83
+ {bays.map((bay, index) => (
84
+ <button
85
+ key={bay.id}
86
+ ref={(element) => {
87
+ tabs.current[index] = element;
88
+ }}
89
+ type="button"
90
+ role="tab"
91
+ id={`${baseId}-${bay.id}-tab`}
92
+ aria-controls={`${baseId}-panel`}
93
+ aria-selected={bay.id === selected}
94
+ tabIndex={bay.id === selected ? 0 : -1}
95
+ data-app={bay.id}
96
+ data-status={bay.status}
97
+ onClick={() => setSelected(bay.id)}
98
+ onKeyDown={(event) => move(event, index)}
99
+ className="lar-sled"
100
+ >
101
+ <i
102
+ className="lar-sled__led lar-led-pulse"
103
+ style={{ ['--lar-led-delay' as string]: `${index * 420}ms` }}
104
+ />
105
+ <i className="lar-sled__vents" />
106
+ <span className="lar-sled__name">{bay.name}</span>
107
+ <span className="lar-sled__state">{bay.statusLabel}</span>
108
+ <i className="lar-sled__latch" />
109
+ </button>
110
+ ))}
111
+ </div>
112
+ </div>
113
+ {legend}
114
+ </div>
115
+ {current ? (
116
+ <div
117
+ role="tabpanel"
118
+ id={`${baseId}-panel`}
119
+ aria-labelledby={`${baseId}-${current.id}-tab`}
120
+ className="border-base-300 bg-base-100/70 dark:bg-base-100/50 rounded-[1.25rem] border p-5 sm:min-h-[420px] sm:p-7"
121
+ >
122
+ {current.panel}
123
+ </div>
124
+ ) : null}
125
+ </div>
126
+ );
127
+ }
128
+
129
+ export interface ReadinessItem {
130
+ label: string;
131
+ status: Readiness;
132
+ statusLabel: string;
133
+ }
134
+
135
+ interface ReadinessPanelProps {
136
+ icon: ReactNode;
137
+ title: string;
138
+ status: ReactNode;
139
+ summary: string;
140
+ groups: readonly { title: string; items: readonly ReadinessItem[]; wideOnly?: boolean }[];
141
+ }
142
+
143
+ /** One app's status: what works, what is being built and what is planned, line by line. */
144
+ export function ReadinessPanel({ icon, title, status, summary, groups }: ReadinessPanelProps) {
145
+ return (
146
+ <div className="flex flex-col gap-5">
147
+ <div className="flex items-center gap-3">
148
+ {icon}
149
+ <Heading as="h3" variant="feature">
150
+ {title}
151
+ </Heading>
152
+ <span className="ml-auto">{status}</span>
153
+ </div>
154
+ <Text variant="prose" tone="muted">
155
+ {summary}
156
+ </Text>
157
+ {groups.map((group) => (
158
+ <div key={group.title} className={`flex-col gap-2 ${group.wideOnly ? 'hidden sm:flex' : 'flex'}`}>
159
+ <Text as="span" variant="overline" tone="muted">
160
+ {group.title}
161
+ </Text>
162
+ <ul className="divide-base-300/70 flex flex-col divide-y">
163
+ {group.items.map((item) => (
164
+ <li
165
+ key={item.label}
166
+ className="text-base-800 flex items-center gap-3 py-1.5 text-sm sm:py-2"
167
+ >
168
+ <StatusLight status={item.status} />
169
+ <span className="min-w-0 flex-1">{item.label}</span>
170
+ <span className="text-base-700 shrink-0 text-xs">{item.statusLabel}</span>
171
+ </li>
172
+ ))}
173
+ </ul>
174
+ </div>
175
+ ))}
176
+ </div>
177
+ );
178
+ }
179
+
180
+ /** The key for the readiness lights. */
181
+ export function ReadinessLegend({ items }: { items: readonly { status: Readiness; label: string }[] }) {
182
+ return (
183
+ <div className="flex flex-wrap items-center justify-center gap-2">
184
+ {items.map((item) => (
185
+ <StatusPill key={item.status} status={item.status}>
186
+ {item.label}
187
+ </StatusPill>
188
+ ))}
189
+ </div>
190
+ );
191
+ }
@@ -0,0 +1,160 @@
1
+ import { type CSSProperties, type PointerEvent, type ReactNode, useRef } from 'react';
2
+
3
+ /** The navy glow and fading grid behind a hero. A hue tints the glow with a product's colour. */
4
+ export function Backdrop({ hue }: { hue?: number }) {
5
+ return (
6
+ <div
7
+ aria-hidden="true"
8
+ className="lar-backdrop"
9
+ data-hue={hue === undefined ? undefined : ''}
10
+ style={hue === undefined ? undefined : ({ '--lar-backdrop-hue': hue } as CSSProperties)}
11
+ />
12
+ );
13
+ }
14
+
15
+ interface DeviceStageProps {
16
+ /** The large device in the middle. */
17
+ main: ReactNode;
18
+ /** A device in front, at the lower right. */
19
+ end?: ReactNode;
20
+ /** A device in front, at the lower left; hidden on narrow screens. */
21
+ start?: ReactNode;
22
+ /** How far the scene leans back, in degrees. */
23
+ pitch?: number;
24
+ /** The start device's width: a tablet or TV at 'wide', a phone at 'narrow'. */
25
+ startSize?: 'wide' | 'narrow';
26
+ /** A close-up that floats in front, across the lower left; hidden on narrow screens. */
27
+ callout?: ReactNode;
28
+ /** How big the end device is: 'small' beside a hero laptop, 'large' when the phone is the point. */
29
+ endSize?: 'small' | 'large';
30
+ /** What a phone-width screen shows, where a laptop's text would be too small to read: the end device or the
31
+ * callout alone, or a readable close-up with the end device overlapping its corner. */
32
+ narrow?: 'stage' | 'end' | 'callout' | 'pair';
33
+ /** The close-up that 'pair' shows on phones. */
34
+ narrowMain?: ReactNode;
35
+ /** Which side a large end device stands on. */
36
+ endSide?: 'left' | 'right';
37
+ }
38
+
39
+ const MAX_TILT = 2.5;
40
+
41
+ /** A group of devices in perspective that leans gently toward the pointer. */
42
+ export function DeviceStage({
43
+ main,
44
+ end,
45
+ start,
46
+ callout,
47
+ pitch = 0,
48
+ startSize = 'wide',
49
+ endSize = 'small',
50
+ narrow = 'stage',
51
+ narrowMain,
52
+ endSide = 'right',
53
+ }: DeviceStageProps) {
54
+ const scene = useRef<HTMLDivElement>(null);
55
+
56
+ function lean(event: PointerEvent<HTMLDivElement>) {
57
+ const element = scene.current;
58
+
59
+ if (!element || event.pointerType !== 'mouse' || matchMedia('(prefers-reduced-motion: reduce)').matches) return;
60
+
61
+ const bounds = event.currentTarget.getBoundingClientRect();
62
+ const x = (event.clientX - bounds.left) / bounds.width - 0.5;
63
+ const y = (event.clientY - bounds.top) / bounds.height - 0.5;
64
+
65
+ element.style.setProperty('--lar-tilt-x', `${(-y * MAX_TILT).toFixed(2)}deg`);
66
+ element.style.setProperty('--lar-tilt-y', `${(x * MAX_TILT * 1.6).toFixed(2)}deg`);
67
+ }
68
+
69
+ function settle() {
70
+ scene.current?.style.removeProperty('--lar-tilt-x');
71
+ scene.current?.style.removeProperty('--lar-tilt-y');
72
+ }
73
+
74
+ const alone = narrow === 'end' ? end : narrow === 'callout' ? callout : undefined;
75
+ const pair = narrow === 'pair' && narrowMain;
76
+
77
+ return (
78
+ <>
79
+ {alone ? <div className="mx-auto w-[min(60%,220px)] sm:hidden">{alone}</div> : null}
80
+ {pair ? (
81
+ <div className={`relative sm:hidden ${end ? 'mr-6 mb-10' : ''}`}>
82
+ {narrowMain}
83
+ {end ? (
84
+ <div className="absolute -right-6 -bottom-10 w-[30%] max-w-[120px] rotate-[3deg]">{end}</div>
85
+ ) : null}
86
+ </div>
87
+ ) : null}
88
+ <div
89
+ className={`lar-stage ${alone || pair ? 'hidden sm:block' : ''}`}
90
+ onPointerMove={lean}
91
+ onPointerLeave={settle}
92
+ >
93
+ <div
94
+ ref={scene}
95
+ className={`lar-stage__scene ${endSize === 'large' ? 'grid grid-cols-1' : ''}`}
96
+ style={{ '--lar-stage-pitch': `${pitch}deg` } as CSSProperties}
97
+ >
98
+ <div
99
+ className={`lar-stage__slot relative ${endSize === 'large' ? `col-start-1 row-start-1 w-[92%] self-start sm:mt-[8%] sm:w-[84%] ${endSide === 'left' ? 'justify-self-end' : ''}` : ''}`}
100
+ >
101
+ {main}
102
+ </div>
103
+ {start ? (
104
+ <div
105
+ className={`lar-stage__slot absolute bottom-[-7%] left-[-2%] hidden [transform:translateZ(60px)_rotateY(9deg)] sm:block ${startSize === 'wide' ? 'w-[34%]' : 'w-[17%]'}`}
106
+ >
107
+ {start}
108
+ </div>
109
+ ) : null}
110
+ {callout ? (
111
+ <div className="lar-stage__slot absolute bottom-[-5%] left-[1%] hidden w-[30%] [transform:translateZ(120px)_rotateY(6deg)_rotateZ(-1.5deg)] md:block">
112
+ {callout}
113
+ </div>
114
+ ) : null}
115
+ {end ? (
116
+ <div
117
+ className={`lar-stage__slot ${endSize === 'large' ? `relative col-start-1 row-start-1 mt-[24%] w-[36%] self-start sm:mt-0 sm:w-[30%] ${endSide === 'left' ? 'justify-self-start sm:[transform:translateZ(90px)_rotateY(9deg)_rotateZ(-1deg)]' : 'justify-self-end sm:[transform:translateZ(90px)_rotateY(-9deg)_rotateZ(1deg)]'}` : 'absolute right-[-1%] bottom-[2%] w-[30%] [transform:translateZ(90px)_rotateY(-11deg)_rotateZ(1deg)] sm:w-[18%]'}`}
118
+ >
119
+ {end}
120
+ </div>
121
+ ) : null}
122
+ </div>
123
+ </div>
124
+ </>
125
+ );
126
+ }
127
+
128
+ /** One device turned in space, for a feature row. */
129
+ export function AngledDevice({
130
+ children,
131
+ angle = 'left',
132
+ }: {
133
+ children: ReactNode;
134
+ angle?: 'left' | 'right' | 'flat' | 'lean' | 'tilt';
135
+ }) {
136
+ const angles = {
137
+ left: 'sm:[transform:perspective(2400px)_rotateY(3deg)]',
138
+ right: 'sm:[transform:perspective(2400px)_rotateY(-3deg)]',
139
+ lean: 'sm:[transform:perspective(2600px)_rotateX(4deg)]',
140
+ tilt: 'sm:[transform:perspective(1600px)_rotateY(-6deg)_rotateX(3deg)]',
141
+ flat: '',
142
+ } as const;
143
+
144
+ return <div className={`transition-transform duration-700 ${angles[angle]}`}>{children}</div>;
145
+ }
146
+
147
+ /** Fades and lifts its content into place as it scrolls into view. */
148
+ export function Reveal({ children }: { children: ReactNode }) {
149
+ return <div className="lar-reveal">{children}</div>;
150
+ }
151
+
152
+ /** Shows the full composition on wider screens and a readable close-up on phones. */
153
+ export function ResponsiveMedia({ wide, narrow }: { wide: ReactNode; narrow: ReactNode }) {
154
+ return (
155
+ <>
156
+ <div className="hidden sm:block">{wide}</div>
157
+ <div className="sm:hidden">{narrow}</div>
158
+ </>
159
+ );
160
+ }