@lar-works/design-system 0.0.0-stage → 0.1.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.
- package/README.md +24 -2
- package/dist/actions/Button.d.ts +25 -0
- package/dist/actions/Button.js +55 -0
- package/dist/actions/Button.js.map +1 -0
- package/dist/actions/ButtonLink.d.ts +21 -0
- package/dist/actions/ButtonLink.js +40 -0
- package/dist/actions/ButtonLink.js.map +1 -0
- package/dist/actions/IconButton.d.ts +14 -0
- package/dist/actions/IconButton.js +29 -0
- package/dist/actions/IconButton.js.map +1 -0
- package/dist/actions/ThemeSwitch.d.ts +7 -0
- package/dist/actions/ThemeSwitch.js +42 -0
- package/dist/actions/ThemeSwitch.js.map +1 -0
- package/dist/actions/index.d.ts +5 -0
- package/dist/collections/CollectionSectionHeader.d.ts +5 -0
- package/dist/collections/CollectionSectionHeader.js +18 -0
- package/dist/collections/CollectionSectionHeader.js.map +1 -0
- package/dist/collections/CollectionState.d.ts +37 -0
- package/dist/collections/CollectionState.js +69 -0
- package/dist/collections/CollectionState.js.map +1 -0
- package/dist/collections/CollectionTokens.d.ts +16 -0
- package/dist/collections/CollectionTokens.js +19 -0
- package/dist/collections/CollectionTokens.js.map +1 -0
- package/dist/collections/CollectionViewport.js +36 -0
- package/dist/collections/CollectionViewport.js.map +1 -0
- package/dist/collections/DataRow.d.ts +23 -0
- package/dist/collections/DataRow.js +57 -0
- package/dist/collections/DataRow.js.map +1 -0
- package/dist/collections/ResultList.d.ts +29 -0
- package/dist/collections/ResultList.js +128 -0
- package/dist/collections/ResultList.js.map +1 -0
- package/dist/collections/ScrollRow.d.ts +23 -0
- package/dist/collections/ScrollRow.js +59 -0
- package/dist/collections/ScrollRow.js.map +1 -0
- package/dist/collections/VirtualGrid.d.ts +14 -0
- package/dist/collections/VirtualGrid.js +71 -0
- package/dist/collections/VirtualGrid.js.map +1 -0
- package/dist/collections/VirtualList.d.ts +34 -0
- package/dist/collections/VirtualList.js +128 -0
- package/dist/collections/VirtualList.js.map +1 -0
- package/dist/collections/index.d.ts +10 -0
- package/dist/collections/useCollectionMotion.d.ts +3 -0
- package/dist/collections/useCollectionMotion.js +34 -0
- package/dist/collections/useCollectionMotion.js.map +1 -0
- package/dist/collections/useScrollRow.d.ts +17 -0
- package/dist/collections/useScrollRow.js +63 -0
- package/dist/collections/useScrollRow.js.map +1 -0
- package/dist/display/ActivityCard.d.ts +17 -0
- package/dist/display/ActivityCard.js +58 -0
- package/dist/display/ActivityCard.js.map +1 -0
- package/dist/display/Artwork.d.ts +25 -0
- package/dist/display/Artwork.js +97 -0
- package/dist/display/Artwork.js.map +1 -0
- package/dist/display/Avatar.d.ts +5 -0
- package/dist/display/Avatar.js +13 -0
- package/dist/display/Avatar.js.map +1 -0
- package/dist/display/Badge.d.ts +10 -0
- package/dist/display/Badge.js +28 -0
- package/dist/display/Badge.js.map +1 -0
- package/dist/display/BadgeList.d.ts +11 -0
- package/dist/display/BadgeList.js +20 -0
- package/dist/display/BadgeList.js.map +1 -0
- package/dist/display/BrandMark.d.ts +21 -0
- package/dist/display/BrandMark.js +60 -0
- package/dist/display/BrandMark.js.map +1 -0
- package/dist/display/ChangeList.d.ts +16 -0
- package/dist/display/ChangeList.js +56 -0
- package/dist/display/ChangeList.js.map +1 -0
- package/dist/display/CheckList.d.ts +10 -0
- package/dist/display/CheckList.js +25 -0
- package/dist/display/CheckList.js.map +1 -0
- package/dist/display/CodeBlock.d.ts +6 -0
- package/dist/display/CodeBlock.js +12 -0
- package/dist/display/CodeBlock.js.map +1 -0
- package/dist/display/CopyButton.d.ts +9 -0
- package/dist/display/CopyButton.js +59 -0
- package/dist/display/CopyButton.js.map +1 -0
- package/dist/display/DataTable.d.ts +35 -0
- package/dist/display/DataTable.js +53 -0
- package/dist/display/DataTable.js.map +1 -0
- package/dist/display/DetailHero.d.ts +39 -0
- package/dist/display/DetailHero.js +146 -0
- package/dist/display/DetailHero.js.map +1 -0
- package/dist/display/DetailList.d.ts +15 -0
- package/dist/display/DetailList.js +53 -0
- package/dist/display/DetailList.js.map +1 -0
- package/dist/display/DeviceCard.d.ts +18 -0
- package/dist/display/DeviceCard.js +48 -0
- package/dist/display/DeviceCard.js.map +1 -0
- package/dist/display/Identity.d.ts +14 -0
- package/dist/display/Identity.js +54 -0
- package/dist/display/Identity.js.map +1 -0
- package/dist/display/ImageCard.d.ts +22 -0
- package/dist/display/ImageCard.js +63 -0
- package/dist/display/ImageCard.js.map +1 -0
- package/dist/display/ImagePicker.d.ts +30 -0
- package/dist/display/ImagePicker.js +108 -0
- package/dist/display/ImagePicker.js.map +1 -0
- package/dist/display/InfoBox.d.ts +15 -0
- package/dist/display/InfoBox.js +41 -0
- package/dist/display/InfoBox.js.map +1 -0
- package/dist/display/InsetPanel.d.ts +13 -0
- package/dist/display/InsetPanel.js +26 -0
- package/dist/display/InsetPanel.js.map +1 -0
- package/dist/display/ItemAction.d.ts +10 -0
- package/dist/display/ItemAction.js +35 -0
- package/dist/display/ItemAction.js.map +1 -0
- package/dist/display/Kbd.d.ts +6 -0
- package/dist/display/Kbd.js +12 -0
- package/dist/display/Kbd.js.map +1 -0
- package/dist/display/KindIcon.d.ts +8 -0
- package/dist/display/KindIcon.js +15 -0
- package/dist/display/KindIcon.js.map +1 -0
- package/dist/display/NoticeCard.d.ts +24 -0
- package/dist/display/NoticeCard.js +59 -0
- package/dist/display/NoticeCard.js.map +1 -0
- package/dist/display/PairingList.d.ts +19 -0
- package/dist/display/PairingList.js +53 -0
- package/dist/display/PairingList.js.map +1 -0
- package/dist/display/PathList.d.ts +9 -0
- package/dist/display/PathList.js +21 -0
- package/dist/display/PathList.js.map +1 -0
- package/dist/display/PeoplePreview.d.ts +16 -0
- package/dist/display/PeoplePreview.js +41 -0
- package/dist/display/PeoplePreview.js.map +1 -0
- package/dist/display/PropertySheet.d.ts +56 -0
- package/dist/display/PropertySheet.js +150 -0
- package/dist/display/PropertySheet.js.map +1 -0
- package/dist/display/QrCode.d.ts +6 -0
- package/dist/display/QrCode.js +47 -0
- package/dist/display/QrCode.js.map +1 -0
- package/dist/display/RadioChoice.d.ts +9 -0
- package/dist/display/RadioChoice.js +28 -0
- package/dist/display/RadioChoice.js.map +1 -0
- package/dist/display/RatingLink.d.ts +10 -0
- package/dist/display/RatingLink.js +80 -0
- package/dist/display/RatingLink.js.map +1 -0
- package/dist/display/ResourceCard.d.ts +20 -0
- package/dist/display/ResourceCard.js +200 -0
- package/dist/display/ResourceCard.js.map +1 -0
- package/dist/display/RowList.d.ts +28 -0
- package/dist/display/RowList.js +76 -0
- package/dist/display/RowList.js.map +1 -0
- package/dist/display/StackedMeter.d.ts +28 -0
- package/dist/display/StackedMeter.js +48 -0
- package/dist/display/StackedMeter.js.map +1 -0
- package/dist/display/StatTile.d.ts +13 -0
- package/dist/display/StatTile.js +35 -0
- package/dist/display/StatTile.js.map +1 -0
- package/dist/display/StepList.d.ts +5 -0
- package/dist/display/StepList.js +12 -0
- package/dist/display/StepList.js.map +1 -0
- package/dist/display/TextPreview.d.ts +14 -0
- package/dist/display/TextPreview.js +46 -0
- package/dist/display/TextPreview.js.map +1 -0
- package/dist/display/TimeSeriesChart.d.ts +19 -0
- package/dist/display/TimeSeriesChart.js +163 -0
- package/dist/display/TimeSeriesChart.js.map +1 -0
- package/dist/display/ToneTile.js +12 -0
- package/dist/display/ToneTile.js.map +1 -0
- package/dist/display/index.d.ts +38 -0
- package/dist/feedback/Alert.d.ts +15 -0
- package/dist/feedback/Alert.js +19 -0
- package/dist/feedback/Alert.js.map +1 -0
- package/dist/feedback/AsyncState.d.ts +16 -0
- package/dist/feedback/AsyncState.js +29 -0
- package/dist/feedback/AsyncState.js.map +1 -0
- package/dist/feedback/ErrorNotification.d.ts +8 -0
- package/dist/feedback/ErrorNotification.js +20 -0
- package/dist/feedback/ErrorNotification.js.map +1 -0
- package/dist/feedback/Notifications.d.ts +2 -0
- package/dist/feedback/Notifications.js +9 -0
- package/dist/feedback/Notifications.js.map +1 -0
- package/dist/feedback/ProgressStatusRow.d.ts +23 -0
- package/dist/feedback/ProgressStatusRow.js +74 -0
- package/dist/feedback/ProgressStatusRow.js.map +1 -0
- package/dist/feedback/SkeletonLoader.d.ts +19 -0
- package/dist/feedback/SkeletonLoader.js +59 -0
- package/dist/feedback/SkeletonLoader.js.map +1 -0
- package/dist/feedback/StatusIndicator.d.ts +9 -0
- package/dist/feedback/StatusIndicator.js +28 -0
- package/dist/feedback/StatusIndicator.js.map +1 -0
- package/dist/feedback/StatusPopoverContent.d.ts +13 -0
- package/dist/feedback/StatusPopoverContent.js +50 -0
- package/dist/feedback/StatusPopoverContent.js.map +1 -0
- package/dist/feedback/StatusRow.d.ts +16 -0
- package/dist/feedback/StatusRow.js +60 -0
- package/dist/feedback/StatusRow.js.map +1 -0
- package/dist/feedback/index.d.ts +11 -0
- package/dist/feedback/index.js +11 -0
- package/dist/forms/Checkbox.d.ts +10 -0
- package/dist/forms/Checkbox.js +48 -0
- package/dist/forms/Checkbox.js.map +1 -0
- package/dist/forms/Field.d.ts +5 -0
- package/dist/forms/Field.js +15 -0
- package/dist/forms/Field.js.map +1 -0
- package/dist/forms/FormControlStyles.js +14 -0
- package/dist/forms/FormControlStyles.js.map +1 -0
- package/dist/forms/FormSection.d.ts +48 -0
- package/dist/forms/FormSection.js +142 -0
- package/dist/forms/FormSection.js.map +1 -0
- package/dist/forms/InlineFields.d.ts +13 -0
- package/dist/forms/InlineFields.js +24 -0
- package/dist/forms/InlineFields.js.map +1 -0
- package/dist/forms/Input.d.ts +5 -0
- package/dist/forms/Input.js +18 -0
- package/dist/forms/Input.js.map +1 -0
- package/dist/forms/OptionSelect.d.ts +21 -0
- package/dist/forms/OptionSelect.js +28 -0
- package/dist/forms/OptionSelect.js.map +1 -0
- package/dist/forms/RadioGroup.d.ts +5 -0
- package/dist/forms/RadioGroup.js +35 -0
- package/dist/forms/RadioGroup.js.map +1 -0
- package/dist/forms/Select.d.ts +6 -0
- package/dist/forms/Select.js +36 -0
- package/dist/forms/Select.js.map +1 -0
- package/dist/forms/Switch.d.ts +4 -0
- package/dist/forms/Switch.js +16 -0
- package/dist/forms/Switch.js.map +1 -0
- package/dist/forms/TagInput.d.ts +19 -0
- package/dist/forms/TagInput.js +60 -0
- package/dist/forms/TagInput.js.map +1 -0
- package/dist/forms/Textarea.d.ts +4 -0
- package/dist/forms/Textarea.js +15 -0
- package/dist/forms/Textarea.js.map +1 -0
- package/dist/forms/index.d.ts +12 -0
- package/dist/foundations/DesignSystemProvider.d.ts +64 -0
- package/dist/foundations/DesignSystemProvider.js +66 -0
- package/dist/foundations/DesignSystemProvider.js.map +1 -0
- package/dist/foundations/KeyboardFocus.d.ts +9 -0
- package/dist/foundations/KeyboardFocus.js +10 -0
- package/dist/foundations/KeyboardFocus.js.map +1 -0
- package/dist/foundations/KeyboardShortcut.d.ts +5 -0
- package/dist/foundations/KeyboardShortcut.js +10 -0
- package/dist/foundations/KeyboardShortcut.js.map +1 -0
- package/dist/foundations/Theme.d.ts +14 -0
- package/dist/foundations/Theme.js +56 -0
- package/dist/foundations/Theme.js.map +1 -0
- package/dist/foundations/index.d.ts +5 -0
- package/dist/icons/BrandIcons.d.ts +3 -0
- package/dist/icons/BrandIcons.js +14 -0
- package/dist/icons/BrandIcons.js.map +1 -0
- package/dist/icons/index.d.ts +3 -0
- package/dist/icons/index.js +2 -0
- package/dist/icons.d.ts +4 -0
- package/dist/icons.js +2 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +125 -0
- package/dist/layout/AppShell.d.ts +11 -0
- package/dist/layout/AppShell.js +46 -0
- package/dist/layout/AppShell.js.map +1 -0
- package/dist/layout/AuthLayout.d.ts +11 -0
- package/dist/layout/AuthLayout.js +48 -0
- package/dist/layout/AuthLayout.js.map +1 -0
- package/dist/layout/ContentContainer.d.ts +9 -0
- package/dist/layout/ContentContainer.js +15 -0
- package/dist/layout/ContentContainer.js.map +1 -0
- package/dist/layout/Flow.d.ts +26 -0
- package/dist/layout/Flow.js +65 -0
- package/dist/layout/Flow.js.map +1 -0
- package/dist/layout/PageLayout.d.ts +12 -0
- package/dist/layout/PageLayout.js +31 -0
- package/dist/layout/PageLayout.js.map +1 -0
- package/dist/layout/PageSection.d.ts +43 -0
- package/dist/layout/PageSection.js +63 -0
- package/dist/layout/PageSection.js.map +1 -0
- package/dist/layout/ScrollArea.d.ts +4 -0
- package/dist/layout/ScrollArea.js +11 -0
- package/dist/layout/ScrollArea.js.map +1 -0
- package/dist/layout/Section.d.ts +12 -0
- package/dist/layout/Section.js +36 -0
- package/dist/layout/Section.js.map +1 -0
- package/dist/layout/Site.d.ts +41 -0
- package/dist/layout/Site.js +157 -0
- package/dist/layout/Site.js.map +1 -0
- package/dist/layout/TitleBar.d.ts +28 -0
- package/dist/layout/TitleBar.js +83 -0
- package/dist/layout/TitleBar.js.map +1 -0
- package/dist/layout/WorkspaceActionsHeader.d.ts +8 -0
- package/dist/layout/WorkspaceActionsHeader.js +18 -0
- package/dist/layout/WorkspaceActionsHeader.js.map +1 -0
- package/dist/layout/index.d.ts +19 -0
- package/dist/layout/index.js +19 -0
- package/dist/layout/sidebar/SidebarNavigationItem.d.ts +10 -0
- package/dist/layout/sidebar/SidebarNavigationItem.js +36 -0
- package/dist/layout/sidebar/SidebarNavigationItem.js.map +1 -0
- package/dist/layout/sidebar/SidebarPane.d.ts +13 -0
- package/dist/layout/sidebar/SidebarPane.js +30 -0
- package/dist/layout/sidebar/SidebarPane.js.map +1 -0
- package/dist/layout/toolbar/CommandPaletteTrigger.d.ts +11 -0
- package/dist/layout/toolbar/CommandPaletteTrigger.js +46 -0
- package/dist/layout/toolbar/CommandPaletteTrigger.js.map +1 -0
- package/dist/layout/toolbar/ToolbarStatusGroup.d.ts +5 -0
- package/dist/layout/toolbar/ToolbarStatusGroup.js +14 -0
- package/dist/layout/toolbar/ToolbarStatusGroup.js.map +1 -0
- package/dist/layout/toolbar/ToolbarStatusItem.d.ts +9 -0
- package/dist/layout/toolbar/ToolbarStatusItem.js +18 -0
- package/dist/layout/toolbar/ToolbarStatusItem.js.map +1 -0
- package/dist/navigation/ArtworkTabs.d.ts +18 -0
- package/dist/navigation/ArtworkTabs.js +72 -0
- package/dist/navigation/ArtworkTabs.js.map +1 -0
- package/dist/navigation/Breadcrumbs.d.ts +13 -0
- package/dist/navigation/Breadcrumbs.js +32 -0
- package/dist/navigation/Breadcrumbs.js.map +1 -0
- package/dist/navigation/CollectionBrowseSelector.d.ts +22 -0
- package/dist/navigation/CollectionBrowseSelector.js +70 -0
- package/dist/navigation/CollectionBrowseSelector.js.map +1 -0
- package/dist/navigation/CollectionViewToggle.d.ts +12 -0
- package/dist/navigation/CollectionViewToggle.js +36 -0
- package/dist/navigation/CollectionViewToggle.js.map +1 -0
- package/dist/navigation/DrilldownBrowseSelector.d.ts +31 -0
- package/dist/navigation/DrilldownBrowseSelector.js +174 -0
- package/dist/navigation/DrilldownBrowseSelector.js.map +1 -0
- package/dist/navigation/FolderSelector.d.ts +24 -0
- package/dist/navigation/FolderSelector.js +142 -0
- package/dist/navigation/FolderSelector.js.map +1 -0
- package/dist/navigation/TabKeys.js +13 -0
- package/dist/navigation/TabKeys.js.map +1 -0
- package/dist/navigation/ViewTabs.d.ts +19 -0
- package/dist/navigation/ViewTabs.js +48 -0
- package/dist/navigation/ViewTabs.js.map +1 -0
- package/dist/navigation/index.d.ts +8 -0
- package/dist/overlays/ActionModal.d.ts +21 -0
- package/dist/overlays/ActionModal.js +48 -0
- package/dist/overlays/ActionModal.js.map +1 -0
- package/dist/overlays/CommandPalette.d.ts +43 -0
- package/dist/overlays/CommandPalette.js +163 -0
- package/dist/overlays/CommandPalette.js.map +1 -0
- package/dist/overlays/Drawer.d.ts +19 -0
- package/dist/overlays/Drawer.js +83 -0
- package/dist/overlays/Drawer.js.map +1 -0
- package/dist/overlays/DropdownMenu.d.ts +47 -0
- package/dist/overlays/DropdownMenu.js +58 -0
- package/dist/overlays/DropdownMenu.js.map +1 -0
- package/dist/overlays/ImageViewer.d.ts +21 -0
- package/dist/overlays/ImageViewer.js +82 -0
- package/dist/overlays/ImageViewer.js.map +1 -0
- package/dist/overlays/Modal.d.ts +36 -0
- package/dist/overlays/Modal.js +149 -0
- package/dist/overlays/Modal.js.map +1 -0
- package/dist/overlays/Popover.d.ts +19 -0
- package/dist/overlays/Popover.js +26 -0
- package/dist/overlays/Popover.js.map +1 -0
- package/dist/overlays/Tooltip.d.ts +12 -0
- package/dist/overlays/Tooltip.js +54 -0
- package/dist/overlays/Tooltip.js.map +1 -0
- package/dist/overlays/index.d.ts +9 -0
- package/dist/overlays/useModalAutoFocus.js +84 -0
- package/dist/overlays/useModalAutoFocus.js.map +1 -0
- package/dist/overlays/useScrollFade.js +43 -0
- package/dist/overlays/useScrollFade.js.map +1 -0
- package/dist/showcase/CallToAction.d.ts +11 -0
- package/dist/showcase/CallToAction.js +54 -0
- package/dist/showcase/CallToAction.js.map +1 -0
- package/dist/showcase/Cards.d.ts +34 -0
- package/dist/showcase/Cards.js +122 -0
- package/dist/showcase/Cards.js.map +1 -0
- package/dist/showcase/Devices.d.ts +72 -0
- package/dist/showcase/Devices.js +249 -0
- package/dist/showcase/Devices.js.map +1 -0
- package/dist/showcase/FeatureRow.d.ts +30 -0
- package/dist/showcase/FeatureRow.js +91 -0
- package/dist/showcase/FeatureRow.js.map +1 -0
- package/dist/showcase/Hero.d.ts +15 -0
- package/dist/showcase/Hero.js +73 -0
- package/dist/showcase/Hero.js.map +1 -0
- package/dist/showcase/PhotoSearchConcept.d.ts +14 -0
- package/dist/showcase/PhotoSearchConcept.js +43 -0
- package/dist/showcase/PhotoSearchConcept.js.map +1 -0
- package/dist/showcase/Platforms.d.ts +15 -0
- package/dist/showcase/Platforms.js +48 -0
- package/dist/showcase/Platforms.js.map +1 -0
- package/dist/showcase/ProductBand.d.ts +38 -0
- package/dist/showcase/ProductBand.js +120 -0
- package/dist/showcase/ProductBand.js.map +1 -0
- package/dist/showcase/Roadmap.d.ts +21 -0
- package/dist/showcase/Roadmap.js +111 -0
- package/dist/showcase/Roadmap.js.map +1 -0
- package/dist/showcase/RouteDiagram.d.ts +14 -0
- package/dist/showcase/RouteDiagram.js +57 -0
- package/dist/showcase/RouteDiagram.js.map +1 -0
- package/dist/showcase/ServerUnit.d.ts +50 -0
- package/dist/showcase/ServerUnit.js +175 -0
- package/dist/showcase/ServerUnit.js.map +1 -0
- package/dist/showcase/Stage.d.ts +46 -0
- package/dist/showcase/Stage.js +106 -0
- package/dist/showcase/Stage.js.map +1 -0
- package/dist/showcase/Status.d.ts +30 -0
- package/dist/showcase/Status.js +84 -0
- package/dist/showcase/Status.js.map +1 -0
- package/dist/showcase/StepFlow.d.ts +13 -0
- package/dist/showcase/StepFlow.js +47 -0
- package/dist/showcase/StepFlow.js.map +1 -0
- package/dist/showcase/index.d.ts +15 -0
- package/dist/testing.d.ts +5 -0
- package/dist/testing.js +43 -0
- package/dist/testing.js.map +1 -0
- package/dist/typography/Link.d.ts +21 -0
- package/dist/typography/Link.js +60 -0
- package/dist/typography/Link.js.map +1 -0
- package/dist/typography/Typography.d.ts +53 -0
- package/dist/typography/Typography.js +67 -0
- package/dist/typography/Typography.js.map +1 -0
- package/dist/typography/index.d.ts +4 -0
- package/dist/typography/index.js +4 -0
- package/package.json +80 -3
- package/src/actions/Button.tsx +68 -0
- package/src/actions/ButtonLink.tsx +75 -0
- package/src/actions/IconButton.tsx +55 -0
- package/src/actions/ThemeSwitch.tsx +46 -0
- package/src/actions/index.ts +4 -0
- package/src/collections/CollectionSectionHeader.tsx +13 -0
- package/src/collections/CollectionState.tsx +76 -0
- package/src/collections/CollectionTokens.ts +12 -0
- package/src/collections/CollectionViewport.ts +40 -0
- package/src/collections/DataRow.tsx +79 -0
- package/src/collections/ResultList.tsx +164 -0
- package/src/collections/ScrollRow.tsx +90 -0
- package/src/collections/VirtualGrid.tsx +92 -0
- package/src/collections/VirtualList.tsx +224 -0
- package/src/collections/index.ts +10 -0
- package/src/collections/useCollectionMotion.ts +42 -0
- package/src/collections/useScrollRow.ts +64 -0
- package/src/display/ActivityCard.tsx +76 -0
- package/src/display/Artwork.tsx +140 -0
- package/src/display/Avatar.tsx +7 -0
- package/src/display/Badge.tsx +33 -0
- package/src/display/BadgeList.tsx +25 -0
- package/src/display/BrandMark.tsx +72 -0
- package/src/display/ChangeList.tsx +41 -0
- package/src/display/CheckList.tsx +27 -0
- package/src/display/CodeBlock.tsx +12 -0
- package/src/display/CopyButton.tsx +77 -0
- package/src/display/DataTable.tsx +80 -0
- package/src/display/DetailHero.tsx +191 -0
- package/src/display/DetailList.tsx +74 -0
- package/src/display/DeviceCard.tsx +49 -0
- package/src/display/Identity.tsx +56 -0
- package/src/display/ImageCard.tsx +102 -0
- package/src/display/ImagePicker.tsx +149 -0
- package/src/display/InfoBox.tsx +48 -0
- package/src/display/InsetPanel.tsx +37 -0
- package/src/display/ItemAction.tsx +53 -0
- package/src/display/Kbd.tsx +6 -0
- package/src/display/KindIcon.tsx +15 -0
- package/src/display/NoticeCard.tsx +77 -0
- package/src/display/PairingList.tsx +55 -0
- package/src/display/PathList.tsx +16 -0
- package/src/display/PeoplePreview.tsx +66 -0
- package/src/display/PropertySheet.tsx +180 -0
- package/src/display/QrCode.tsx +47 -0
- package/src/display/RadioChoice.tsx +34 -0
- package/src/display/RatingLink.tsx +76 -0
- package/src/display/ResourceCard.tsx +201 -0
- package/src/display/RowList.tsx +110 -0
- package/src/display/StackedMeter.tsx +72 -0
- package/src/display/StatTile.tsx +39 -0
- package/src/display/StepList.tsx +10 -0
- package/src/display/TextPreview.tsx +66 -0
- package/src/display/TimeSeriesChart.tsx +191 -0
- package/src/display/ToneTile.ts +10 -0
- package/src/display/index.ts +37 -0
- package/src/feedback/Alert.tsx +35 -0
- package/src/feedback/AsyncState.tsx +56 -0
- package/src/feedback/ErrorNotification.ts +24 -0
- package/src/feedback/Notifications.tsx +5 -0
- package/src/feedback/ProgressStatusRow.tsx +104 -0
- package/src/feedback/SkeletonLoader.tsx +88 -0
- package/src/feedback/StatusIndicator.tsx +28 -0
- package/src/feedback/StatusPopoverContent.tsx +54 -0
- package/src/feedback/StatusRow.tsx +70 -0
- package/src/feedback/index.ts +15 -0
- package/src/forms/Checkbox.tsx +61 -0
- package/src/forms/Field.tsx +17 -0
- package/src/forms/FormControlStyles.ts +9 -0
- package/src/forms/FormSection.tsx +175 -0
- package/src/forms/InlineFields.tsx +22 -0
- package/src/forms/Input.tsx +22 -0
- package/src/forms/OptionSelect.tsx +49 -0
- package/src/forms/RadioGroup.tsx +48 -0
- package/src/forms/Select.tsx +46 -0
- package/src/forms/Switch.tsx +10 -0
- package/src/forms/TagInput.tsx +76 -0
- package/src/forms/Textarea.tsx +14 -0
- package/src/forms/index.ts +11 -0
- package/src/foundations/DesignSystemProvider.tsx +79 -0
- package/src/foundations/KeyboardFocus.ts +6 -0
- package/src/foundations/KeyboardShortcut.ts +12 -0
- package/src/foundations/Theme.ts +75 -0
- package/src/foundations/index.ts +10 -0
- package/src/foundations/theme.css +425 -0
- package/src/icons/BrandIcons.tsx +8 -0
- package/src/icons/index.ts +4 -0
- package/src/icons.ts +1 -0
- package/src/index.ts +13 -0
- package/src/layout/AppShell.tsx +63 -0
- package/src/layout/AuthLayout.tsx +40 -0
- package/src/layout/ContentContainer.tsx +16 -0
- package/src/layout/Flow.tsx +56 -0
- package/src/layout/PageLayout.tsx +35 -0
- package/src/layout/PageSection.tsx +103 -0
- package/src/layout/ScrollArea.tsx +7 -0
- package/src/layout/Section.tsx +36 -0
- package/src/layout/Site.tsx +205 -0
- package/src/layout/TitleBar.tsx +97 -0
- package/src/layout/WorkspaceActionsHeader.tsx +17 -0
- package/src/layout/index.ts +18 -0
- package/src/layout/sidebar/SidebarNavigationItem.tsx +45 -0
- package/src/layout/sidebar/SidebarPane.tsx +37 -0
- package/src/layout/toolbar/CommandPaletteTrigger.tsx +53 -0
- package/src/layout/toolbar/ToolbarStatusGroup.tsx +9 -0
- package/src/layout/toolbar/ToolbarStatusItem.tsx +18 -0
- package/src/navigation/ArtworkTabs.tsx +107 -0
- package/src/navigation/Breadcrumbs.tsx +31 -0
- package/src/navigation/CollectionBrowseSelector.tsx +90 -0
- package/src/navigation/CollectionViewToggle.tsx +52 -0
- package/src/navigation/DrilldownBrowseSelector.tsx +229 -0
- package/src/navigation/FolderSelector.tsx +172 -0
- package/src/navigation/TabKeys.ts +21 -0
- package/src/navigation/ViewTabs.tsx +85 -0
- package/src/navigation/index.ts +15 -0
- package/src/overlays/ActionModal.tsx +81 -0
- package/src/overlays/CommandPalette.tsx +199 -0
- package/src/overlays/Drawer.tsx +107 -0
- package/src/overlays/DropdownMenu.tsx +122 -0
- package/src/overlays/ImageViewer.tsx +96 -0
- package/src/overlays/Modal.tsx +234 -0
- package/src/overlays/Popover.tsx +40 -0
- package/src/overlays/Tooltip.tsx +56 -0
- package/src/overlays/index.ts +8 -0
- package/src/overlays/useModalAutoFocus.ts +119 -0
- package/src/overlays/useScrollFade.ts +49 -0
- package/src/showcase/CallToAction.tsx +46 -0
- package/src/showcase/Cards.tsx +133 -0
- package/src/showcase/Devices.tsx +259 -0
- package/src/showcase/FeatureRow.tsx +107 -0
- package/src/showcase/Hero.tsx +70 -0
- package/src/showcase/PhotoSearchConcept.tsx +50 -0
- package/src/showcase/Platforms.tsx +49 -0
- package/src/showcase/ProductBand.tsx +148 -0
- package/src/showcase/Roadmap.tsx +115 -0
- package/src/showcase/RouteDiagram.tsx +56 -0
- package/src/showcase/ServerUnit.tsx +191 -0
- package/src/showcase/Stage.tsx +160 -0
- package/src/showcase/Status.tsx +107 -0
- package/src/showcase/StepFlow.tsx +48 -0
- package/src/showcase/devices.css +441 -0
- package/src/showcase/index.ts +34 -0
- package/src/showcase/server-unit.css +258 -0
- package/src/showcase/stage.css +175 -0
- package/src/styles.css +5 -0
- package/src/testing.ts +34 -0
- package/src/typography/Link.tsx +105 -0
- package/src/typography/Typography.tsx +113 -0
- 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
|
+
}
|