@sovereignfs/ui 0.45.0 → 0.83.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Accordion.module.css +1 -1
- package/dist/Alert.module.css +1 -1
- package/dist/AppsLauncher.module.css +96 -0
- package/dist/Avatar.module.css +1 -1
- package/dist/Badge.module.css +30 -7
- package/dist/BalanceChip.module.css +1 -1
- package/dist/Button.module.css +18 -2
- package/dist/Card.module.css +1 -1
- package/dist/CardTile.module.css +181 -0
- package/dist/CodeTextarea.module.css +1 -1
- package/dist/Collapsible.module.css +1 -1
- package/dist/ColorPicker.module.css +132 -0
- package/dist/Combobox.module.css +2 -2
- package/dist/Command.module.css +1 -1
- package/dist/ConfirmDialog.module.css +2 -2
- package/dist/ConsentPrompt.module.css +21 -0
- package/dist/DatePicker.module.css +1 -1
- package/dist/Dialog.module.css +130 -21
- package/dist/Drawer.module.css +36 -7
- package/dist/Header.module.css +62 -0
- package/dist/HeaderFooterLayout.module.css +21 -0
- package/dist/IconPicker.module.css +1 -1
- package/dist/Input.module.css +1 -1
- package/dist/Kbd.module.css +1 -1
- package/dist/LegalLinks.module.css +24 -0
- package/dist/Markdown.module.css +73 -0
- package/dist/Menu.module.css +1 -0
- package/dist/Message.module.css +1 -1
- package/dist/MessageScroller.module.css +12 -1
- package/dist/MobileAppsDrawer.module.css +82 -0
- package/dist/MobileFooter.module.css +73 -0
- package/dist/MobileHeader.module.css +76 -0
- package/dist/NavList.module.css +130 -0
- package/dist/NavTabs.module.css +1 -1
- package/dist/NotificationsPanel.module.css +258 -0
- package/dist/OverlayHeader.module.css +1 -1
- package/dist/PageContainer.module.css +82 -0
- package/dist/PageHeader.module.css +54 -0
- package/dist/PageLayout.module.css +51 -0
- package/dist/Popover.module.css +1 -1
- package/dist/QuantityStepper.module.css +1 -1
- package/dist/Resizable.module.css +3 -3
- package/dist/RootLayout.module.css +12 -0
- package/dist/SegmentedControl.module.css +1 -1
- package/dist/Select.module.css +1 -1
- package/dist/Sheet.module.css +4 -1
- package/dist/SplitPane.module.css +4 -4
- package/dist/StatusBadge.module.css +1 -1
- package/dist/StepStrip.module.css +53 -0
- package/dist/SuggestionInput.module.css +2 -2
- package/dist/SwipableMobileCarousel.module.css +64 -0
- package/dist/SwipableMobileCarouselDots.module.css +64 -0
- package/dist/SwipableMobileCarouselSlideParts.module.css +29 -0
- package/dist/SwipeStack.module.css +101 -0
- package/dist/SystemBanner.module.css +10 -0
- package/dist/Table.module.css +2 -2
- package/dist/Tabs.module.css +1 -1
- package/dist/TagInput.module.css +2 -2
- package/dist/Textarea.module.css +9 -1
- package/dist/ThreeColumnLayout.module.css +35 -0
- package/dist/Toast.module.css +62 -3
- package/dist/Tooltip.module.css +1 -1
- package/dist/UserMenu.module.css +90 -0
- package/dist/index.d.ts +1680 -30
- package/dist/index.js +4618 -1443
- package/dist/tokens/primitives.css +36 -0
- package/dist/tokens/semantic.css +32 -0
- package/dist/tokens/theme-presets.css +33 -0
- package/package.json +32 -12
- package/src/__tests__/package-json.test.ts +8 -0
- package/src/components/Accordion/Accordion.module.css +1 -1
- package/src/components/Alert/Alert.module.css +1 -1
- package/src/components/AppsLauncher/AppsLauncher.module.css +96 -0
- package/src/components/AppsLauncher/AppsLauncher.stories.tsx +58 -0
- package/src/components/AppsLauncher/AppsLauncher.tsx +117 -0
- package/src/components/AppsLauncher/__tests__/AppsLauncher.test.tsx +52 -0
- package/src/components/Avatar/Avatar.module.css +1 -1
- package/src/components/Badge/Badge.module.css +30 -7
- package/src/components/Badge/Badge.stories.tsx +16 -4
- package/src/components/Badge/Badge.tsx +8 -11
- package/src/components/Badge/__tests__/Badge.test.tsx +4 -2
- package/src/components/BalanceChip/BalanceChip.module.css +1 -1
- package/src/components/Button/Button.module.css +18 -2
- package/src/components/Card/Card.module.css +1 -1
- package/src/components/CardTile/CardTile.module.css +181 -0
- package/src/components/CardTile/CardTile.stories.tsx +86 -0
- package/src/components/CardTile/CardTile.tsx +128 -0
- package/src/components/CardTile/__tests__/CardTile.test.tsx +56 -0
- package/src/components/CodeTextarea/CodeTextarea.module.css +1 -1
- package/src/components/Collapsible/Collapsible.module.css +1 -1
- package/src/components/ColorPicker/ColorPicker.module.css +132 -0
- package/src/components/ColorPicker/ColorPicker.stories.tsx +80 -0
- package/src/components/ColorPicker/ColorPicker.tsx +157 -0
- package/src/components/ColorPicker/__tests__/ColorPicker.test.tsx +117 -0
- package/src/components/Combobox/Combobox.module.css +2 -2
- package/src/components/Command/Command.module.css +1 -1
- package/src/components/ConfirmDialog/ConfirmDialog.module.css +2 -2
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +28 -2
- package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +71 -3
- package/src/components/ConsentPrompt/ConsentPrompt.module.css +21 -0
- package/src/components/ConsentPrompt/ConsentPrompt.stories.tsx +31 -0
- package/src/components/ConsentPrompt/ConsentPrompt.tsx +66 -0
- package/src/components/ContextMenu/ContextMenu.tsx +1 -1
- package/src/components/DatePicker/DatePicker.module.css +1 -1
- package/src/components/DeviceOnlyGate/DeviceOnlyGate.tsx +58 -0
- package/src/components/DeviceOnlyGate/__tests__/DeviceOnlyGate.test.tsx +45 -0
- package/src/components/DeviceStorageKeyGate/DeviceStorageKeyGate.tsx +100 -0
- package/src/components/DeviceStorageKeyGate/__tests__/DeviceStorageKeyGate.test.tsx +119 -0
- package/src/components/Dialog/Dialog.module.css +130 -21
- package/src/components/Dialog/Dialog.stories.tsx +179 -2
- package/src/components/Dialog/Dialog.tsx +137 -94
- package/src/components/Dialog/__tests__/Dialog.test.tsx +190 -9
- package/src/components/DragHandleRow/DragHandleRow.tsx +2 -21
- package/src/components/Drawer/Drawer.module.css +36 -7
- package/src/components/Drawer/Drawer.stories.tsx +44 -0
- package/src/components/Drawer/Drawer.tsx +27 -66
- package/src/components/Drawer/__tests__/Drawer.test.tsx +55 -6
- package/src/components/GripIcon/GripIcon.tsx +27 -0
- package/src/components/Header/Header.module.css +62 -0
- package/src/components/Header/Header.stories.tsx +452 -0
- package/src/components/Header/Header.tsx +102 -0
- package/src/components/Header/__tests__/Header.test.tsx +104 -0
- package/src/components/HeaderFooterLayout/HeaderFooterLayout.module.css +21 -0
- package/src/components/HeaderFooterLayout/HeaderFooterLayout.stories.tsx +111 -0
- package/src/components/HeaderFooterLayout/HeaderFooterLayout.tsx +54 -0
- package/src/components/HeaderFooterLayout/__tests__/HeaderFooterLayout.test.tsx +58 -0
- package/src/components/Icon/icons/arrow-left-right.tsx +23 -0
- package/src/components/Icon/icons/bold.tsx +20 -0
- package/src/components/Icon/icons/calendar.tsx +4 -4
- package/src/components/Icon/icons/carrot.tsx +3 -3
- package/src/components/Icon/icons/circle-chevron-left.tsx +21 -0
- package/src/components/Icon/icons/code.tsx +21 -0
- package/src/components/Icon/icons/copy.tsx +21 -0
- package/src/components/Icon/icons/credit-card.tsx +21 -0
- package/src/components/Icon/icons/database.tsx +22 -0
- package/src/components/Icon/icons/download.tsx +22 -0
- package/src/components/Icon/icons/file-text.tsx +24 -0
- package/src/components/Icon/icons/folder-closed.tsx +21 -0
- package/src/components/Icon/icons/folder-open.tsx +20 -0
- package/src/components/Icon/icons/folder.tsx +20 -0
- package/src/components/Icon/icons/folders.tsx +21 -0
- package/src/components/Icon/icons/hat-glasses.tsx +24 -0
- package/src/components/Icon/icons/history.tsx +22 -0
- package/src/components/Icon/icons/inbox.tsx +21 -0
- package/src/components/Icon/icons/index.ts +169 -1
- package/src/components/Icon/icons/italic.tsx +22 -0
- package/src/components/Icon/icons/layers.tsx +22 -0
- package/src/components/Icon/icons/layout-dashboard.tsx +23 -0
- package/src/components/Icon/icons/layout-grid.tsx +23 -0
- package/src/components/Icon/icons/link.tsx +21 -0
- package/src/components/Icon/icons/list-ordered.tsx +25 -0
- package/src/components/Icon/icons/list.tsx +25 -0
- package/src/components/Icon/icons/luggage.tsx +24 -0
- package/src/components/Icon/icons/map-pin.tsx +21 -0
- package/src/components/Icon/icons/menu.tsx +22 -0
- package/src/components/Icon/icons/minus.tsx +20 -0
- package/src/components/Icon/icons/paint-bucket.tsx +23 -0
- package/src/components/Icon/icons/panel-left.tsx +21 -0
- package/src/components/Icon/icons/pin.tsx +21 -0
- package/src/components/Icon/icons/rectangle-ellipsis.tsx +23 -0
- package/src/components/Icon/icons/refresh-cw.tsx +23 -0
- package/src/components/Icon/icons/rotate-cw.tsx +21 -0
- package/src/components/Icon/icons/route.tsx +22 -0
- package/src/components/Icon/icons/send.tsx +21 -0
- package/src/components/Icon/icons/share-2.tsx +24 -0
- package/src/components/Icon/icons/sheet.tsx +24 -0
- package/src/components/Icon/icons/smartphone.tsx +21 -0
- package/src/components/Icon/icons/square-kanban.tsx +23 -0
- package/src/components/Icon/icons/table.tsx +23 -0
- package/src/components/Icon/icons/user-round-plus.tsx +23 -0
- package/src/components/Icon/icons/users.tsx +23 -0
- package/src/components/IconPicker/IconPicker.module.css +1 -1
- package/src/components/Input/Input.module.css +1 -1
- package/src/components/Input/Input.tsx +8 -2
- package/src/components/Kbd/Kbd.module.css +1 -1
- package/src/components/LegalLinks/LegalLinks.module.css +24 -0
- package/src/components/LegalLinks/LegalLinks.stories.tsx +22 -0
- package/src/components/LegalLinks/LegalLinks.tsx +40 -0
- package/src/components/Markdown/Markdown.module.css +73 -0
- package/src/components/Markdown/Markdown.stories.tsx +40 -0
- package/src/components/Markdown/Markdown.tsx +305 -0
- package/src/components/Markdown/__tests__/Markdown.test.tsx +144 -0
- package/src/components/Menu/Menu.module.css +1 -0
- package/src/components/Menu/Menu.tsx +72 -22
- package/src/components/Menu/__tests__/Menu.test.tsx +30 -0
- package/src/components/Menubar/Menubar.tsx +1 -1
- package/src/components/Message/Message.module.css +1 -1
- package/src/components/MessageScroller/MessageScroller.module.css +12 -1
- package/src/components/MessageScroller/MessageScroller.tsx +12 -0
- package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +82 -0
- package/src/components/MobileAppsDrawer/MobileAppsDrawer.tsx +78 -0
- package/src/components/MobileAppsDrawer/__tests__/MobileAppsDrawer.test.tsx +80 -0
- package/src/components/MobileFooter/MobileFooter.module.css +73 -0
- package/src/components/MobileFooter/MobileFooter.stories.tsx +47 -0
- package/src/components/MobileFooter/MobileFooter.tsx +122 -0
- package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +129 -0
- package/src/components/MobileHeader/MobileHeader.module.css +76 -0
- package/src/components/MobileHeader/MobileHeader.stories.tsx +57 -0
- package/src/components/MobileHeader/MobileHeader.tsx +90 -0
- package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +113 -0
- package/src/components/NavList/NavList.module.css +130 -0
- package/src/components/NavList/NavList.tsx +136 -0
- package/src/components/NavList/__tests__/NavList.test.tsx +109 -0
- package/src/components/NavTabs/NavTabs.module.css +1 -1
- package/src/components/NavTabs/NavTabs.tsx +39 -11
- package/src/components/NotificationsPanel/NotificationsPanel.module.css +258 -0
- package/src/components/NotificationsPanel/NotificationsPanel.stories.tsx +61 -0
- package/src/components/NotificationsPanel/NotificationsPanel.tsx +187 -0
- package/src/components/NotificationsPanel/__tests__/NotificationsPanel.test.tsx +78 -0
- package/src/components/OfflineGate/OfflineGate.tsx +44 -0
- package/src/components/OfflineGate/__tests__/OfflineGate.test.tsx +66 -0
- package/src/components/OverlayHeader/OverlayHeader.module.css +1 -1
- package/src/components/OverlayHeader/OverlayHeader.tsx +19 -4
- package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +18 -0
- package/src/components/PageContainer/PageContainer.module.css +82 -0
- package/src/components/PageContainer/PageContainer.tsx +64 -0
- package/src/components/PageContainer/__tests__/PageContainer.test.tsx +70 -0
- package/src/components/PageHeader/PageHeader.module.css +54 -0
- package/src/components/PageHeader/PageHeader.tsx +157 -2
- package/src/components/PageHeader/__tests__/PageHeader.test.tsx +103 -0
- package/src/components/PageLayout/PageLayout.module.css +51 -0
- package/src/components/PageLayout/PageLayout.stories.tsx +73 -0
- package/src/components/PageLayout/PageLayout.tsx +51 -0
- package/src/components/PageLayout/__tests__/PageLayout.test.tsx +34 -0
- package/src/components/Popover/Popover.module.css +1 -1
- package/src/components/Popover/Popover.tsx +86 -4
- package/src/components/Popover/__tests__/Popover.test.tsx +165 -0
- package/src/components/QuantityStepper/QuantityStepper.module.css +1 -1
- package/src/components/Resizable/Resizable.module.css +3 -3
- package/src/components/ResponsiveSurface/ResponsiveSurface.tsx +24 -0
- package/src/components/ResponsiveSurface/__tests__/ResponsiveSurface.test.tsx +73 -0
- package/src/components/RootLayout/RootLayout.module.css +12 -0
- package/src/components/RootLayout/RootLayout.stories.tsx +125 -0
- package/src/components/RootLayout/RootLayout.tsx +185 -0
- package/src/components/RootLayout/__tests__/RootLayout.test.tsx +161 -0
- package/src/components/SegmentedControl/SegmentedControl.module.css +1 -1
- package/src/components/Select/Select.module.css +1 -1
- package/src/components/Sheet/Sheet.module.css +4 -1
- package/src/components/Sheet/Sheet.tsx +14 -56
- package/src/components/SplitPane/SplitPane.module.css +4 -4
- package/src/components/StatusBadge/StatusBadge.module.css +1 -1
- package/src/components/StepStrip/StepStrip.module.css +53 -0
- package/src/components/StepStrip/StepStrip.tsx +74 -0
- package/src/components/SuggestionInput/SuggestionInput.module.css +2 -2
- package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +64 -0
- package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +243 -0
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlide.tsx +35 -0
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody.tsx +42 -0
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideFooter.tsx +18 -0
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader.tsx +21 -0
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideParts.module.css +29 -0
- package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +214 -0
- package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarouselDevGuard.test.tsx +61 -0
- package/src/components/SwipableMobileCarousel/context.ts +13 -0
- package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +64 -0
- package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +73 -0
- package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +63 -0
- package/src/components/SwipeStack/SwipeStack.module.css +101 -0
- package/src/components/SwipeStack/SwipeStack.tsx +199 -0
- package/src/components/SwipeStack/SwipeStackCard.tsx +22 -0
- package/src/components/SwipeStack/__tests__/SwipeStack.test.tsx +169 -0
- package/src/components/SystemBanner/SystemBanner.module.css +10 -0
- package/src/components/Table/Table.module.css +2 -2
- package/src/components/Tabs/Tabs.module.css +1 -1
- package/src/components/TagInput/TagInput.module.css +2 -2
- package/src/components/Textarea/Textarea.module.css +9 -1
- package/src/components/Textarea/Textarea.tsx +28 -5
- package/src/components/Textarea/__tests__/Textarea.test.tsx +23 -1
- package/src/components/ThreeColumnLayout/ThreeColumnLayout.module.css +35 -0
- package/src/components/ThreeColumnLayout/ThreeColumnLayout.stories.tsx +152 -0
- package/src/components/ThreeColumnLayout/ThreeColumnLayout.tsx +87 -0
- package/src/components/ThreeColumnLayout/__tests__/ThreeColumnLayout.test.tsx +78 -0
- package/src/components/Toast/Toast.module.css +62 -3
- package/src/components/Toast/Toast.stories.tsx +1 -1
- package/src/components/Tooltip/Tooltip.module.css +1 -1
- package/src/components/UserMenu/UserMenu.module.css +90 -0
- package/src/components/UserMenu/UserMenu.stories.tsx +49 -0
- package/src/components/UserMenu/UserMenu.tsx +132 -0
- package/src/components/UserMenu/__tests__/UserMenu.test.tsx +77 -0
- package/src/hooks/__tests__/useCarouselRouteSync.test.tsx +126 -0
- package/src/hooks/__tests__/useIsOffline.test.tsx +53 -0
- package/src/hooks/__tests__/useOfflineTileState.test.tsx +69 -0
- package/src/hooks/__tests__/usePublishShellChromeHeight.test.tsx +118 -0
- package/src/hooks/__tests__/useReorderSensors.test.ts +26 -0
- package/src/hooks/__tests__/useResponsiveLayout.test.tsx +87 -0
- package/src/hooks/__tests__/useSnapCarousel.test.tsx +175 -0
- package/src/hooks/__tests__/useSwipeReveal.test.tsx +110 -0
- package/src/hooks/__tests__/useSwipeStack.test.tsx +155 -0
- package/src/hooks/index.ts +27 -0
- package/src/hooks/useCarouselRouteSync.ts +92 -0
- package/src/hooks/useIsOffline.ts +41 -0
- package/src/hooks/useOfflineTileState.ts +45 -0
- package/src/hooks/usePublishShellChromeHeight.ts +96 -0
- package/src/hooks/useReorderSensors.ts +88 -0
- package/src/hooks/useResponsiveLayout.ts +36 -0
- package/src/hooks/useSnapCarousel.ts +284 -0
- package/src/hooks/useSwipeReveal.ts +107 -0
- package/src/hooks/useSwipeStack.ts +235 -0
- package/src/index.ts +124 -3
- package/src/overlay-shell.ts +159 -0
- package/src/stories/DesignSystemOverview.stories.tsx +933 -6
- package/src/stories/DeviceOnlyGate.stories.tsx +35 -0
- package/src/stories/DeviceStorageKeyGate.stories.tsx +57 -0
- package/src/stories/GripIcon.stories.tsx +29 -0
- package/src/stories/InteractionHooks.stories.tsx +483 -0
- package/src/stories/LayoutSystem.stories.tsx +639 -0
- package/src/stories/MenuEntries.stories.tsx +86 -0
- package/src/stories/MobilePatterns.stories.tsx +247 -2
- package/src/stories/NavList.stories.tsx +147 -0
- package/src/stories/NavTabs.stories.tsx +18 -0
- package/src/stories/OfflineGate.stories.tsx +42 -0
- package/src/stories/PageContainer.stories.tsx +82 -0
- package/src/stories/PageHeader.stories.tsx +65 -1
- package/src/stories/ResponsiveSurface.stories.tsx +47 -0
- package/src/stories/StepStrip.stories.tsx +76 -0
- package/src/stories/SwipableMobileCarousel.stories.tsx +362 -0
- package/src/stories/SwipeStack.stories.tsx +200 -0
- package/src/stories/Textarea.stories.tsx +12 -0
- package/src/stories/TokenGallery.stories.tsx +115 -0
- package/src/tokens/primitives.css +36 -0
- package/src/tokens/semantic.css +32 -0
- package/src/tokens/theme-presets.css +33 -0
- package/src/tokens/theme-presets.ts +72 -0
|
@@ -5,13 +5,18 @@ import { Avatar } from '../components/Avatar/Avatar';
|
|
|
5
5
|
import { Badge } from '../components/Badge/Badge';
|
|
6
6
|
import { Button } from '../components/Button/Button';
|
|
7
7
|
import { Card } from '../components/Card/Card';
|
|
8
|
+
import { CardTile, CardTileGrid, NewCardTile } from '../components/CardTile/CardTile';
|
|
8
9
|
import { Dialog } from '../components/Dialog/Dialog';
|
|
9
10
|
import { Drawer } from '../components/Drawer/Drawer';
|
|
10
11
|
import { EmptyState } from '../components/EmptyState/EmptyState';
|
|
12
|
+
import { OfflineGate } from '../components/OfflineGate/OfflineGate';
|
|
13
|
+
import { DeviceOnlyGate } from '../components/DeviceOnlyGate/DeviceOnlyGate';
|
|
14
|
+
import { DeviceStorageKeyGate } from '../components/DeviceStorageKeyGate/DeviceStorageKeyGate';
|
|
11
15
|
import { FormField } from '../components/FormField/FormField';
|
|
12
16
|
import { Icon } from '../components/Icon/Icon';
|
|
13
17
|
import type { IconName } from '../components/Icon/Icon';
|
|
14
18
|
import { IconPicker } from '../components/IconPicker/IconPicker';
|
|
19
|
+
import { ColorPicker } from '../components/ColorPicker/ColorPicker';
|
|
15
20
|
import { QuantityStepper } from '../components/QuantityStepper/QuantityStepper';
|
|
16
21
|
import { CheckableListRow } from '../components/CheckableListRow/CheckableListRow';
|
|
17
22
|
import { Input } from '../components/Input/Input';
|
|
@@ -19,11 +24,32 @@ import { CodeTextarea } from '../components/CodeTextarea/CodeTextarea';
|
|
|
19
24
|
import { Textarea } from '../components/Textarea/Textarea';
|
|
20
25
|
import { StatusBadge } from '../components/StatusBadge/StatusBadge';
|
|
21
26
|
import { SplitPane } from '../components/SplitPane/SplitPane';
|
|
27
|
+
import { ThreeColumnLayout } from '../components/ThreeColumnLayout/ThreeColumnLayout';
|
|
28
|
+
import { HeaderFooterLayout } from '../components/HeaderFooterLayout/HeaderFooterLayout';
|
|
29
|
+
import { RootLayout } from '../components/RootLayout/RootLayout';
|
|
30
|
+
import { PageLayout } from '../components/PageLayout/PageLayout';
|
|
22
31
|
import { TagInput } from '../components/TagInput/TagInput';
|
|
23
32
|
import { SuggestionInput } from '../components/SuggestionInput/SuggestionInput';
|
|
33
|
+
import { AppsLauncher } from '../components/AppsLauncher/AppsLauncher';
|
|
34
|
+
import { Header } from '../components/Header/Header';
|
|
35
|
+
import { MobileAppsDrawer } from '../components/MobileAppsDrawer/MobileAppsDrawer';
|
|
36
|
+
import { MobileFooter } from '../components/MobileFooter/MobileFooter';
|
|
37
|
+
import { MobileHeader } from '../components/MobileHeader/MobileHeader';
|
|
38
|
+
import { NavList } from '../components/NavList/NavList';
|
|
24
39
|
import { NavTabs } from '../components/NavTabs/NavTabs';
|
|
40
|
+
import { NotificationsPanel } from '../components/NotificationsPanel/NotificationsPanel';
|
|
25
41
|
import { PageHeader } from '../components/PageHeader/PageHeader';
|
|
42
|
+
import { PageContainer } from '../components/PageContainer/PageContainer';
|
|
26
43
|
import { Popover } from '../components/Popover/Popover';
|
|
44
|
+
import { UserMenu } from '../components/UserMenu/UserMenu';
|
|
45
|
+
import { ResponsiveSurface } from '../components/ResponsiveSurface/ResponsiveSurface';
|
|
46
|
+
import { SwipableMobileCarousel } from '../components/SwipableMobileCarousel/SwipableMobileCarousel';
|
|
47
|
+
import { SwipableMobileCarouselSlide } from '../components/SwipableMobileCarousel/SwipableMobileCarouselSlide';
|
|
48
|
+
import { SwipableMobileCarouselSlideHeader } from '../components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader';
|
|
49
|
+
import { SwipableMobileCarouselSlideBody } from '../components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody';
|
|
50
|
+
import { SwipableMobileCarouselDots } from '../components/SwipableMobileCarouselDots/SwipableMobileCarouselDots';
|
|
51
|
+
import { SwipeStack } from '../components/SwipeStack/SwipeStack';
|
|
52
|
+
import { SwipeStackCard } from '../components/SwipeStack/SwipeStackCard';
|
|
27
53
|
import { SegmentedControl } from '../components/SegmentedControl/SegmentedControl';
|
|
28
54
|
import { Select } from '../components/Select/Select';
|
|
29
55
|
import { Spinner } from '../components/Spinner/Spinner';
|
|
@@ -46,6 +72,9 @@ import {
|
|
|
46
72
|
} from '../components/Table/Table';
|
|
47
73
|
import { Alert } from '../components/Alert/Alert';
|
|
48
74
|
import { Breadcrumb } from '../components/Breadcrumb/Breadcrumb';
|
|
75
|
+
import { LegalLinks } from '../components/LegalLinks/LegalLinks';
|
|
76
|
+
import { ConsentPrompt } from '../components/ConsentPrompt/ConsentPrompt';
|
|
77
|
+
import { Markdown } from '../components/Markdown/Markdown';
|
|
49
78
|
import { Pagination } from '../components/Pagination/Pagination';
|
|
50
79
|
import { Kbd } from '../components/Kbd/Kbd';
|
|
51
80
|
import { Accordion } from '../components/Accordion/Accordion';
|
|
@@ -72,11 +101,13 @@ import { NavigationMenu } from '../components/NavigationMenu/NavigationMenu';
|
|
|
72
101
|
import { Menubar } from '../components/Menubar/Menubar';
|
|
73
102
|
import { Collapsible } from '../components/Collapsible/Collapsible';
|
|
74
103
|
import { DragHandleRow } from '../components/DragHandleRow/DragHandleRow';
|
|
104
|
+
import { GripIcon } from '../components/GripIcon/GripIcon';
|
|
105
|
+
import { StepStrip, type StepStripItem } from '../components/StepStrip/StepStrip';
|
|
75
106
|
import { FileDropzone } from '../components/FileDropzone/FileDropzone';
|
|
76
107
|
import { OverlayHeader } from '../components/OverlayHeader/OverlayHeader';
|
|
77
108
|
import { Sheet } from '../components/Sheet/Sheet';
|
|
78
109
|
import { ConfirmDialog } from '../components/ConfirmDialog/ConfirmDialog';
|
|
79
|
-
import { Menu } from '../components/Menu/Menu';
|
|
110
|
+
import { Menu, MenuEntries } from '../components/Menu/Menu';
|
|
80
111
|
import { Calendar } from '../components/Calendar/Calendar';
|
|
81
112
|
import { DatePicker } from '../components/DatePicker/DatePicker';
|
|
82
113
|
import { CurrencyInput } from '../components/CurrencyInput/CurrencyInput';
|
|
@@ -236,6 +267,8 @@ const COLOR_GROUPS: Array<{
|
|
|
236
267
|
{ token: '--sv-color-text-on-accent', name: 'text-on-accent' },
|
|
237
268
|
{ token: '--sv-color-text-on-error', name: 'text-on-error' },
|
|
238
269
|
{ token: '--sv-color-text-on-success', name: 'text-on-success' },
|
|
270
|
+
{ token: '--sv-color-text-on-light-fill', name: 'text-on-light-fill' },
|
|
271
|
+
{ token: '--sv-color-text-on-dark-fill', name: 'text-on-dark-fill' },
|
|
239
272
|
],
|
|
240
273
|
},
|
|
241
274
|
{
|
|
@@ -246,6 +279,12 @@ const COLOR_GROUPS: Array<{
|
|
|
246
279
|
{ token: '--sv-color-border-strong', name: 'border-strong' },
|
|
247
280
|
],
|
|
248
281
|
},
|
|
282
|
+
{
|
|
283
|
+
label: 'Shadow',
|
|
284
|
+
usage:
|
|
285
|
+
'High-contrast shadow color for theme presets with hard offset shadows (RFC 0094). Unused by the default theme.',
|
|
286
|
+
tokens: [{ token: '--sv-color-shadow-strong', name: 'shadow-strong' }],
|
|
287
|
+
},
|
|
249
288
|
{
|
|
250
289
|
label: 'Accent',
|
|
251
290
|
usage:
|
|
@@ -375,6 +414,7 @@ function ColorGroup({
|
|
|
375
414
|
// ---------------------------------------------------------------------------
|
|
376
415
|
|
|
377
416
|
const TYPE_SCALE: Array<{ token: string; label: string; note: string }> = [
|
|
417
|
+
{ token: '--sv-font-size-3xl', label: '3xl — 32px', note: 'Document title style' },
|
|
378
418
|
{ token: '--sv-font-size-2xl', label: '2xl — 24px', note: 'Page titles' },
|
|
379
419
|
{ token: '--sv-font-size-xl', label: 'xl — 20px', note: 'Section headings' },
|
|
380
420
|
{ token: '--sv-font-size-lg', label: 'lg — 18px', note: 'Sub-headings' },
|
|
@@ -383,6 +423,11 @@ const TYPE_SCALE: Array<{ token: string; label: string; note: string }> = [
|
|
|
383
423
|
{ token: '--sv-font-size-caption', label: 'caption — 13px', note: 'Secondary / supporting copy' },
|
|
384
424
|
{ token: '--sv-font-size-xs', label: 'xs — 12px', note: 'Mono identifiers, badges' },
|
|
385
425
|
{ token: '--sv-font-size-label', label: 'label — 11px', note: 'All-caps section labels' },
|
|
426
|
+
{
|
|
427
|
+
token: '--sv-font-size-2xs',
|
|
428
|
+
label: '2xs — 10px',
|
|
429
|
+
note: 'Badge size="xs" — smallest badge tier',
|
|
430
|
+
},
|
|
386
431
|
];
|
|
387
432
|
|
|
388
433
|
// ---------------------------------------------------------------------------
|
|
@@ -631,6 +676,28 @@ function DrawerDemo() {
|
|
|
631
676
|
);
|
|
632
677
|
}
|
|
633
678
|
|
|
679
|
+
function MobileAppsDrawerDemo() {
|
|
680
|
+
const [open, setOpen] = useState(false);
|
|
681
|
+
const items = [
|
|
682
|
+
{ key: 'home', icon: <Icon name="house" size="lg" aria-hidden />, label: 'Home' },
|
|
683
|
+
{ key: 'notes', icon: <Icon name="file" size="lg" aria-hidden />, label: 'Notes' },
|
|
684
|
+
{ key: 'gallery', icon: <Icon name="grid-2x2" size="lg" aria-hidden />, label: 'Gallery' },
|
|
685
|
+
];
|
|
686
|
+
return (
|
|
687
|
+
<>
|
|
688
|
+
<Button size="sm" variant="secondary" onClick={() => setOpen(true)}>
|
|
689
|
+
Open drawer
|
|
690
|
+
</Button>
|
|
691
|
+
<MobileAppsDrawer
|
|
692
|
+
open={open}
|
|
693
|
+
onClose={() => setOpen(false)}
|
|
694
|
+
aria-label="Sections"
|
|
695
|
+
items={items.map((item) => ({ ...item, onClick: () => setOpen(false) }))}
|
|
696
|
+
/>
|
|
697
|
+
</>
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
|
|
634
701
|
function PopoverDemo() {
|
|
635
702
|
const [open, setOpen] = useState(false);
|
|
636
703
|
return (
|
|
@@ -795,6 +862,24 @@ function MenuDemo() {
|
|
|
795
862
|
);
|
|
796
863
|
}
|
|
797
864
|
|
|
865
|
+
function MenuEntriesDemo() {
|
|
866
|
+
return (
|
|
867
|
+
<div style={{ width: '100%', maxWidth: 240 }}>
|
|
868
|
+
<MenuEntries
|
|
869
|
+
items={[
|
|
870
|
+
{ type: 'label', label: 'Sort by' },
|
|
871
|
+
{ label: 'Manual', checked: true },
|
|
872
|
+
{ label: 'Title', checked: false },
|
|
873
|
+
{ type: 'separator' },
|
|
874
|
+
{ label: 'Rename', icon: 'pencil' },
|
|
875
|
+
{ label: 'Delete', icon: 'trash-2', destructive: true },
|
|
876
|
+
]}
|
|
877
|
+
onSelect={() => {}}
|
|
878
|
+
/>
|
|
879
|
+
</div>
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
|
|
798
883
|
function CalendarDemo() {
|
|
799
884
|
const [value, setValue] = useState<Date | null>(new Date());
|
|
800
885
|
return (
|
|
@@ -921,6 +1006,187 @@ function FileDropzoneDemo() {
|
|
|
921
1006
|
);
|
|
922
1007
|
}
|
|
923
1008
|
|
|
1009
|
+
interface StepStripDemoStop extends StepStripItem {
|
|
1010
|
+
label: string;
|
|
1011
|
+
sublabel: string;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
const STEP_STRIP_DEMO_STOPS: StepStripDemoStop[] = [
|
|
1015
|
+
{ id: 'lisbon', label: 'Lisbon', sublabel: 'Aug 26 – 28' },
|
|
1016
|
+
{ id: 'porto', label: 'Porto', sublabel: 'Aug 28 – 30' },
|
|
1017
|
+
];
|
|
1018
|
+
|
|
1019
|
+
function StepStripDemo() {
|
|
1020
|
+
const [activeId, setActiveId] = useState('lisbon');
|
|
1021
|
+
return (
|
|
1022
|
+
<StepStrip
|
|
1023
|
+
items={STEP_STRIP_DEMO_STOPS}
|
|
1024
|
+
activeId={activeId}
|
|
1025
|
+
aria-label="Trip stops"
|
|
1026
|
+
onAdd={() => undefined}
|
|
1027
|
+
addLabel="Add a stop"
|
|
1028
|
+
renderItem={(stop, { isActive }) => (
|
|
1029
|
+
<button
|
|
1030
|
+
type="button"
|
|
1031
|
+
onClick={() => setActiveId(stop.id)}
|
|
1032
|
+
style={{
|
|
1033
|
+
boxSizing: 'border-box',
|
|
1034
|
+
minWidth: '150px',
|
|
1035
|
+
padding: 'var(--sv-space-3) var(--sv-space-4)',
|
|
1036
|
+
borderRadius: 'var(--sv-radius-lg)',
|
|
1037
|
+
border: `1px solid ${isActive ? 'var(--sv-color-text-primary)' : 'var(--sv-color-border)'}`,
|
|
1038
|
+
background: isActive
|
|
1039
|
+
? 'var(--sv-color-text-primary)'
|
|
1040
|
+
: 'var(--sv-color-surface-raised)',
|
|
1041
|
+
color: isActive ? 'var(--sv-color-surface)' : 'var(--sv-color-text-primary)',
|
|
1042
|
+
cursor: 'pointer',
|
|
1043
|
+
textAlign: 'left',
|
|
1044
|
+
}}
|
|
1045
|
+
>
|
|
1046
|
+
<div style={{ fontWeight: 600, fontSize: 'var(--sv-font-size-sm)' }}>{stop.label}</div>
|
|
1047
|
+
<div style={{ fontSize: 'var(--sv-font-size-xs)', opacity: 0.8 }}>{stop.sublabel}</div>
|
|
1048
|
+
</button>
|
|
1049
|
+
)}
|
|
1050
|
+
/>
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
function ResponsiveSurfaceDemo() {
|
|
1055
|
+
return (
|
|
1056
|
+
<div
|
|
1057
|
+
style={{
|
|
1058
|
+
border: '1px dashed var(--sv-color-border)',
|
|
1059
|
+
borderRadius: 'var(--sv-radius-md)',
|
|
1060
|
+
padding: 'var(--sv-space-4)',
|
|
1061
|
+
fontFamily: ff,
|
|
1062
|
+
fontSize: 'var(--sv-font-size-sm)',
|
|
1063
|
+
color: 'var(--sv-color-text-muted)',
|
|
1064
|
+
}}
|
|
1065
|
+
>
|
|
1066
|
+
<ResponsiveSurface
|
|
1067
|
+
web={
|
|
1068
|
+
<span style={{ color: 'var(--sv-color-text-primary)' }}>
|
|
1069
|
+
Web tree (resize below 768px)
|
|
1070
|
+
</span>
|
|
1071
|
+
}
|
|
1072
|
+
mobile={<span style={{ color: 'var(--sv-color-text-primary)' }}>Mobile tree</span>}
|
|
1073
|
+
/>
|
|
1074
|
+
</div>
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
const SWIPABLE_CAROUSEL_DEMO_SLIDES = [
|
|
1079
|
+
{ key: 'lists', label: 'Lists' },
|
|
1080
|
+
{ key: 'groceries', label: 'Groceries' },
|
|
1081
|
+
{ key: 'errands', label: 'Errands' },
|
|
1082
|
+
];
|
|
1083
|
+
|
|
1084
|
+
function SwipableMobileCarouselDemo() {
|
|
1085
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
1086
|
+
return (
|
|
1087
|
+
<div
|
|
1088
|
+
style={{
|
|
1089
|
+
height: 220,
|
|
1090
|
+
border: '1px solid var(--sv-color-border)',
|
|
1091
|
+
borderRadius: 'var(--sv-radius-md)',
|
|
1092
|
+
overflow: 'hidden',
|
|
1093
|
+
}}
|
|
1094
|
+
>
|
|
1095
|
+
<SwipableMobileCarousel
|
|
1096
|
+
activeIndex={activeIndex}
|
|
1097
|
+
onSettle={setActiveIndex}
|
|
1098
|
+
aria-label="Task lists"
|
|
1099
|
+
>
|
|
1100
|
+
{SWIPABLE_CAROUSEL_DEMO_SLIDES.map((slide) => (
|
|
1101
|
+
<SwipableMobileCarouselSlide key={slide.key} slideKey={slide.key} label={slide.label}>
|
|
1102
|
+
<SwipableMobileCarouselSlideHeader>
|
|
1103
|
+
<div
|
|
1104
|
+
style={{
|
|
1105
|
+
padding: 'var(--sv-space-3)',
|
|
1106
|
+
fontFamily: ff,
|
|
1107
|
+
fontWeight: 'var(--sv-font-weight-semibold)',
|
|
1108
|
+
color: 'var(--sv-color-text-primary)',
|
|
1109
|
+
}}
|
|
1110
|
+
>
|
|
1111
|
+
{slide.label}
|
|
1112
|
+
</div>
|
|
1113
|
+
</SwipableMobileCarouselSlideHeader>
|
|
1114
|
+
<SwipableMobileCarouselSlideBody>
|
|
1115
|
+
<div
|
|
1116
|
+
style={{
|
|
1117
|
+
display: 'flex',
|
|
1118
|
+
alignItems: 'center',
|
|
1119
|
+
justifyContent: 'center',
|
|
1120
|
+
height: '100%',
|
|
1121
|
+
fontFamily: ff,
|
|
1122
|
+
color: 'var(--sv-color-text-muted)',
|
|
1123
|
+
}}
|
|
1124
|
+
>
|
|
1125
|
+
{slide.label} content
|
|
1126
|
+
</div>
|
|
1127
|
+
</SwipableMobileCarouselSlideBody>
|
|
1128
|
+
</SwipableMobileCarouselSlide>
|
|
1129
|
+
))}
|
|
1130
|
+
</SwipableMobileCarousel>
|
|
1131
|
+
</div>
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
function SwipableMobileCarouselDotsDemo() {
|
|
1136
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
1137
|
+
return (
|
|
1138
|
+
<SwipableMobileCarouselDots
|
|
1139
|
+
count={3}
|
|
1140
|
+
activeIndex={activeIndex}
|
|
1141
|
+
onJump={setActiveIndex}
|
|
1142
|
+
labels={['Lists', 'Groceries', 'Errands']}
|
|
1143
|
+
aria-label="Task lists"
|
|
1144
|
+
/>
|
|
1145
|
+
);
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
const SWIPE_STACK_DEMO_CARDS = [
|
|
1149
|
+
{ id: 'water-plants', title: 'Water the plants' },
|
|
1150
|
+
{ id: 'standup', title: 'Team standup · 9:30am' },
|
|
1151
|
+
{ id: 'groceries', title: 'Buy groceries' },
|
|
1152
|
+
];
|
|
1153
|
+
|
|
1154
|
+
function SwipeStackDemo() {
|
|
1155
|
+
return (
|
|
1156
|
+
<div style={{ height: 260, maxWidth: 320 }}>
|
|
1157
|
+
<SwipeStack
|
|
1158
|
+
aria-label="Today's agenda"
|
|
1159
|
+
directions={{
|
|
1160
|
+
up: { label: 'Done', icon: 'check' },
|
|
1161
|
+
down: { label: 'Defer', icon: 'history' },
|
|
1162
|
+
}}
|
|
1163
|
+
onSwipe={() => {}}
|
|
1164
|
+
>
|
|
1165
|
+
{SWIPE_STACK_DEMO_CARDS.map((card) => (
|
|
1166
|
+
<SwipeStackCard key={card.id} cardId={card.id}>
|
|
1167
|
+
<div
|
|
1168
|
+
style={{
|
|
1169
|
+
height: '100%',
|
|
1170
|
+
boxSizing: 'border-box',
|
|
1171
|
+
display: 'flex',
|
|
1172
|
+
alignItems: 'center',
|
|
1173
|
+
justifyContent: 'center',
|
|
1174
|
+
padding: 'var(--sv-space-4)',
|
|
1175
|
+
fontFamily: ff,
|
|
1176
|
+
fontWeight: 'var(--sv-font-weight-semibold)',
|
|
1177
|
+
color: 'var(--sv-color-text-primary)',
|
|
1178
|
+
textAlign: 'center',
|
|
1179
|
+
}}
|
|
1180
|
+
>
|
|
1181
|
+
{card.title}
|
|
1182
|
+
</div>
|
|
1183
|
+
</SwipeStackCard>
|
|
1184
|
+
))}
|
|
1185
|
+
</SwipeStack>
|
|
1186
|
+
</div>
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1189
|
+
|
|
924
1190
|
function IconPickerDemo() {
|
|
925
1191
|
const [value, setValue] = useState<IconName | null>('banana');
|
|
926
1192
|
const options: IconName[] = [
|
|
@@ -946,6 +1212,26 @@ function IconPickerDemo() {
|
|
|
946
1212
|
);
|
|
947
1213
|
}
|
|
948
1214
|
|
|
1215
|
+
function ColorPickerDemo() {
|
|
1216
|
+
const [value, setValue] = useState<string | null>('#b5c9e8');
|
|
1217
|
+
const swatches = [
|
|
1218
|
+
{ label: 'Sky', value: '#b5c9e8' },
|
|
1219
|
+
{ label: 'Sage', value: '#c9e0c4' },
|
|
1220
|
+
{ label: 'Sand', value: '#e8d3b5' },
|
|
1221
|
+
{ label: 'Clay', value: '#e0c4c4' },
|
|
1222
|
+
{ label: 'Lilac', value: '#d8c4e0' },
|
|
1223
|
+
];
|
|
1224
|
+
return (
|
|
1225
|
+
<ColorPicker
|
|
1226
|
+
swatches={swatches}
|
|
1227
|
+
value={value}
|
|
1228
|
+
onChange={setValue}
|
|
1229
|
+
allowNone
|
|
1230
|
+
aria-label="Board color"
|
|
1231
|
+
/>
|
|
1232
|
+
);
|
|
1233
|
+
}
|
|
1234
|
+
|
|
949
1235
|
function SuggestionInputDemo() {
|
|
950
1236
|
const [value, setValue] = useState('ban');
|
|
951
1237
|
const options = ['Bananas', 'Banana bread mix']
|
|
@@ -1423,6 +1709,21 @@ font-weight: var(--sv-font-weight-medium); /* 500 */
|
|
|
1423
1709
|
font-weight: var(--sv-font-weight-semibold); /* 600 */
|
|
1424
1710
|
font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
1425
1711
|
</div>
|
|
1712
|
+
|
|
1713
|
+
<div style={{ marginTop: 'var(--sv-space-4)' }}>
|
|
1714
|
+
<p
|
|
1715
|
+
style={{
|
|
1716
|
+
fontSize: 'var(--sv-font-size-caption)',
|
|
1717
|
+
color: 'var(--sv-color-text-muted)',
|
|
1718
|
+
}}
|
|
1719
|
+
>
|
|
1720
|
+
Every size above is rem-based, so the whole scale responds to the in-app text-size
|
|
1721
|
+
control (Account → Preferences → Appearance, task 10.2), which sets{' '}
|
|
1722
|
+
<code>[data-text-size]</code> on <code><html></code> to override{' '}
|
|
1723
|
+
<code>--sv-text-size-scale</code> — see the "Text-size presets" section of
|
|
1724
|
+
the Token Gallery.
|
|
1725
|
+
</p>
|
|
1726
|
+
</div>
|
|
1426
1727
|
</section>
|
|
1427
1728
|
|
|
1428
1729
|
{/* ── Spacing & Radius ─────────────────────────────────────────── */}
|
|
@@ -1582,7 +1883,7 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
1582
1883
|
<section style={{ marginBottom: 'var(--sv-space-12)' }}>
|
|
1583
1884
|
<SectionHeader
|
|
1584
1885
|
title="Component gallery"
|
|
1585
|
-
subtitle="All
|
|
1886
|
+
subtitle="All 77 components — click each story in the sidebar for the full API, variants, and controls."
|
|
1586
1887
|
/>
|
|
1587
1888
|
|
|
1588
1889
|
<div style={{ marginBottom: 'var(--sv-space-6)' }}>
|
|
@@ -1620,7 +1921,7 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
1620
1921
|
<ComponentCard
|
|
1621
1922
|
name="Badge"
|
|
1622
1923
|
importLine="import { Badge } from '@sovereignfs/ui';"
|
|
1623
|
-
usage="Compact label for roles (role), lifecycle states (status), and type/version tags (mono). sm/md/lg sizes; ALL CAPS by default, or uppercase={false} for title case. RSC-safe."
|
|
1924
|
+
usage="Compact label for roles (role), lifecycle states (status), and type/version tags (mono). xs/sm/md/lg sizes; ALL CAPS by default, or uppercase={false} for title case. RSC-safe."
|
|
1624
1925
|
>
|
|
1625
1926
|
<Badge variant="role">Admin</Badge>
|
|
1626
1927
|
<Badge variant="status" status="active">
|
|
@@ -1633,6 +1934,9 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
1633
1934
|
<Badge variant="role" size="lg" uppercase={false}>
|
|
1634
1935
|
Owner
|
|
1635
1936
|
</Badge>
|
|
1937
|
+
<Badge variant="status" status="active" size="xs">
|
|
1938
|
+
Connected
|
|
1939
|
+
</Badge>
|
|
1636
1940
|
</ComponentCard>
|
|
1637
1941
|
|
|
1638
1942
|
{/* StatusBadge */}
|
|
@@ -1708,6 +2012,15 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
1708
2012
|
<IconPickerDemo />
|
|
1709
2013
|
</ComponentCard>
|
|
1710
2014
|
|
|
2015
|
+
{/* ColorPicker */}
|
|
2016
|
+
<ComponentCard
|
|
2017
|
+
name="ColorPicker"
|
|
2018
|
+
importLine="import { ColorPicker } from '@sovereignfs/ui';"
|
|
2019
|
+
usage="Curated swatch suggestions plus a native color-input trigger for picking any color — not just the curated set."
|
|
2020
|
+
>
|
|
2021
|
+
<ColorPickerDemo />
|
|
2022
|
+
</ComponentCard>
|
|
2023
|
+
|
|
1711
2024
|
{/* QuantityStepper */}
|
|
1712
2025
|
<ComponentCard
|
|
1713
2026
|
name="QuantityStepper"
|
|
@@ -1781,7 +2094,7 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
1781
2094
|
<ComponentCard
|
|
1782
2095
|
name="Icon"
|
|
1783
2096
|
importLine="import { Icon } from '@sovereignfs/ui';"
|
|
1784
|
-
usage="SVG icon primitive.
|
|
2097
|
+
usage="SVG icon primitive. 96 bundled icons. Decorative: aria-hidden. Meaningful: aria-label. Three sizes: sm, md, lg."
|
|
1785
2098
|
>
|
|
1786
2099
|
{(
|
|
1787
2100
|
[
|
|
@@ -1864,6 +2177,15 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
1864
2177
|
<MenuDemo />
|
|
1865
2178
|
</ComponentCard>
|
|
1866
2179
|
|
|
2180
|
+
{/* MenuEntries */}
|
|
2181
|
+
<ComponentCard
|
|
2182
|
+
name="MenuEntries"
|
|
2183
|
+
importLine="import { MenuEntries } from '@sovereignfs/ui';"
|
|
2184
|
+
usage='The <ul role="menu"> item list itself, factored out of Menu so other adaptive-surface components (ContextMenu, Menubar) can render the exact same items/destructive/checked/icon markup inside their own positioning shell instead of re-deriving it. No panel chrome of its own — the background/border/shadow around it belongs to whichever surface hosts it.'
|
|
2185
|
+
>
|
|
2186
|
+
<MenuEntriesDemo />
|
|
2187
|
+
</ComponentCard>
|
|
2188
|
+
|
|
1867
2189
|
{/* Calendar */}
|
|
1868
2190
|
<ComponentCard
|
|
1869
2191
|
name="Calendar"
|
|
@@ -1899,7 +2221,7 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
1899
2221
|
<ComponentCard
|
|
1900
2222
|
name="Toast"
|
|
1901
2223
|
importLine="import { ToastProvider, useToast } from '@sovereignfs/ui';"
|
|
1902
|
-
usage="Fixed top-right
|
|
2224
|
+
usage="Fixed top-right on desktop, bottom-center on mobile. Wrap app in ToastProvider; call useToast().show() imperatively. Six categories."
|
|
1903
2225
|
>
|
|
1904
2226
|
<ToastProvider>
|
|
1905
2227
|
<ToastDemo />
|
|
@@ -1920,6 +2242,38 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
1920
2242
|
</div>
|
|
1921
2243
|
</ComponentCard>
|
|
1922
2244
|
|
|
2245
|
+
{/* CardTile */}
|
|
2246
|
+
<ComponentCard
|
|
2247
|
+
name="CardTile"
|
|
2248
|
+
importLine="import { CardTile, CardTileGrid, NewCardTile } from '@sovereignfs/ui';"
|
|
2249
|
+
usage="A colored/iconed banner over a footer label, for a grid of navigable top-level entities (projects, boards). Card can't express this — its padding always wraps the whole box, with no bleed slot for a full-width banner. Not link-aware; wrap each tile in the host router's own link component. Pair with NewCardTile for the grid's 'add new' affordance. The icon variant below swaps the card chrome for a plain Finder-style icon + label, for entities that read as a single glyph + name (e.g. a folder)."
|
|
2250
|
+
>
|
|
2251
|
+
<CardTileGrid minTileWidth={140}>
|
|
2252
|
+
<CardTile banner={<Icon name="folder" size="lg" aria-hidden={true} />}>
|
|
2253
|
+
Q4 Planning
|
|
2254
|
+
</CardTile>
|
|
2255
|
+
<CardTile bannerColor="#c7d8ff">Marketing site</CardTile>
|
|
2256
|
+
<NewCardTile label="New project" />
|
|
2257
|
+
</CardTileGrid>
|
|
2258
|
+
<div style={{ marginTop: 'var(--sv-space-4)' }}>
|
|
2259
|
+
<CardTileGrid dense minTileWidth={100}>
|
|
2260
|
+
<CardTile
|
|
2261
|
+
variant="icon"
|
|
2262
|
+
banner={<Icon name="folder-closed" size="lg" aria-hidden={true} />}
|
|
2263
|
+
>
|
|
2264
|
+
Handbook
|
|
2265
|
+
</CardTile>
|
|
2266
|
+
<CardTile
|
|
2267
|
+
variant="icon"
|
|
2268
|
+
banner={<Icon name="folder-closed" size="lg" aria-hidden={true} />}
|
|
2269
|
+
>
|
|
2270
|
+
Q4 Planning
|
|
2271
|
+
</CardTile>
|
|
2272
|
+
<NewCardTile variant="icon" label="New" />
|
|
2273
|
+
</CardTileGrid>
|
|
2274
|
+
</div>
|
|
2275
|
+
</ComponentCard>
|
|
2276
|
+
|
|
1923
2277
|
{/* FormField */}
|
|
1924
2278
|
<ComponentCard
|
|
1925
2279
|
name="FormField"
|
|
@@ -1998,11 +2352,186 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
1998
2352
|
/>
|
|
1999
2353
|
</ComponentCard>
|
|
2000
2354
|
|
|
2355
|
+
{/* ThreeColumnLayout */}
|
|
2356
|
+
<ComponentCard
|
|
2357
|
+
name="ThreeColumnLayout"
|
|
2358
|
+
importLine="import { ThreeColumnLayout } from '@sovereignfs/ui';"
|
|
2359
|
+
usage="Sidebar + main + optional detail column, for list-app shells (Tasks, Shopper). Purely positional — pass 2 children for sidebar+main, or 3 for sidebar+main+detail; the third is simply omitted when nothing is selected."
|
|
2360
|
+
>
|
|
2361
|
+
<div style={{ width: '100%', height: '220px' }}>
|
|
2362
|
+
<ThreeColumnLayout sidebarWidth={120} detailWidth={140}>
|
|
2363
|
+
<div
|
|
2364
|
+
style={{
|
|
2365
|
+
padding: 'var(--sv-space-3)',
|
|
2366
|
+
fontFamily: ffm,
|
|
2367
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2368
|
+
color: 'var(--sv-color-text-primary)',
|
|
2369
|
+
}}
|
|
2370
|
+
>
|
|
2371
|
+
Sidebar
|
|
2372
|
+
</div>
|
|
2373
|
+
<div
|
|
2374
|
+
style={{
|
|
2375
|
+
padding: 'var(--sv-space-3)',
|
|
2376
|
+
fontFamily: ffm,
|
|
2377
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2378
|
+
color: 'var(--sv-color-text-primary)',
|
|
2379
|
+
}}
|
|
2380
|
+
>
|
|
2381
|
+
Main
|
|
2382
|
+
</div>
|
|
2383
|
+
<div
|
|
2384
|
+
style={{
|
|
2385
|
+
padding: 'var(--sv-space-3)',
|
|
2386
|
+
fontFamily: ffm,
|
|
2387
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2388
|
+
color: 'var(--sv-color-text-primary)',
|
|
2389
|
+
}}
|
|
2390
|
+
>
|
|
2391
|
+
Detail
|
|
2392
|
+
</div>
|
|
2393
|
+
</ThreeColumnLayout>
|
|
2394
|
+
</div>
|
|
2395
|
+
</ComponentCard>
|
|
2396
|
+
|
|
2397
|
+
{/* HeaderFooterLayout */}
|
|
2398
|
+
<ComponentCard
|
|
2399
|
+
name="HeaderFooterLayout"
|
|
2400
|
+
importLine="import { HeaderFooterLayout } from '@sovereignfs/ui';"
|
|
2401
|
+
usage="Header + main + optional footer, both fixed-height and independently optional; main always claims the remaining height. The vertical counterpart to ThreeColumnLayout."
|
|
2402
|
+
>
|
|
2403
|
+
<div style={{ width: '100%', height: '220px' }}>
|
|
2404
|
+
<HeaderFooterLayout
|
|
2405
|
+
headerHeight={36}
|
|
2406
|
+
footerHeight={36}
|
|
2407
|
+
header={
|
|
2408
|
+
<div
|
|
2409
|
+
style={{
|
|
2410
|
+
display: 'flex',
|
|
2411
|
+
alignItems: 'center',
|
|
2412
|
+
justifyContent: 'center',
|
|
2413
|
+
height: '100%',
|
|
2414
|
+
fontFamily: ffm,
|
|
2415
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2416
|
+
color: 'var(--sv-color-text-primary)',
|
|
2417
|
+
}}
|
|
2418
|
+
>
|
|
2419
|
+
Header
|
|
2420
|
+
</div>
|
|
2421
|
+
}
|
|
2422
|
+
footer={
|
|
2423
|
+
<div
|
|
2424
|
+
style={{
|
|
2425
|
+
display: 'flex',
|
|
2426
|
+
alignItems: 'center',
|
|
2427
|
+
justifyContent: 'center',
|
|
2428
|
+
height: '100%',
|
|
2429
|
+
fontFamily: ffm,
|
|
2430
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2431
|
+
color: 'var(--sv-color-text-primary)',
|
|
2432
|
+
}}
|
|
2433
|
+
>
|
|
2434
|
+
Footer
|
|
2435
|
+
</div>
|
|
2436
|
+
}
|
|
2437
|
+
>
|
|
2438
|
+
<div
|
|
2439
|
+
style={{
|
|
2440
|
+
padding: 'var(--sv-space-3)',
|
|
2441
|
+
fontFamily: ffm,
|
|
2442
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2443
|
+
color: 'var(--sv-color-text-primary)',
|
|
2444
|
+
}}
|
|
2445
|
+
>
|
|
2446
|
+
Main (scrolls)
|
|
2447
|
+
</div>
|
|
2448
|
+
</HeaderFooterLayout>
|
|
2449
|
+
</div>
|
|
2450
|
+
</ComponentCard>
|
|
2451
|
+
|
|
2452
|
+
{/* RootLayout */}
|
|
2453
|
+
<ComponentCard
|
|
2454
|
+
name="RootLayout"
|
|
2455
|
+
importLine="import { RootLayout } from '@sovereignfs/ui';"
|
|
2456
|
+
usage="The root-level layout a plugin's page tree sits in. variant='sidebar' is web-only (sidebar + main); variant='shell' is mobile-only (header + main + footer) — same children, different fork per breakpoint via ResponsiveSurface. Shown here: variant='header', identical on both breakpoints."
|
|
2457
|
+
>
|
|
2458
|
+
<div style={{ width: '100%', height: '160px' }}>
|
|
2459
|
+
<RootLayout variant="header" headerHeight={32}>
|
|
2460
|
+
<div
|
|
2461
|
+
style={{
|
|
2462
|
+
display: 'flex',
|
|
2463
|
+
alignItems: 'center',
|
|
2464
|
+
justifyContent: 'center',
|
|
2465
|
+
height: '100%',
|
|
2466
|
+
fontFamily: ffm,
|
|
2467
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2468
|
+
color: 'var(--sv-color-text-primary)',
|
|
2469
|
+
}}
|
|
2470
|
+
>
|
|
2471
|
+
Header
|
|
2472
|
+
</div>
|
|
2473
|
+
<div
|
|
2474
|
+
style={{
|
|
2475
|
+
padding: 'var(--sv-space-3)',
|
|
2476
|
+
fontFamily: ffm,
|
|
2477
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2478
|
+
color: 'var(--sv-color-text-primary)',
|
|
2479
|
+
}}
|
|
2480
|
+
>
|
|
2481
|
+
Main
|
|
2482
|
+
</div>
|
|
2483
|
+
</RootLayout>
|
|
2484
|
+
</div>
|
|
2485
|
+
</ComponentCard>
|
|
2486
|
+
|
|
2487
|
+
{/* PageLayout */}
|
|
2488
|
+
<ComponentCard
|
|
2489
|
+
name="PageLayout"
|
|
2490
|
+
importLine="import { PageLayout } from '@sovereignfs/ui';"
|
|
2491
|
+
usage="A single page's content area, nested inside RootLayout's main slot. No padding by default (opt in via padding, same scale as PageContainer). The optional header is page-specific — a board title/toolbar, not the app-level header."
|
|
2492
|
+
>
|
|
2493
|
+
<div
|
|
2494
|
+
style={{
|
|
2495
|
+
width: '100%',
|
|
2496
|
+
height: '160px',
|
|
2497
|
+
border: '1px solid var(--sv-color-border)',
|
|
2498
|
+
}}
|
|
2499
|
+
>
|
|
2500
|
+
<PageLayout
|
|
2501
|
+
padding="sm"
|
|
2502
|
+
header={
|
|
2503
|
+
<div
|
|
2504
|
+
style={{
|
|
2505
|
+
padding: 'var(--sv-space-2) var(--sv-space-3)',
|
|
2506
|
+
borderBottom: '1px solid var(--sv-color-border)',
|
|
2507
|
+
fontFamily: ffm,
|
|
2508
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2509
|
+
fontWeight: 600,
|
|
2510
|
+
color: 'var(--sv-color-text-primary)',
|
|
2511
|
+
}}
|
|
2512
|
+
>
|
|
2513
|
+
Page header
|
|
2514
|
+
</div>
|
|
2515
|
+
}
|
|
2516
|
+
>
|
|
2517
|
+
<div
|
|
2518
|
+
style={{
|
|
2519
|
+
fontFamily: ffm,
|
|
2520
|
+
fontSize: 'var(--sv-font-size-xs)',
|
|
2521
|
+
color: 'var(--sv-color-text-primary)',
|
|
2522
|
+
}}
|
|
2523
|
+
>
|
|
2524
|
+
Page content
|
|
2525
|
+
</div>
|
|
2526
|
+
</PageLayout>
|
|
2527
|
+
</div>
|
|
2528
|
+
</ComponentCard>
|
|
2529
|
+
|
|
2001
2530
|
{/* PageHeader */}
|
|
2002
2531
|
<ComponentCard
|
|
2003
2532
|
name="PageHeader"
|
|
2004
2533
|
importLine="import { PageHeader } from '@sovereignfs/ui';"
|
|
2005
|
-
usage="Plugin page top section. Title + optional description + right-side action slot. Replaces the hand-rolled .pageHeader pattern in every plugin."
|
|
2534
|
+
usage="Plugin page top section. Title + optional description + right-side action slot. Replaces the hand-rolled .pageHeader pattern in every plugin. An optional `icon` renders before the title text on both breakpoints. On mobile, description drops out and onBack/onMenuClick add an optional back button and vertical-ellipsis menu trigger."
|
|
2006
2535
|
>
|
|
2007
2536
|
<div style={{ width: '100%' }}>
|
|
2008
2537
|
<PageHeader
|
|
@@ -2013,6 +2542,223 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
2013
2542
|
</div>
|
|
2014
2543
|
</ComponentCard>
|
|
2015
2544
|
|
|
2545
|
+
{/* PageContainer */}
|
|
2546
|
+
<ComponentCard
|
|
2547
|
+
name="PageContainer"
|
|
2548
|
+
importLine="import { PageContainer } from '@sovereignfs/ui';"
|
|
2549
|
+
usage="The wrapper every plugin page renders through. Supplies the page gutter (padding: none/sm/md/lg, default md — the runtime shell no longer pads plugin content) and constrains width (maxWidth: sm/md/lg/full, default full). Use instead of declaring padding or max-width in a plugin's own CSS."
|
|
2550
|
+
>
|
|
2551
|
+
<div style={{ width: '100%', background: 'var(--sv-color-surface-sunken)' }}>
|
|
2552
|
+
<PageContainer maxWidth="sm" padding="md">
|
|
2553
|
+
<div
|
|
2554
|
+
style={{
|
|
2555
|
+
background: 'var(--sv-color-surface-raised)',
|
|
2556
|
+
border: '1px dashed var(--sv-color-border)',
|
|
2557
|
+
borderRadius: 'var(--sv-radius-md)',
|
|
2558
|
+
padding: 'var(--sv-space-4)',
|
|
2559
|
+
}}
|
|
2560
|
+
>
|
|
2561
|
+
maxWidth="sm" padding="md"
|
|
2562
|
+
</div>
|
|
2563
|
+
</PageContainer>
|
|
2564
|
+
</div>
|
|
2565
|
+
</ComponentCard>
|
|
2566
|
+
|
|
2567
|
+
{/* Header */}
|
|
2568
|
+
<ComponentCard
|
|
2569
|
+
name="Header"
|
|
2570
|
+
importLine="import { Header } from '@sovereignfs/ui';"
|
|
2571
|
+
usage="The web top-bar header for shell: minimal plugins that own their whole viewport (no platform sidebar). Brand badge + optional active plugin on the left; launcher (AppsLauncher), notifications (NotificationsPanel), and avatarMenu (UserMenu) on the right — all real, shared, independently clickable components. Presentational only — see Components/Header for the mobile counterpart (MobileHeader) shown side by side."
|
|
2572
|
+
>
|
|
2573
|
+
<Header
|
|
2574
|
+
instanceName="Sovereign"
|
|
2575
|
+
homeHref="/launcher"
|
|
2576
|
+
plugin={{
|
|
2577
|
+
// The plugin icon is 28px — the same size as the brand
|
|
2578
|
+
// badge next to it, not a smaller inline glyph.
|
|
2579
|
+
name: 'Notes',
|
|
2580
|
+
icon: (
|
|
2581
|
+
<span
|
|
2582
|
+
aria-hidden="true"
|
|
2583
|
+
style={{
|
|
2584
|
+
display: 'inline-flex',
|
|
2585
|
+
alignItems: 'center',
|
|
2586
|
+
justifyContent: 'center',
|
|
2587
|
+
width: 28,
|
|
2588
|
+
height: 28,
|
|
2589
|
+
}}
|
|
2590
|
+
>
|
|
2591
|
+
<span style={{ display: 'inline-flex', transform: 'scale(1.15)' }}>
|
|
2592
|
+
<Icon name="file" size="lg" aria-hidden />
|
|
2593
|
+
</span>
|
|
2594
|
+
</span>
|
|
2595
|
+
),
|
|
2596
|
+
href: '/notes',
|
|
2597
|
+
}}
|
|
2598
|
+
launcher={
|
|
2599
|
+
<AppsLauncher
|
|
2600
|
+
items={[
|
|
2601
|
+
{
|
|
2602
|
+
key: 'home',
|
|
2603
|
+
icon: <Icon name="house" size="md" aria-hidden />,
|
|
2604
|
+
label: 'Home',
|
|
2605
|
+
href: '/launcher',
|
|
2606
|
+
},
|
|
2607
|
+
{
|
|
2608
|
+
key: 'notes',
|
|
2609
|
+
icon: <Icon name="file" size="md" aria-hidden />,
|
|
2610
|
+
label: 'Notes',
|
|
2611
|
+
href: '/notes',
|
|
2612
|
+
},
|
|
2613
|
+
]}
|
|
2614
|
+
/>
|
|
2615
|
+
}
|
|
2616
|
+
notifications={<NotificationsPanel items={[]} unreadCount={0} />}
|
|
2617
|
+
avatarMenu={
|
|
2618
|
+
<UserMenu
|
|
2619
|
+
name="Kasun Benthara"
|
|
2620
|
+
email="kasun@openfs.io"
|
|
2621
|
+
items={[
|
|
2622
|
+
{ label: 'Account', icon: 'user', href: '/account' },
|
|
2623
|
+
{ label: 'Sign out', icon: 'log-out', destructive: true, onSelect: () => {} },
|
|
2624
|
+
]}
|
|
2625
|
+
size="sm"
|
|
2626
|
+
/>
|
|
2627
|
+
}
|
|
2628
|
+
/>
|
|
2629
|
+
</ComponentCard>
|
|
2630
|
+
|
|
2631
|
+
{/* AppsLauncher */}
|
|
2632
|
+
<ComponentCard
|
|
2633
|
+
name="AppsLauncher"
|
|
2634
|
+
importLine="import { AppsLauncher } from '@sovereignfs/ui';"
|
|
2635
|
+
usage="The desktop 'Apps' switcher — a 28px grid trigger opening a Popover tile grid. The desktop counterpart to MobileAppsDrawer: same items shape (key/icon/label/href/onClick), different chrome. Presentational only — items are supplied already resolved; loading/error are separate props."
|
|
2636
|
+
>
|
|
2637
|
+
<AppsLauncher
|
|
2638
|
+
items={[
|
|
2639
|
+
{
|
|
2640
|
+
key: 'home',
|
|
2641
|
+
icon: <Icon name="house" size="md" aria-hidden />,
|
|
2642
|
+
label: 'Home',
|
|
2643
|
+
href: '/launcher',
|
|
2644
|
+
},
|
|
2645
|
+
{
|
|
2646
|
+
key: 'console',
|
|
2647
|
+
icon: <Icon name="layout-dashboard" size="md" aria-hidden />,
|
|
2648
|
+
label: 'Console',
|
|
2649
|
+
href: '/console',
|
|
2650
|
+
},
|
|
2651
|
+
{
|
|
2652
|
+
key: 'notes',
|
|
2653
|
+
icon: <Icon name="file" size="md" aria-hidden />,
|
|
2654
|
+
label: 'Notes',
|
|
2655
|
+
href: '/notes',
|
|
2656
|
+
},
|
|
2657
|
+
]}
|
|
2658
|
+
/>
|
|
2659
|
+
</ComponentCard>
|
|
2660
|
+
|
|
2661
|
+
{/* NotificationsPanel */}
|
|
2662
|
+
<ComponentCard
|
|
2663
|
+
name="NotificationsPanel"
|
|
2664
|
+
importLine="import { NotificationsPanel } from '@sovereignfs/ui';"
|
|
2665
|
+
usage="The bell trigger + dropdown, generalized from the runtime shell's own NotificationBell — title/Mark all read/Clear all/close, then category-icon + title + time + unread-dot + dismiss rows. Pure presentation: no fetch/SSE/mark-read logic of its own; the consumer supplies already-resolved items and wires onOpen/onDismiss/onMarkAllRead/onClearAll."
|
|
2666
|
+
>
|
|
2667
|
+
<NotificationsPanel
|
|
2668
|
+
items={[
|
|
2669
|
+
{
|
|
2670
|
+
id: '1',
|
|
2671
|
+
icon: <Icon name="layers" size="sm" aria-hidden />,
|
|
2672
|
+
title: 'Added to a project',
|
|
2673
|
+
timeLabel: '2d ago',
|
|
2674
|
+
read: false,
|
|
2675
|
+
onDismiss: () => {},
|
|
2676
|
+
},
|
|
2677
|
+
]}
|
|
2678
|
+
unreadCount={1}
|
|
2679
|
+
onMarkAllRead={() => {}}
|
|
2680
|
+
onClearAll={() => {}}
|
|
2681
|
+
/>
|
|
2682
|
+
</ComponentCard>
|
|
2683
|
+
|
|
2684
|
+
{/* UserMenu */}
|
|
2685
|
+
<ComponentCard
|
|
2686
|
+
name="UserMenu"
|
|
2687
|
+
importLine="import { UserMenu } from '@sovereignfs/ui';"
|
|
2688
|
+
usage="The account avatar trigger + dropdown, generalized from the runtime shell's own AccountMenu — accent-filled avatar, a name/email header block, then a plain item list. Presentational only: no auth/session logic — items carry their own onSelect and/or href (e.g. a real 'Sign out' item just does whatever the consuming app's sign-out requires)."
|
|
2689
|
+
>
|
|
2690
|
+
<UserMenu
|
|
2691
|
+
name="Kasun Benthara"
|
|
2692
|
+
email="kasun@openfs.io"
|
|
2693
|
+
items={[
|
|
2694
|
+
{ label: 'Account', icon: 'user', href: '/account' },
|
|
2695
|
+
{
|
|
2696
|
+
label: 'Preferences',
|
|
2697
|
+
icon: 'sliders-horizontal',
|
|
2698
|
+
href: '/account/preferences',
|
|
2699
|
+
},
|
|
2700
|
+
{ label: 'Sign out', icon: 'log-out', destructive: true, onSelect: () => {} },
|
|
2701
|
+
]}
|
|
2702
|
+
/>
|
|
2703
|
+
</ComponentCard>
|
|
2704
|
+
|
|
2705
|
+
{/* MobileHeader */}
|
|
2706
|
+
<ComponentCard
|
|
2707
|
+
name="MobileHeader"
|
|
2708
|
+
importLine="import { MobileHeader } from '@sovereignfs/ui';"
|
|
2709
|
+
usage="Mobile shell header content row (RFC 0088). Bell and avatarMenu are always rendered by the consumer; logo is optional — omit it for a default 'S' badge (matching the shell's own fallback brand icon), or supply your own. Title is the only content-level override. Presentational only — see Overview/Mobile Patterns for the full immutable/overridable boundary."
|
|
2710
|
+
>
|
|
2711
|
+
<div
|
|
2712
|
+
style={{
|
|
2713
|
+
width: '100%',
|
|
2714
|
+
background: 'var(--sv-color-surface)',
|
|
2715
|
+
border: '1px solid var(--sv-color-border)',
|
|
2716
|
+
borderRadius: 'var(--sv-radius-md)',
|
|
2717
|
+
padding: '0 var(--sv-space-3)',
|
|
2718
|
+
}}
|
|
2719
|
+
>
|
|
2720
|
+
<MobileHeader
|
|
2721
|
+
title="Tasks"
|
|
2722
|
+
bell={<Icon name="bell" size="lg" aria-label="Notifications" />}
|
|
2723
|
+
avatarMenu={<Avatar name="Jamie Doe" size="sm" />}
|
|
2724
|
+
/>
|
|
2725
|
+
</div>
|
|
2726
|
+
</ComponentCard>
|
|
2727
|
+
|
|
2728
|
+
{/* MobileFooter */}
|
|
2729
|
+
<ComponentCard
|
|
2730
|
+
name="MobileFooter"
|
|
2731
|
+
importLine="import { MobileFooter } from '@sovereignfs/ui';"
|
|
2732
|
+
usage="Mobile shell footer nav row (RFC 0088). The centered launcher (onOpenApps) is always rendered; leftIcons/rightIcons take 1 or 2 items each, symmetric so the launcher stays centered."
|
|
2733
|
+
>
|
|
2734
|
+
<div
|
|
2735
|
+
style={{
|
|
2736
|
+
width: '100%',
|
|
2737
|
+
background: 'var(--sv-color-surface)',
|
|
2738
|
+
border: '1px solid var(--sv-color-border)',
|
|
2739
|
+
borderRadius: 'var(--sv-radius-md)',
|
|
2740
|
+
padding: '0 var(--sv-space-3)',
|
|
2741
|
+
}}
|
|
2742
|
+
>
|
|
2743
|
+
<MobileFooter
|
|
2744
|
+
onOpenApps={() => {}}
|
|
2745
|
+
leftIcons={[{ icon: <Icon name="house" size="md" aria-hidden />, label: 'Home' }]}
|
|
2746
|
+
rightIcons={[
|
|
2747
|
+
{ icon: <Icon name="search" size="md" aria-hidden />, label: 'Search' },
|
|
2748
|
+
]}
|
|
2749
|
+
/>
|
|
2750
|
+
</div>
|
|
2751
|
+
</ComponentCard>
|
|
2752
|
+
|
|
2753
|
+
{/* MobileAppsDrawer */}
|
|
2754
|
+
<ComponentCard
|
|
2755
|
+
name="MobileAppsDrawer"
|
|
2756
|
+
importLine="import { MobileAppsDrawer } from '@sovereignfs/ui';"
|
|
2757
|
+
usage="The mobile 'Apps' bottom sheet: a 3-column tile grid matching the runtime shell's own Apps drawer exactly (56px icon tiles, radius 14px). No header row — Drawer's own grab handle plus swipe-down/scrim-tap dismissal are enough. The tile list is supplied by the consumer via `items` — e.g. installed plugins for the shell, or a plugin's own sections for its own launcher button."
|
|
2758
|
+
>
|
|
2759
|
+
<MobileAppsDrawerDemo />
|
|
2760
|
+
</ComponentCard>
|
|
2761
|
+
|
|
2016
2762
|
{/* EmptyState */}
|
|
2017
2763
|
<ComponentCard
|
|
2018
2764
|
name="EmptyState"
|
|
@@ -2031,6 +2777,53 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
2031
2777
|
/>
|
|
2032
2778
|
</ComponentCard>
|
|
2033
2779
|
|
|
2780
|
+
{/* OfflineGate */}
|
|
2781
|
+
<ComponentCard
|
|
2782
|
+
name="OfflineGate"
|
|
2783
|
+
importLine="import { OfflineGate } from '@sovereignfs/ui';"
|
|
2784
|
+
usage="Blocks an administrative/settings surface from rendering possibly-stale cached content while offline, showing an EmptyState instead. Reads the live useIsOffline() hook — toggle DevTools > Network > Offline to see it swap. Wrap the body of a surface like Console or Account where operating against stale data is actively wrong, not every page."
|
|
2785
|
+
>
|
|
2786
|
+
<OfflineGate surfaceName="Console">
|
|
2787
|
+
<p style={{ margin: 0, fontFamily: 'var(--sv-font-family)', fontSize: 14 }}>
|
|
2788
|
+
Renders normally while online.
|
|
2789
|
+
</p>
|
|
2790
|
+
</OfflineGate>
|
|
2791
|
+
</ComponentCard>
|
|
2792
|
+
|
|
2793
|
+
{/* DeviceOnlyGate */}
|
|
2794
|
+
<ComponentCard
|
|
2795
|
+
name="DeviceOnlyGate"
|
|
2796
|
+
importLine="import { DeviceOnlyGate } from '@sovereignfs/ui';"
|
|
2797
|
+
usage="Blocks a device-only-tier plugin's content on a surface without the durable, encrypted, device-auth-gated store that tier needs. `available` is the caller's own isDeviceOnlyTierAvailable() result (from @sovereignfs/sdk/device-client) — a capability signal, never a security boundary; the real protection is that the data is encrypted regardless."
|
|
2798
|
+
>
|
|
2799
|
+
<DeviceOnlyGate available={false} surfaceName="Wallet">
|
|
2800
|
+
<p style={{ margin: 0, fontFamily: 'var(--sv-font-family)', fontSize: 14 }}>
|
|
2801
|
+
Renders normally when available.
|
|
2802
|
+
</p>
|
|
2803
|
+
</DeviceOnlyGate>
|
|
2804
|
+
</ComponentCard>
|
|
2805
|
+
|
|
2806
|
+
{/* DeviceStorageKeyGate */}
|
|
2807
|
+
<ComponentCard
|
|
2808
|
+
name="DeviceStorageKeyGate"
|
|
2809
|
+
importLine="import { DeviceStorageKeyGate } from '@sovereignfs/ui';"
|
|
2810
|
+
usage="Blocks a device-only-tier plugin's content until the user has set up their Device Storage Key. `status` is the caller's own getDeviceStorageKeyStatus() result (from @sovereignfs/sdk/device-only-storage). Enrollment is centralized in Account > Security, not per-plugin — `setupAction` is where the caller supplies a link there."
|
|
2811
|
+
>
|
|
2812
|
+
<DeviceStorageKeyGate
|
|
2813
|
+
status="not-set-up"
|
|
2814
|
+
surfaceName="Notes"
|
|
2815
|
+
setupAction={
|
|
2816
|
+
<a href="/account/security" style={{ color: 'var(--sv-color-accent)' }}>
|
|
2817
|
+
Go to Account → Security
|
|
2818
|
+
</a>
|
|
2819
|
+
}
|
|
2820
|
+
>
|
|
2821
|
+
<p style={{ margin: 0, fontFamily: 'var(--sv-font-family)', fontSize: 14 }}>
|
|
2822
|
+
Renders normally once set up.
|
|
2823
|
+
</p>
|
|
2824
|
+
</DeviceStorageKeyGate>
|
|
2825
|
+
</ComponentCard>
|
|
2826
|
+
|
|
2034
2827
|
{/* Spinner */}
|
|
2035
2828
|
<ComponentCard
|
|
2036
2829
|
name="Spinner"
|
|
@@ -2076,6 +2869,42 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
2076
2869
|
</div>
|
|
2077
2870
|
</ComponentCard>
|
|
2078
2871
|
|
|
2872
|
+
{/* NavList */}
|
|
2873
|
+
<ComponentCard
|
|
2874
|
+
name="NavList"
|
|
2875
|
+
importLine="import { NavList } from '@sovereignfs/ui';"
|
|
2876
|
+
usage='Vertical list of icon+label rows, optionally grouped under section headers. static: active row highlighted, no chevron — a persistent sidebar. drilldown: trailing chevron on every row, no active state — a native-Settings-app style index. density="compact" (static only) shrinks row height for a short, always-visible list. Framework-agnostic like NavTabs; supply active/renderLink from the consumer.'
|
|
2877
|
+
>
|
|
2878
|
+
<div style={{ width: '100%', maxWidth: 220 }}>
|
|
2879
|
+
<NavList
|
|
2880
|
+
variant="static"
|
|
2881
|
+
aria-label="Example sections"
|
|
2882
|
+
groups={[
|
|
2883
|
+
{
|
|
2884
|
+
id: 'overview',
|
|
2885
|
+
items: [
|
|
2886
|
+
{
|
|
2887
|
+
id: 'overview',
|
|
2888
|
+
label: 'Overview',
|
|
2889
|
+
href: '#',
|
|
2890
|
+
icon: 'layout-dashboard',
|
|
2891
|
+
active: true,
|
|
2892
|
+
},
|
|
2893
|
+
],
|
|
2894
|
+
},
|
|
2895
|
+
{
|
|
2896
|
+
id: 'people',
|
|
2897
|
+
label: 'People',
|
|
2898
|
+
items: [
|
|
2899
|
+
{ id: 'users', label: 'Users', href: '#', icon: 'users' },
|
|
2900
|
+
{ id: 'groups', label: 'Groups', href: '#', icon: 'layers' },
|
|
2901
|
+
],
|
|
2902
|
+
},
|
|
2903
|
+
]}
|
|
2904
|
+
/>
|
|
2905
|
+
</div>
|
|
2906
|
+
</ComponentCard>
|
|
2907
|
+
|
|
2079
2908
|
{/* Tooltip */}
|
|
2080
2909
|
<ComponentCard
|
|
2081
2910
|
name="Tooltip"
|
|
@@ -2238,6 +3067,44 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
2238
3067
|
/>
|
|
2239
3068
|
</ComponentCard>
|
|
2240
3069
|
|
|
3070
|
+
{/* LegalLinks */}
|
|
3071
|
+
<ComponentCard
|
|
3072
|
+
name="LegalLinks"
|
|
3073
|
+
importLine="import { LegalLinks } from '@sovereignfs/ui';"
|
|
3074
|
+
usage="Privacy Policy / Terms of Service link row for standalone auth pages (login, register, forgot/reset password). Pass renderLink to keep navigation client-side if ever mounted inside an SPA-like shell."
|
|
3075
|
+
>
|
|
3076
|
+
<LegalLinks />
|
|
3077
|
+
</ComponentCard>
|
|
3078
|
+
|
|
3079
|
+
{/* ConsentPrompt */}
|
|
3080
|
+
<ComponentCard
|
|
3081
|
+
name="ConsentPrompt"
|
|
3082
|
+
importLine="import { ConsentPrompt } from '@sovereignfs/ui';"
|
|
3083
|
+
usage="Consent screen shown before one plugin is allowed to read another plugin's data (RFC 0002 data grants) or connect to an external service on the user's behalf. description should come from the provider's own manifest declaration, never caller-supplied copy."
|
|
3084
|
+
>
|
|
3085
|
+
<ConsentPrompt
|
|
3086
|
+
consumerName="Ledger"
|
|
3087
|
+
providerName="Finance Tracker"
|
|
3088
|
+
contract="expenses"
|
|
3089
|
+
description="Monthly expense totals by category, no transaction-level detail."
|
|
3090
|
+
onAllow={() => {}}
|
|
3091
|
+
onDeny={() => {}}
|
|
3092
|
+
/>
|
|
3093
|
+
</ComponentCard>
|
|
3094
|
+
|
|
3095
|
+
{/* Markdown */}
|
|
3096
|
+
<ComponentCard
|
|
3097
|
+
name="Markdown"
|
|
3098
|
+
importLine="import { Markdown } from '@sovereignfs/ui';"
|
|
3099
|
+
usage="Renders a constrained markdown subset (headings, paragraphs, bold/italic/code, links, ordered and unordered lists, fenced code blocks, blockquotes) as Typography-based React elements — no HTML string injection. Built for first-party long-form content and model-generated replies; still not a full CommonMark parser (no tables, images, or nested blocks)."
|
|
3100
|
+
>
|
|
3101
|
+
<Markdown
|
|
3102
|
+
content={
|
|
3103
|
+
'## Heading\n\nA paragraph with **bold** and a [link](/privacy).\n\n- One\n- Two\n\n1. First\n2. Second\n\n```ts\nconst a = 1;\n```'
|
|
3104
|
+
}
|
|
3105
|
+
/>
|
|
3106
|
+
</ComponentCard>
|
|
3107
|
+
|
|
2241
3108
|
{/* Pagination */}
|
|
2242
3109
|
<ComponentCard
|
|
2243
3110
|
name="Pagination"
|
|
@@ -2668,6 +3535,26 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
2668
3535
|
</div>
|
|
2669
3536
|
</ComponentCard>
|
|
2670
3537
|
|
|
3538
|
+
{/* GripIcon */}
|
|
3539
|
+
<ComponentCard
|
|
3540
|
+
name="GripIcon"
|
|
3541
|
+
importLine="import { GripIcon } from '@sovereignfs/ui';"
|
|
3542
|
+
usage="Six-dot drag-handle icon, sized via `size` (default 14). No baked-in pointer-events or color — DragHandleRow uses it internally; a floating, absolutely-positioned handle can use it directly."
|
|
3543
|
+
>
|
|
3544
|
+
<div style={{ color: 'var(--sv-color-text-muted)' }}>
|
|
3545
|
+
<GripIcon />
|
|
3546
|
+
</div>
|
|
3547
|
+
</ComponentCard>
|
|
3548
|
+
|
|
3549
|
+
{/* StepStrip */}
|
|
3550
|
+
<ComponentCard
|
|
3551
|
+
name="StepStrip"
|
|
3552
|
+
importLine="import { StepStrip } from '@sovereignfs/ui';"
|
|
3553
|
+
usage="Horizontal connected-chip strip (a route/itinerary sequence) with an optional trailing add chip. Purely presentational — renderItem owns each chip's content, click handling, and any drag-reorder wiring (attach dnd-kit's useSortable the same way DragHandleRow's handleProps expects it)."
|
|
3554
|
+
>
|
|
3555
|
+
<StepStripDemo />
|
|
3556
|
+
</ComponentCard>
|
|
3557
|
+
|
|
2671
3558
|
{/* FileDropzone */}
|
|
2672
3559
|
<ComponentCard
|
|
2673
3560
|
name="FileDropzone"
|
|
@@ -2676,6 +3563,42 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
2676
3563
|
>
|
|
2677
3564
|
<FileDropzoneDemo />
|
|
2678
3565
|
</ComponentCard>
|
|
3566
|
+
|
|
3567
|
+
{/* ResponsiveSurface */}
|
|
3568
|
+
<ComponentCard
|
|
3569
|
+
name="ResponsiveSurface"
|
|
3570
|
+
importLine="import { ResponsiveSurface } from '@sovereignfs/ui';"
|
|
3571
|
+
usage="Renders an entirely different component tree below a breakpoint, not a CSS squeeze of the same one — only the active side is ever mounted. See also the useResponsiveLayout hook for non-JSX values."
|
|
3572
|
+
>
|
|
3573
|
+
<ResponsiveSurfaceDemo />
|
|
3574
|
+
</ComponentCard>
|
|
3575
|
+
|
|
3576
|
+
{/* SwipableMobileCarousel */}
|
|
3577
|
+
<ComponentCard
|
|
3578
|
+
name="SwipableMobileCarousel"
|
|
3579
|
+
importLine="import { SwipableMobileCarousel, SwipableMobileCarouselSlide, SwipableMobileCarouselSlideHeader, SwipableMobileCarouselSlideBody } from '@sovereignfs/ui';"
|
|
3580
|
+
usage="Compound component for swiping between full-width slides. A Slide's Header/Footer always render; only Body's own loading prop gates its content, so a title can show immediately while the body's own fetch is still in flight. Owns mount-window/reorder mechanics only — never put cross-slide aggregation or a detail overlay inside a Slide."
|
|
3581
|
+
>
|
|
3582
|
+
<SwipableMobileCarouselDemo />
|
|
3583
|
+
</ComponentCard>
|
|
3584
|
+
|
|
3585
|
+
{/* SwipableMobileCarouselDots */}
|
|
3586
|
+
<ComponentCard
|
|
3587
|
+
name="SwipableMobileCarouselDots"
|
|
3588
|
+
importLine="import { SwipableMobileCarouselDots } from '@sovereignfs/ui';"
|
|
3589
|
+
usage="A real, tappable, labeled slide indicator (role=tablist/tab) — standalone and reusable outside SwipableMobileCarousel too, and its default renderIndicator."
|
|
3590
|
+
>
|
|
3591
|
+
<SwipableMobileCarouselDotsDemo />
|
|
3592
|
+
</ComponentCard>
|
|
3593
|
+
|
|
3594
|
+
{/* SwipeStack */}
|
|
3595
|
+
<ComponentCard
|
|
3596
|
+
name="SwipeStack"
|
|
3597
|
+
importLine="import { SwipeStack, SwipeStackCard } from '@sovereignfs/ui';"
|
|
3598
|
+
usage="Triage one card at a time by dragging left/right/up/down, plus an always-visible fallback button per configured direction wired to the identical commit path. Every direction is independently optional and has no baked-in meaning — the caller supplies label/icon and reacts to onSwipe; once triggered a direction removes the card for good, there is no reversible 'go back'."
|
|
3599
|
+
>
|
|
3600
|
+
<SwipeStackDemo />
|
|
3601
|
+
</ComponentCard>
|
|
2679
3602
|
</div>
|
|
2680
3603
|
</section>
|
|
2681
3604
|
|
|
@@ -2789,6 +3712,10 @@ font-weight: var(--sv-font-weight-bold); /* 700 */`}</Code>
|
|
|
2789
3712
|
<li>
|
|
2790
3713
|
Use <code style={{ fontFamily: ffm }}>--sv-shadow-*</code> for elevation
|
|
2791
3714
|
</li>
|
|
3715
|
+
<li>
|
|
3716
|
+
Use <code style={{ fontFamily: ffm }}>--sv-border-width-hairline</code> instead of
|
|
3717
|
+
a literal border width (RFC 0094)
|
|
3718
|
+
</li>
|
|
2792
3719
|
</ul>
|
|
2793
3720
|
</div>
|
|
2794
3721
|
<div
|