@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,133 @@
|
|
|
1
|
+
import { ArrowRightIcon } from 'lucide-react';
|
|
2
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
import { tabbable } from '../foundations/KeyboardFocus';
|
|
5
|
+
import { Heading, Text } from '../typography/Typography';
|
|
6
|
+
|
|
7
|
+
interface ProductCardProps {
|
|
8
|
+
/** A lar-brand app hue; omit for Factory's neutral graphite. */
|
|
9
|
+
hue?: number;
|
|
10
|
+
icon: ReactNode;
|
|
11
|
+
name: string;
|
|
12
|
+
status: ReactNode;
|
|
13
|
+
title: string;
|
|
14
|
+
description: string;
|
|
15
|
+
linkLabel: string;
|
|
16
|
+
href: string;
|
|
17
|
+
onNavigate: (href: string) => void;
|
|
18
|
+
media: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** A product on the home page: its name and promise above a screenshot that runs off the card's edge. */
|
|
22
|
+
export function ProductCard({
|
|
23
|
+
hue,
|
|
24
|
+
icon,
|
|
25
|
+
name,
|
|
26
|
+
status,
|
|
27
|
+
title,
|
|
28
|
+
description,
|
|
29
|
+
linkLabel,
|
|
30
|
+
href,
|
|
31
|
+
onNavigate,
|
|
32
|
+
media,
|
|
33
|
+
}: ProductCardProps) {
|
|
34
|
+
return (
|
|
35
|
+
<article
|
|
36
|
+
className="group/product border-base-300 bg-base-100 hover:border-base-400 dark:bg-base-100/80 relative isolate flex flex-col overflow-hidden rounded-[1.5rem] border shadow-[0_1px_0_rgb(255_255_255/4%)_inset] transition-[border-color,box-shadow] duration-300 hover:shadow-[0_30px_80px_-40px_rgb(0_0_0/45%)]"
|
|
37
|
+
style={
|
|
38
|
+
{ '--lar-card-hue': hue ?? 264, '--lar-card-chroma': hue === undefined ? 0.01 : 0.12 } as CSSProperties
|
|
39
|
+
}
|
|
40
|
+
>
|
|
41
|
+
<div
|
|
42
|
+
aria-hidden="true"
|
|
43
|
+
className="absolute inset-0 -z-10 bg-[radial-gradient(80%_60%_at_100%_0%,oklch(0.6_var(--lar-card-chroma)_var(--lar-card-hue)/0.16),transparent_70%)] transition-opacity duration-500 group-hover/product:opacity-150 dark:bg-[radial-gradient(80%_60%_at_100%_0%,oklch(0.5_var(--lar-card-chroma)_var(--lar-card-hue)/0.3),transparent_70%)]"
|
|
44
|
+
/>
|
|
45
|
+
<div className="flex flex-col gap-5 p-7 pb-8 sm:p-9 sm:pb-10">
|
|
46
|
+
<div className="flex items-center gap-3">
|
|
47
|
+
{icon}
|
|
48
|
+
<div className="flex min-w-0 flex-col">
|
|
49
|
+
<Text as="span" variant="label">
|
|
50
|
+
{name}
|
|
51
|
+
</Text>
|
|
52
|
+
</div>
|
|
53
|
+
<span className="ml-auto">{status}</span>
|
|
54
|
+
</div>
|
|
55
|
+
<Heading as="h3" variant="feature" className="max-w-[440px]">
|
|
56
|
+
{title}
|
|
57
|
+
</Heading>
|
|
58
|
+
<Text variant="prose" tone="muted" className="max-w-[460px]">
|
|
59
|
+
{description}
|
|
60
|
+
</Text>
|
|
61
|
+
<a
|
|
62
|
+
{...tabbable}
|
|
63
|
+
href={href}
|
|
64
|
+
onClick={(event) => {
|
|
65
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.button !== 0) return;
|
|
66
|
+
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
onNavigate(href);
|
|
69
|
+
}}
|
|
70
|
+
className="text-base-content focus-visible:before:outline-primary inline-flex w-fit items-center gap-1.5 text-[15px] font-medium before:absolute before:inset-0 before:z-10 before:rounded-[inherit] focus-visible:outline-none focus-visible:before:outline-2 focus-visible:before:outline-offset-[-2px] [&_svg]:size-4"
|
|
71
|
+
>
|
|
72
|
+
{linkLabel}
|
|
73
|
+
<span className="inline-flex transition-transform duration-200 group-hover/product:translate-x-1">
|
|
74
|
+
<ArrowRightIcon />
|
|
75
|
+
</span>
|
|
76
|
+
</a>
|
|
77
|
+
</div>
|
|
78
|
+
<div className="relative h-[240px] overflow-hidden [mask-image:linear-gradient(to_bottom,#000_calc(100%-56px),transparent)] pl-7 sm:h-[320px] sm:pl-9">
|
|
79
|
+
<div className="transition-transform duration-700 ease-[cubic-bezier(0.16,1,0.3,1)] group-hover/product:-translate-y-2">
|
|
80
|
+
{media}
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</article>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Two or three product cards side by side. */
|
|
88
|
+
export function ProductGrid({ children }: { children: ReactNode }) {
|
|
89
|
+
return <div className="grid gap-5 lg:grid-cols-2">{children}</div>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface FeatureTileProps {
|
|
93
|
+
icon: ReactNode;
|
|
94
|
+
title: string;
|
|
95
|
+
children: ReactNode;
|
|
96
|
+
hue?: number;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** A short benefit: an icon in a tinted square, a title and a sentence or two. */
|
|
100
|
+
export function FeatureTile({ icon, title, children, hue }: FeatureTileProps) {
|
|
101
|
+
return (
|
|
102
|
+
<div className="sm:border-base-300/80 sm:bg-base-100/60 sm:dark:bg-base-100/40 grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 p-4 sm:flex sm:flex-col sm:gap-3 sm:rounded-[1.125rem] sm:border sm:p-6">
|
|
103
|
+
<span
|
|
104
|
+
className={`row-span-2 inline-flex size-8 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 ${hue === undefined ? 'bg-primary/10 text-primary ring-primary/15 dark:bg-primary/20 dark:ring-primary/30 dark:text-[color-mix(in_srgb,var(--color-primary)_45%,white)]' : 'kind-badge ring-current/10'}`}
|
|
105
|
+
style={hue === undefined ? undefined : ({ '--lar-kind-hue': hue } as CSSProperties)}
|
|
106
|
+
>
|
|
107
|
+
{icon}
|
|
108
|
+
</span>
|
|
109
|
+
<Heading as="h3" variant="subsection" className="self-center sm:mt-1 sm:self-auto">
|
|
110
|
+
{title}
|
|
111
|
+
</Heading>
|
|
112
|
+
<Text variant="prose" tone="muted" className="col-start-2">
|
|
113
|
+
{children}
|
|
114
|
+
</Text>
|
|
115
|
+
</div>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function FeatureGrid({ children, columns = 3 }: { children: ReactNode; columns?: 2 | 3 | 4 }) {
|
|
120
|
+
const layouts = {
|
|
121
|
+
2: 'sm:grid-cols-2',
|
|
122
|
+
3: 'sm:grid-cols-2 lg:grid-cols-3',
|
|
123
|
+
4: 'sm:grid-cols-2 lg:grid-cols-4',
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div
|
|
128
|
+
className={`divide-base-300/70 border-base-300/80 bg-base-100/60 dark:bg-base-100/40 grid divide-y rounded-2xl border sm:gap-4 sm:divide-y-0 sm:rounded-none sm:border-0 sm:bg-transparent sm:dark:bg-transparent ${layouts[columns]}`}
|
|
129
|
+
>
|
|
130
|
+
{children}
|
|
131
|
+
</div>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface ScreenshotProps {
|
|
4
|
+
/** The screenshot shown with the dark theme, and with both when there is no light one. */
|
|
5
|
+
dark: string;
|
|
6
|
+
light?: string;
|
|
7
|
+
alt: string;
|
|
8
|
+
/** Loads at once, for the first screen of a page. */
|
|
9
|
+
eager?: boolean;
|
|
10
|
+
/** Natural pixel size, so the browser can reserve the space before the image arrives. */
|
|
11
|
+
width?: number;
|
|
12
|
+
height?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A product screenshot that follows the page's theme when it has a light and a dark capture. */
|
|
16
|
+
export function Screenshot({ dark, light, alt, eager, width, height }: ScreenshotProps) {
|
|
17
|
+
const loading = eager ? 'eager' : 'lazy';
|
|
18
|
+
const priority = eager ? 'high' : 'auto';
|
|
19
|
+
|
|
20
|
+
if (!light)
|
|
21
|
+
return (
|
|
22
|
+
<img
|
|
23
|
+
src={dark}
|
|
24
|
+
alt={alt}
|
|
25
|
+
loading={loading}
|
|
26
|
+
fetchPriority={priority}
|
|
27
|
+
width={width}
|
|
28
|
+
height={height}
|
|
29
|
+
decoding="async"
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<>
|
|
35
|
+
<img
|
|
36
|
+
src={light}
|
|
37
|
+
alt={alt}
|
|
38
|
+
loading={loading}
|
|
39
|
+
fetchPriority={priority}
|
|
40
|
+
width={width}
|
|
41
|
+
height={height}
|
|
42
|
+
decoding="async"
|
|
43
|
+
className="dark:hidden!"
|
|
44
|
+
/>
|
|
45
|
+
<img
|
|
46
|
+
src={dark}
|
|
47
|
+
alt={alt}
|
|
48
|
+
loading={loading}
|
|
49
|
+
width={width}
|
|
50
|
+
height={height}
|
|
51
|
+
decoding="async"
|
|
52
|
+
className="hidden! dark:block!"
|
|
53
|
+
/>
|
|
54
|
+
</>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface FrameProps {
|
|
59
|
+
children: ReactNode;
|
|
60
|
+
/** A soft contact shadow under the device. */
|
|
61
|
+
shadow?: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** A MacBook Pro: a notched display with the macOS menu bar, on an aluminium base that follows the theme. */
|
|
65
|
+
export function LaptopFrame({
|
|
66
|
+
children,
|
|
67
|
+
shadow = true,
|
|
68
|
+
app,
|
|
69
|
+
menu = [],
|
|
70
|
+
time,
|
|
71
|
+
}: FrameProps & { app: string; menu?: readonly string[]; time?: string }) {
|
|
72
|
+
return (
|
|
73
|
+
<div className="lar-device lar-laptop" data-shadow={shadow ? 'float' : undefined}>
|
|
74
|
+
<div className="lar-laptop__lid">
|
|
75
|
+
<div className="lar-laptop__screen">
|
|
76
|
+
<div className="lar-laptop__menubar" aria-hidden="true">
|
|
77
|
+
<LarMenuMark />
|
|
78
|
+
<span>{app}</span>
|
|
79
|
+
{menu.map((item) => (
|
|
80
|
+
<span key={item}>{item}</span>
|
|
81
|
+
))}
|
|
82
|
+
{time ? <time>{time}</time> : null}
|
|
83
|
+
</div>
|
|
84
|
+
<div className="lar-laptop__notch" aria-hidden="true" />
|
|
85
|
+
<div className="lar-laptop__app">{children}</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
<div className="lar-laptop__base" aria-hidden="true" />
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The menu bar's leading glyph: the Lar mark stands in for the Apple menu, so the frame claims no one's logo. */
|
|
94
|
+
function LarMenuMark() {
|
|
95
|
+
return (
|
|
96
|
+
<svg viewBox="0 0 100 100" className="size-[1.3cqi] shrink-0" aria-hidden="true">
|
|
97
|
+
<path d="M0 0H27.52V72.48H100V100H3a3 3 0 0 1-3-3z" fill="currentColor" />
|
|
98
|
+
<path
|
|
99
|
+
d="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"
|
|
100
|
+
fill="currentColor"
|
|
101
|
+
/>
|
|
102
|
+
</svg>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** An iPhone Pro with its Dynamic Island and side buttons, for an iOS screenshot at 1206 × 2622. */
|
|
107
|
+
export function PhoneFrame({ children, shadow = true }: FrameProps) {
|
|
108
|
+
return (
|
|
109
|
+
<div className="lar-device" data-shadow={shadow ? 'float' : undefined}>
|
|
110
|
+
<div className="lar-phone">
|
|
111
|
+
<i className="lar-phone__button lar-phone__button--action" aria-hidden="true" />
|
|
112
|
+
<i className="lar-phone__button lar-phone__button--volume-up" aria-hidden="true" />
|
|
113
|
+
<i className="lar-phone__button lar-phone__button--volume-down" aria-hidden="true" />
|
|
114
|
+
<i className="lar-phone__button lar-phone__button--side" aria-hidden="true" />
|
|
115
|
+
<div className="lar-phone__screen">
|
|
116
|
+
<div className="lar-phone__island" aria-hidden="true" />
|
|
117
|
+
{children}
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** An iPad Pro with even, thin bezels; the screenshot sets the aspect ratio. */
|
|
125
|
+
export function TabletFrame({ children, shadow = true, aspect = '4 / 3' }: FrameProps & { aspect?: string }) {
|
|
126
|
+
return (
|
|
127
|
+
<div className="lar-device" data-shadow={shadow ? 'float' : undefined}>
|
|
128
|
+
<div className="lar-tablet">
|
|
129
|
+
<div className="lar-tablet__screen" style={{ aspectRatio: aspect }}>
|
|
130
|
+
{children}
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** A slim television on a pedestal, for a 16:9 capture. */
|
|
138
|
+
export function TvFrame({ children, shadow = true, stand = true }: FrameProps & { stand?: boolean }) {
|
|
139
|
+
return (
|
|
140
|
+
<div className="lar-device lar-tv" data-shadow={shadow ? 'float' : undefined}>
|
|
141
|
+
<div className="lar-tv__panel">
|
|
142
|
+
<div className="lar-tv__screen">{children}</div>
|
|
143
|
+
</div>
|
|
144
|
+
{stand ? <div className="lar-tv__stand" aria-hidden="true" /> : null}
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** A Safari-style window with traffic lights and an address field. */
|
|
150
|
+
export function BrowserFrame({
|
|
151
|
+
children,
|
|
152
|
+
shadow = true,
|
|
153
|
+
address,
|
|
154
|
+
aspect = '16 / 10',
|
|
155
|
+
fade,
|
|
156
|
+
tone,
|
|
157
|
+
}: FrameProps & {
|
|
158
|
+
address: string;
|
|
159
|
+
aspect?: string;
|
|
160
|
+
fade?: 'right' | 'bottom' | 'both' | 'under' | 'tail';
|
|
161
|
+
tone?: 'dark';
|
|
162
|
+
}) {
|
|
163
|
+
return (
|
|
164
|
+
<div
|
|
165
|
+
className={`lar-device ${tone === 'dark' ? 'dark lar-dark-palette' : ''}`}
|
|
166
|
+
data-shadow={shadow ? 'float' : undefined}
|
|
167
|
+
>
|
|
168
|
+
<div className="lar-window" data-fade={fade === 'bottom' || fade === 'tail' ? fade : undefined}>
|
|
169
|
+
<div className="lar-window__bar" aria-hidden="true">
|
|
170
|
+
<span className="lar-window__lights">
|
|
171
|
+
<i />
|
|
172
|
+
<i />
|
|
173
|
+
<i />
|
|
174
|
+
</span>
|
|
175
|
+
<span className="lar-window__address">{address}</span>
|
|
176
|
+
</div>
|
|
177
|
+
<div
|
|
178
|
+
className="lar-window__screen"
|
|
179
|
+
data-fade={fade === 'bottom' || fade === 'tail' ? undefined : fade}
|
|
180
|
+
style={{ aspectRatio: aspect }}
|
|
181
|
+
>
|
|
182
|
+
{children}
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** A Mac app window whose screenshot already carries its own title bar: corners, a hairline and depth only.
|
|
190
|
+
* A bezel sets a dark-only capture in a dark display edge, so it reads as a deliberate dark shot on a light page;
|
|
191
|
+
* a fade dissolves an edge where the capture is cropped. */
|
|
192
|
+
export function AppWindow({
|
|
193
|
+
children,
|
|
194
|
+
shadow = true,
|
|
195
|
+
bezel,
|
|
196
|
+
fade,
|
|
197
|
+
}: FrameProps & { bezel?: boolean; fade?: 'right' | 'bottom' | 'both' }) {
|
|
198
|
+
return (
|
|
199
|
+
<div className="lar-device" data-shadow={shadow ? 'float' : undefined}>
|
|
200
|
+
<div className="lar-app-window" data-bezel={bezel || undefined} data-fade={fade}>
|
|
201
|
+
<div className="lar-app-window__fade">{children}</div>
|
|
202
|
+
</div>
|
|
203
|
+
</div>
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** A close-up cut from a screenshot, raised on glass above a device to point at one detail. */
|
|
208
|
+
export function Callout({ children, compact, fade }: { children: ReactNode; compact?: boolean; fade?: boolean }) {
|
|
209
|
+
return (
|
|
210
|
+
<div className={`lar-callout ${compact ? 'mx-auto max-w-[240px]' : ''}`} data-fade={fade || undefined}>
|
|
211
|
+
<div className="lar-callout__fade">{children}</div>
|
|
212
|
+
</div>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** A close-up with a smaller detail card overlapping its lower corner. */
|
|
217
|
+
export function CalloutPair({ base, detail }: { base: ReactNode; detail: ReactNode }) {
|
|
218
|
+
return (
|
|
219
|
+
<div className="relative pb-[18%]">
|
|
220
|
+
{base}
|
|
221
|
+
<div className="absolute right-[-2%] bottom-0 w-[62%] rotate-[1.5deg]">{detail}</div>
|
|
222
|
+
</div>
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Close-ups one under another, for a phone-width column. */
|
|
227
|
+
export function CalloutStack({ children }: { children: ReactNode }) {
|
|
228
|
+
return <div className="mx-auto flex max-w-[330px] flex-col gap-3">{children}</div>;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Media with a short, numbered reading guide floating over a quiet corner of it, on wide screens. */
|
|
232
|
+
export function GuidedMedia({
|
|
233
|
+
children,
|
|
234
|
+
guide,
|
|
235
|
+
label,
|
|
236
|
+
}: {
|
|
237
|
+
children: ReactNode;
|
|
238
|
+
guide: readonly string[];
|
|
239
|
+
label: string;
|
|
240
|
+
}) {
|
|
241
|
+
return (
|
|
242
|
+
<div className="relative flex flex-col gap-4">
|
|
243
|
+
{children}
|
|
244
|
+
<ol
|
|
245
|
+
aria-label={label}
|
|
246
|
+
className="text-base-content md:glass-menu flex flex-col gap-2 text-sm leading-5 md:absolute md:top-[8%] md:right-[4%] md:max-w-[260px] md:rounded-xl md:p-4"
|
|
247
|
+
>
|
|
248
|
+
{guide.map((step, index) => (
|
|
249
|
+
<li key={step} className="flex gap-2.5">
|
|
250
|
+
<span className="bg-primary text-primary-content inline-flex size-5 shrink-0 items-center justify-center rounded-full text-[11px] font-semibold tabular-nums">
|
|
251
|
+
{index + 1}
|
|
252
|
+
</span>
|
|
253
|
+
{step}
|
|
254
|
+
</li>
|
|
255
|
+
))}
|
|
256
|
+
</ol>
|
|
257
|
+
</div>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { CheckIcon } from 'lucide-react';
|
|
2
|
+
import { type ReactNode, useId } from 'react';
|
|
3
|
+
|
|
4
|
+
import { Eyebrow } from '../layout/PageSection';
|
|
5
|
+
import { Heading, Text } from '../typography/Typography';
|
|
6
|
+
|
|
7
|
+
interface FeatureRowProps {
|
|
8
|
+
eyebrow?: string;
|
|
9
|
+
title: string;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
points?: readonly string[];
|
|
12
|
+
media: ReactNode;
|
|
13
|
+
/** Puts the media on the left. */
|
|
14
|
+
reverse?: boolean;
|
|
15
|
+
/** Copy in two columns above media that spans the full width, for detailed screenshots. */
|
|
16
|
+
wide?: boolean;
|
|
17
|
+
/** A status chip beside the eyebrow. */
|
|
18
|
+
badge?: ReactNode;
|
|
19
|
+
/** How wide a wide row's media runs: the whole column, or a centred, readable measure. */
|
|
20
|
+
mediaWidth?: 'full' | 'measure';
|
|
21
|
+
/** Gives the media two-thirds of a side-by-side row instead of seven twelfths. */
|
|
22
|
+
largeMedia?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** A feature told in copy on one side and shown on a device on the other. */
|
|
26
|
+
export function FeatureRow({
|
|
27
|
+
eyebrow,
|
|
28
|
+
title,
|
|
29
|
+
children,
|
|
30
|
+
points,
|
|
31
|
+
media,
|
|
32
|
+
reverse,
|
|
33
|
+
wide,
|
|
34
|
+
badge,
|
|
35
|
+
mediaWidth = 'measure',
|
|
36
|
+
largeMedia,
|
|
37
|
+
}: FeatureRowProps) {
|
|
38
|
+
const id = useId();
|
|
39
|
+
|
|
40
|
+
if (wide)
|
|
41
|
+
return (
|
|
42
|
+
<article aria-labelledby={id} className="flex flex-col gap-12">
|
|
43
|
+
<div className="grid gap-x-16 gap-y-4 lg:grid-cols-2">
|
|
44
|
+
<div className="flex flex-col gap-4">
|
|
45
|
+
{eyebrow ? <Eyebrow>{eyebrow}</Eyebrow> : null}
|
|
46
|
+
<Heading id={id} as="h3" variant="feature">
|
|
47
|
+
{title}
|
|
48
|
+
</Heading>
|
|
49
|
+
<Text variant="prose" tone="muted">
|
|
50
|
+
{children}
|
|
51
|
+
</Text>
|
|
52
|
+
</div>
|
|
53
|
+
{points?.length ? (
|
|
54
|
+
<div className="lg:pt-9">
|
|
55
|
+
<PointList points={points} />
|
|
56
|
+
</div>
|
|
57
|
+
) : null}
|
|
58
|
+
</div>
|
|
59
|
+
<div className={`mx-auto w-full ${mediaWidth === 'full' ? '' : 'max-w-[780px]'}`}>{media}</div>
|
|
60
|
+
</article>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<article
|
|
65
|
+
aria-labelledby={id}
|
|
66
|
+
className={`grid items-center gap-8 sm:gap-12 lg:gap-16 ${reverse ? (largeMedia ? 'lg:grid-cols-[minmax(0,8fr)_minmax(0,4fr)]' : 'lg:grid-cols-[minmax(0,7fr)_minmax(0,5fr)]') : largeMedia ? 'lg:grid-cols-[minmax(0,4fr)_minmax(0,8fr)]' : 'lg:grid-cols-[minmax(0,5fr)_minmax(0,7fr)]'}`}
|
|
67
|
+
>
|
|
68
|
+
<div className={`flex flex-col gap-4 max-sm:[&>h3]:mb-1 ${reverse ? 'lg:order-2' : ''}`}>
|
|
69
|
+
{eyebrow ? (
|
|
70
|
+
<div className="flex items-center gap-3">
|
|
71
|
+
<Eyebrow>{eyebrow}</Eyebrow>
|
|
72
|
+
{badge}
|
|
73
|
+
</div>
|
|
74
|
+
) : null}
|
|
75
|
+
<Heading id={id} as="h3" variant="feature">
|
|
76
|
+
{title}
|
|
77
|
+
</Heading>
|
|
78
|
+
<Text variant="prose" tone="muted">
|
|
79
|
+
{children}
|
|
80
|
+
</Text>
|
|
81
|
+
{points?.length ? <PointList points={points} /> : null}
|
|
82
|
+
</div>
|
|
83
|
+
<div className={reverse ? 'lg:order-1' : ''}>{media}</div>
|
|
84
|
+
</article>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Checked lines under a feature. */
|
|
89
|
+
export function PointList({ points }: { points: readonly string[] }) {
|
|
90
|
+
return (
|
|
91
|
+
<ul className="mt-2 flex flex-col gap-2.5">
|
|
92
|
+
{points.map((point) => (
|
|
93
|
+
<li key={point} className="text-base-800 flex gap-2.5 text-[15px] leading-6">
|
|
94
|
+
<span className="bg-primary/12 text-primary dark:bg-primary/25 mt-[3px] inline-flex size-[18px] shrink-0 items-center justify-center rounded-full dark:text-[color-mix(in_srgb,var(--color-primary)_45%,white)] [&>svg]:size-3">
|
|
95
|
+
<CheckIcon />
|
|
96
|
+
</span>
|
|
97
|
+
{point}
|
|
98
|
+
</li>
|
|
99
|
+
))}
|
|
100
|
+
</ul>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** A stack of feature rows with room between them. */
|
|
105
|
+
export function FeatureRows({ children }: { children: ReactNode }) {
|
|
106
|
+
return <div className="flex flex-col gap-16 sm:gap-24">{children}</div>;
|
|
107
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Heading, Text } from '../typography/Typography';
|
|
4
|
+
import { Backdrop } from './Stage';
|
|
5
|
+
|
|
6
|
+
interface HeroProps {
|
|
7
|
+
announcement?: ReactNode;
|
|
8
|
+
title: ReactNode;
|
|
9
|
+
lead: ReactNode;
|
|
10
|
+
actions?: ReactNode;
|
|
11
|
+
note?: ReactNode;
|
|
12
|
+
visual?: ReactNode;
|
|
13
|
+
/** Tints the glow behind the hero with a product hue. */
|
|
14
|
+
hue?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** A page's opening: a centred statement over the brand glow, then the product on its devices. */
|
|
18
|
+
export function Hero({ announcement, title, lead, actions, note, visual, hue }: HeroProps) {
|
|
19
|
+
return (
|
|
20
|
+
<section className="relative isolate">
|
|
21
|
+
<Backdrop hue={hue} />
|
|
22
|
+
<div className="mx-auto flex w-full max-w-[1200px] flex-col items-center px-5 pt-8 text-center sm:px-8 sm:pt-16 lg:pt-16">
|
|
23
|
+
{announcement ? <Intro delay={0}>{announcement}</Intro> : null}
|
|
24
|
+
<Intro delay={60}>
|
|
25
|
+
<Heading as="h1" variant="display" className="mx-auto mt-5 max-w-[920px] whitespace-pre-line">
|
|
26
|
+
{title}
|
|
27
|
+
</Heading>
|
|
28
|
+
</Intro>
|
|
29
|
+
<Intro delay={140}>
|
|
30
|
+
<Text variant="lead" tone="muted" className="mx-auto mt-5 max-w-[640px]">
|
|
31
|
+
{lead}
|
|
32
|
+
</Text>
|
|
33
|
+
</Intro>
|
|
34
|
+
{actions ? (
|
|
35
|
+
<Intro delay={220}>
|
|
36
|
+
<div className="mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row sm:flex-wrap max-sm:[&>a]:w-full max-sm:[&>a]:max-w-[320px]">
|
|
37
|
+
{actions}
|
|
38
|
+
</div>
|
|
39
|
+
</Intro>
|
|
40
|
+
) : null}
|
|
41
|
+
{note ? (
|
|
42
|
+
<Intro delay={280}>
|
|
43
|
+
<Text
|
|
44
|
+
variant="body"
|
|
45
|
+
tone="muted"
|
|
46
|
+
className="mx-auto mt-4 max-w-[560px] text-balance dark:text-[#96969f]"
|
|
47
|
+
>
|
|
48
|
+
{note}
|
|
49
|
+
</Text>
|
|
50
|
+
</Intro>
|
|
51
|
+
) : null}
|
|
52
|
+
</div>
|
|
53
|
+
{visual ? (
|
|
54
|
+
<div className="mx-auto w-full max-w-[1200px] px-5 pt-7 pb-6 sm:px-8 sm:pt-12 sm:pb-28">
|
|
55
|
+
<Intro delay={320}>{visual}</Intro>
|
|
56
|
+
</div>
|
|
57
|
+
) : (
|
|
58
|
+
<div className="pb-16 sm:pb-24" />
|
|
59
|
+
)}
|
|
60
|
+
</section>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function Intro({ children, delay }: { children: ReactNode; delay: number }) {
|
|
65
|
+
return (
|
|
66
|
+
<div className="lar-intro w-full" style={{ '--lar-intro-delay': `${delay}ms` } as CSSProperties}>
|
|
67
|
+
{children}
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SearchIcon } from 'lucide-react';
|
|
2
|
+
|
|
3
|
+
export interface ConceptPhoto {
|
|
4
|
+
src: string;
|
|
5
|
+
alt: string;
|
|
6
|
+
/** Whether the photo matches the search shown above the grid. */
|
|
7
|
+
match: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** An illustration, not a screenshot: a search over your own photo library, with the matches lit. Its label says
|
|
11
|
+
* it is a concept. */
|
|
12
|
+
export function PhotoSearchConcept({
|
|
13
|
+
query,
|
|
14
|
+
photos,
|
|
15
|
+
label,
|
|
16
|
+
}: {
|
|
17
|
+
query: string;
|
|
18
|
+
photos: readonly ConceptPhoto[];
|
|
19
|
+
label: string;
|
|
20
|
+
}) {
|
|
21
|
+
return (
|
|
22
|
+
<figure className="flex flex-col gap-3">
|
|
23
|
+
<div className="border-base-300 bg-base-100/80 text-base-content dark:bg-base-200/70 [&>svg]:text-base-600 flex items-center gap-2 rounded-full border px-3 py-1.5 text-sm [&>svg]:size-4">
|
|
24
|
+
<SearchIcon />
|
|
25
|
+
<span className="truncate">{query}</span>
|
|
26
|
+
</div>
|
|
27
|
+
<ul className="grid grid-cols-3 gap-1.5">
|
|
28
|
+
{photos.map((photo) => (
|
|
29
|
+
<li key={photo.src} className="relative overflow-hidden rounded-md">
|
|
30
|
+
<img
|
|
31
|
+
src={photo.src}
|
|
32
|
+
alt={photo.alt}
|
|
33
|
+
loading="lazy"
|
|
34
|
+
width={320}
|
|
35
|
+
height={320}
|
|
36
|
+
className={`aspect-square w-full object-cover transition-opacity ${photo.match ? '' : 'opacity-35'}`}
|
|
37
|
+
/>
|
|
38
|
+
{photo.match ? (
|
|
39
|
+
<span
|
|
40
|
+
aria-hidden="true"
|
|
41
|
+
className="absolute inset-0 rounded-md ring-2 ring-white/80 ring-inset"
|
|
42
|
+
/>
|
|
43
|
+
) : null}
|
|
44
|
+
</li>
|
|
45
|
+
))}
|
|
46
|
+
</ul>
|
|
47
|
+
<figcaption className="text-base-700 text-xs">{label}</figcaption>
|
|
48
|
+
</figure>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { type Readiness, StatusPill } from './Status';
|
|
4
|
+
|
|
5
|
+
export interface Platform {
|
|
6
|
+
name: string;
|
|
7
|
+
detail: string;
|
|
8
|
+
icon: ReactNode;
|
|
9
|
+
status: Readiness;
|
|
10
|
+
statusLabel: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Every screen Lar reaches, each with where it stands: compact rows on phones, cards on wider screens. */
|
|
14
|
+
export function PlatformGrid({ platforms, label }: { platforms: readonly Platform[]; label: string }) {
|
|
15
|
+
return (
|
|
16
|
+
<ul
|
|
17
|
+
aria-label={label}
|
|
18
|
+
className="divide-base-300/70 border-base-300/80 bg-base-100/60 dark:bg-base-100/40 grid divide-y rounded-2xl border sm:grid-cols-2 sm:gap-3 sm:divide-y-0 sm:rounded-none sm:border-0 sm:bg-transparent lg:grid-cols-4 sm:dark:bg-transparent"
|
|
19
|
+
>
|
|
20
|
+
{platforms.map((platform) => (
|
|
21
|
+
<li
|
|
22
|
+
key={platform.name}
|
|
23
|
+
data-status={platform.status}
|
|
24
|
+
className="sm:border-base-300/80 sm:bg-base-100/60 sm:dark:bg-base-100/40 flex items-start gap-3 p-4 sm:flex-col sm:items-stretch sm:gap-4 sm:rounded-2xl sm:border sm:p-5 sm:data-[status=planned]:border-dashed sm:data-[status=planned]:bg-transparent"
|
|
25
|
+
>
|
|
26
|
+
<div className="flex shrink-0 items-start justify-between gap-3">
|
|
27
|
+
<span className="bg-base-200 text-base-800 ring-base-300/70 dark:bg-base-300/60 inline-flex size-9 items-center justify-center rounded-[0.65rem] ring-1 ring-inset sm:size-10 [&>svg]:size-[18px] sm:[&>svg]:size-5">
|
|
28
|
+
{platform.icon}
|
|
29
|
+
</span>
|
|
30
|
+
<span className="hidden sm:inline-flex">
|
|
31
|
+
<StatusPill status={platform.status}>{platform.statusLabel}</StatusPill>
|
|
32
|
+
</span>
|
|
33
|
+
</div>
|
|
34
|
+
<div className="flex min-w-0 flex-1 flex-col gap-0.5 sm:gap-1">
|
|
35
|
+
<span className="flex flex-wrap items-center gap-x-2 gap-y-1">
|
|
36
|
+
<span className="text-base-content text-[15px] font-semibold tracking-[-0.01em]">
|
|
37
|
+
{platform.name}
|
|
38
|
+
</span>
|
|
39
|
+
<span className="sm:hidden">
|
|
40
|
+
<StatusPill status={platform.status}>{platform.statusLabel}</StatusPill>
|
|
41
|
+
</span>
|
|
42
|
+
</span>
|
|
43
|
+
<span className="text-base-700 text-sm leading-5">{platform.detail}</span>
|
|
44
|
+
</div>
|
|
45
|
+
</li>
|
|
46
|
+
))}
|
|
47
|
+
</ul>
|
|
48
|
+
);
|
|
49
|
+
}
|