@sovereignfs/ui 0.83.1 → 0.89.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/LICENSE +373 -661
- package/NOTICE +8 -0
- package/README.md +4 -6
- package/dist/AppsLauncher.module.css +6 -0
- package/dist/Button.module.css +5 -0
- package/dist/Card.module.css +6 -0
- package/dist/CardTile.module.css +6 -0
- package/dist/CheckableListRow.module.css +8 -0
- package/dist/Checkbox.module.css +8 -0
- package/dist/CodeTextarea.module.css +6 -0
- package/dist/ColorPicker.module.css +6 -0
- package/dist/Combobox.module.css +6 -0
- package/dist/Command.module.css +6 -0
- package/dist/ConfirmDialog.module.css +6 -0
- package/dist/DatePicker.module.css +6 -0
- package/dist/Dialog.module.css +1 -1
- package/dist/DragHandleRow.module.css +6 -0
- package/dist/FileDropzone.module.css +25 -1
- package/dist/Header.module.css +6 -0
- package/dist/IconPicker.module.css +14 -4
- package/dist/Input.module.css +6 -0
- package/dist/LegalLinks.module.css +9 -2
- package/dist/Markdown.module.css +5 -0
- package/dist/Message.module.css +9 -0
- package/dist/MobileAppsDrawer.module.css +9 -5
- package/dist/MobileFooter.module.css +6 -0
- package/dist/NavList.module.css +11 -2
- package/dist/NavTabs.module.css +7 -1
- package/dist/NotificationsPanel.module.css +10 -0
- package/dist/QrCode.module.css +17 -0
- package/dist/QuantityStepper.module.css +4 -2
- package/dist/RadioGroup.module.css +6 -0
- package/dist/SegmentedControl.module.css +6 -0
- package/dist/Select.module.css +6 -0
- package/dist/Sheet.module.css +16 -1
- package/dist/SplitPane.module.css +1 -1
- package/dist/StepStrip.module.css +5 -3
- package/dist/SuggestionInput.module.css +12 -1
- package/dist/SwipableMobileCarouselDots.module.css +6 -0
- package/dist/SystemBanner.module.css +6 -0
- package/dist/Tabs.module.css +6 -0
- package/dist/TagInput.module.css +6 -0
- package/dist/Textarea.module.css +6 -0
- package/dist/Toast.module.css +5 -0
- package/dist/Toggle.module.css +7 -0
- package/dist/Tooltip.module.css +6 -0
- package/dist/UserMenu.module.css +5 -0
- package/dist/fonts/OFL.txt +93 -0
- package/dist/fonts/hanken-grotesk-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/hanken-grotesk-vietnamese-wght-normal.woff2 +0 -0
- package/dist/index.d.ts +121 -43
- package/dist/index.js +1410 -1152
- package/dist/tokens/fonts.css +53 -0
- package/dist/tokens/primitives.css +12 -12
- package/dist/tokens.css +2 -1
- package/package.json +24 -13
- package/src/__tests__/motion.test.tsx +0 -105
- package/src/__tests__/package-json.test.ts +0 -8
- package/src/components/Accordion/Accordion.module.css +0 -3
- package/src/components/Accordion/Accordion.stories.tsx +0 -110
- package/src/components/Accordion/Accordion.tsx +0 -53
- package/src/components/Accordion/__tests__/Accordion.test.tsx +0 -61
- package/src/components/Alert/Alert.module.css +0 -62
- package/src/components/Alert/Alert.stories.tsx +0 -96
- package/src/components/Alert/Alert.tsx +0 -58
- package/src/components/Alert/__tests__/Alert.test.tsx +0 -75
- package/src/components/AppsLauncher/AppsLauncher.module.css +0 -96
- package/src/components/AppsLauncher/AppsLauncher.stories.tsx +0 -58
- package/src/components/AppsLauncher/AppsLauncher.tsx +0 -117
- package/src/components/AppsLauncher/__tests__/AppsLauncher.test.tsx +0 -52
- package/src/components/AspectRatio/AspectRatio.module.css +0 -15
- package/src/components/AspectRatio/AspectRatio.stories.tsx +0 -78
- package/src/components/AspectRatio/AspectRatio.tsx +0 -21
- package/src/components/AspectRatio/__tests__/AspectRatio.test.tsx +0 -27
- package/src/components/Avatar/Avatar.module.css +0 -38
- package/src/components/Avatar/Avatar.tsx +0 -42
- package/src/components/Badge/Badge.module.css +0 -177
- package/src/components/Badge/Badge.stories.tsx +0 -238
- package/src/components/Badge/Badge.tsx +0 -84
- package/src/components/Badge/__tests__/Badge.test.tsx +0 -90
- package/src/components/BalanceChip/BalanceChip.module.css +0 -32
- package/src/components/BalanceChip/BalanceChip.stories.tsx +0 -45
- package/src/components/BalanceChip/BalanceChip.tsx +0 -33
- package/src/components/Breadcrumb/Breadcrumb.module.css +0 -49
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -47
- package/src/components/Breadcrumb/Breadcrumb.tsx +0 -57
- package/src/components/Breadcrumb/__tests__/Breadcrumb.test.tsx +0 -52
- package/src/components/Button/Button.module.css +0 -169
- package/src/components/Button/Button.stories.tsx +0 -83
- package/src/components/Button/Button.tsx +0 -52
- package/src/components/Button/__tests__/Button.test.tsx +0 -66
- package/src/components/ButtonGroup/ButtonGroup.module.css +0 -29
- package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -57
- package/src/components/ButtonGroup/ButtonGroup.tsx +0 -27
- package/src/components/ButtonGroup/__tests__/ButtonGroup.test.tsx +0 -29
- package/src/components/Calendar/Calendar.module.css +0 -126
- package/src/components/Calendar/Calendar.tsx +0 -213
- package/src/components/Calendar/__tests__/Calendar.test.tsx +0 -98
- package/src/components/Calendar/dateUtils.ts +0 -97
- package/src/components/Card/Card.module.css +0 -42
- package/src/components/Card/Card.tsx +0 -34
- package/src/components/CardTile/CardTile.module.css +0 -181
- package/src/components/CardTile/CardTile.stories.tsx +0 -86
- package/src/components/CardTile/CardTile.tsx +0 -128
- package/src/components/CardTile/__tests__/CardTile.test.tsx +0 -56
- package/src/components/CheckableListRow/CheckableListRow.module.css +0 -95
- package/src/components/CheckableListRow/CheckableListRow.stories.tsx +0 -99
- package/src/components/CheckableListRow/CheckableListRow.tsx +0 -89
- package/src/components/Checkbox/Checkbox.module.css +0 -111
- package/src/components/Checkbox/Checkbox.tsx +0 -78
- package/src/components/CodeTextarea/CodeTextarea.module.css +0 -53
- package/src/components/CodeTextarea/CodeTextarea.stories.tsx +0 -77
- package/src/components/CodeTextarea/CodeTextarea.tsx +0 -36
- package/src/components/Collapsible/Collapsible.module.css +0 -70
- package/src/components/Collapsible/Collapsible.stories.tsx +0 -62
- package/src/components/Collapsible/Collapsible.tsx +0 -66
- package/src/components/Collapsible/__tests__/Collapsible.test.tsx +0 -71
- package/src/components/ColorPicker/ColorPicker.module.css +0 -132
- package/src/components/ColorPicker/ColorPicker.stories.tsx +0 -80
- package/src/components/ColorPicker/ColorPicker.tsx +0 -157
- package/src/components/ColorPicker/__tests__/ColorPicker.test.tsx +0 -117
- package/src/components/Combobox/Combobox.module.css +0 -122
- package/src/components/Combobox/Combobox.stories.tsx +0 -79
- package/src/components/Combobox/Combobox.tsx +0 -186
- package/src/components/Combobox/__tests__/Combobox.test.tsx +0 -158
- package/src/components/Command/Command.module.css +0 -80
- package/src/components/Command/Command.stories.tsx +0 -104
- package/src/components/Command/Command.tsx +0 -168
- package/src/components/Command/__tests__/Command.test.tsx +0 -162
- package/src/components/ConfirmDialog/ConfirmDialog.module.css +0 -113
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +0 -150
- package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +0 -214
- package/src/components/ConsentPrompt/ConsentPrompt.module.css +0 -21
- package/src/components/ConsentPrompt/ConsentPrompt.stories.tsx +0 -31
- package/src/components/ConsentPrompt/ConsentPrompt.tsx +0 -66
- package/src/components/ContextMenu/ContextMenu.stories.tsx +0 -81
- package/src/components/ContextMenu/ContextMenu.tsx +0 -100
- package/src/components/ContextMenu/__tests__/ContextMenu.test.tsx +0 -87
- package/src/components/CurrencyInput/CurrencyInput.stories.tsx +0 -50
- package/src/components/CurrencyInput/CurrencyInput.tsx +0 -60
- package/src/components/DataTable/DataTable.module.css +0 -28
- package/src/components/DataTable/DataTable.stories.tsx +0 -74
- package/src/components/DataTable/DataTable.tsx +0 -154
- package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -123
- package/src/components/DatePicker/DatePicker.module.css +0 -61
- package/src/components/DatePicker/DatePicker.tsx +0 -103
- package/src/components/DatePicker/__tests__/DatePicker.test.tsx +0 -89
- package/src/components/DeviceOnlyGate/DeviceOnlyGate.tsx +0 -58
- package/src/components/DeviceOnlyGate/__tests__/DeviceOnlyGate.test.tsx +0 -45
- package/src/components/DeviceStorageKeyGate/DeviceStorageKeyGate.tsx +0 -100
- package/src/components/DeviceStorageKeyGate/__tests__/DeviceStorageKeyGate.test.tsx +0 -119
- package/src/components/Dialog/Dialog.module.css +0 -335
- package/src/components/Dialog/Dialog.stories.tsx +0 -324
- package/src/components/Dialog/Dialog.tsx +0 -254
- package/src/components/Dialog/__tests__/Dialog.test.tsx +0 -318
- package/src/components/DragHandleRow/DragHandleRow.module.css +0 -57
- package/src/components/DragHandleRow/DragHandleRow.tsx +0 -42
- package/src/components/Drawer/Drawer.module.css +0 -121
- package/src/components/Drawer/Drawer.stories.tsx +0 -132
- package/src/components/Drawer/Drawer.tsx +0 -175
- package/src/components/Drawer/__tests__/Drawer.test.tsx +0 -226
- package/src/components/EmptyState/EmptyState.module.css +0 -27
- package/src/components/EmptyState/EmptyState.tsx +0 -27
- package/src/components/FileDropzone/FileDropzone.module.css +0 -63
- package/src/components/FileDropzone/FileDropzone.tsx +0 -109
- package/src/components/FileDropzone/__tests__/FileDropzone.test.tsx +0 -67
- package/src/components/FormField/FormField.module.css +0 -33
- package/src/components/FormField/FormField.tsx +0 -78
- package/src/components/FormField/__tests__/FormField.test.tsx +0 -83
- package/src/components/GripIcon/GripIcon.tsx +0 -27
- package/src/components/Header/Header.module.css +0 -62
- package/src/components/Header/Header.stories.tsx +0 -452
- package/src/components/Header/Header.tsx +0 -102
- package/src/components/Header/__tests__/Header.test.tsx +0 -104
- package/src/components/HeaderFooterLayout/HeaderFooterLayout.module.css +0 -21
- package/src/components/HeaderFooterLayout/HeaderFooterLayout.stories.tsx +0 -111
- package/src/components/HeaderFooterLayout/HeaderFooterLayout.tsx +0 -54
- package/src/components/HeaderFooterLayout/__tests__/HeaderFooterLayout.test.tsx +0 -58
- package/src/components/HoverCard/HoverCard.module.css +0 -3
- package/src/components/HoverCard/HoverCard.stories.tsx +0 -66
- package/src/components/HoverCard/HoverCard.tsx +0 -111
- package/src/components/HoverCard/__tests__/HoverCard.test.tsx +0 -99
- package/src/components/Icon/Icon.module.css +0 -27
- package/src/components/Icon/Icon.stories.tsx +0 -95
- package/src/components/Icon/Icon.tsx +0 -43
- package/src/components/Icon/__tests__/Icon.test.tsx +0 -40
- package/src/components/Icon/icons/activity.tsx +0 -20
- package/src/components/Icon/icons/alert-triangle.tsx +0 -22
- package/src/components/Icon/icons/apple.tsx +0 -21
- package/src/components/Icon/icons/arrow-left-right.tsx +0 -23
- package/src/components/Icon/icons/banana.tsx +0 -21
- package/src/components/Icon/icons/beef.tsx +0 -22
- package/src/components/Icon/icons/beer.tsx +0 -24
- package/src/components/Icon/icons/bell.tsx +0 -21
- package/src/components/Icon/icons/bold.tsx +0 -20
- package/src/components/Icon/icons/calendar.tsx +0 -23
- package/src/components/Icon/icons/candy.tsx +0 -24
- package/src/components/Icon/icons/carrot.tsx +0 -22
- package/src/components/Icon/icons/check.tsx +0 -20
- package/src/components/Icon/icons/chevron-down.tsx +0 -20
- package/src/components/Icon/icons/chevron-left.tsx +0 -20
- package/src/components/Icon/icons/chevron-right.tsx +0 -20
- package/src/components/Icon/icons/chevron-up.tsx +0 -20
- package/src/components/Icon/icons/circle-check.tsx +0 -21
- package/src/components/Icon/icons/circle-chevron-left.tsx +0 -21
- package/src/components/Icon/icons/circle-x.tsx +0 -22
- package/src/components/Icon/icons/code.tsx +0 -21
- package/src/components/Icon/icons/coffee.tsx +0 -23
- package/src/components/Icon/icons/cookie.tsx +0 -25
- package/src/components/Icon/icons/copy.tsx +0 -21
- package/src/components/Icon/icons/credit-card.tsx +0 -21
- package/src/components/Icon/icons/croissant.tsx +0 -24
- package/src/components/Icon/icons/cup-soda.tsx +0 -23
- package/src/components/Icon/icons/database.tsx +0 -22
- package/src/components/Icon/icons/download.tsx +0 -22
- package/src/components/Icon/icons/drumstick.tsx +0 -21
- package/src/components/Icon/icons/egg.tsx +0 -20
- package/src/components/Icon/icons/ellipsis-vertical.tsx +0 -22
- package/src/components/Icon/icons/external-link.tsx +0 -22
- package/src/components/Icon/icons/eye-off.tsx +0 -23
- package/src/components/Icon/icons/eye.tsx +0 -21
- package/src/components/Icon/icons/file-text.tsx +0 -24
- package/src/components/Icon/icons/file.tsx +0 -21
- package/src/components/Icon/icons/fish.tsx +0 -25
- package/src/components/Icon/icons/folder-closed.tsx +0 -21
- package/src/components/Icon/icons/folder-open.tsx +0 -20
- package/src/components/Icon/icons/folder.tsx +0 -20
- package/src/components/Icon/icons/folders.tsx +0 -21
- package/src/components/Icon/icons/grid-2x2.tsx +0 -22
- package/src/components/Icon/icons/hat-glasses.tsx +0 -24
- package/src/components/Icon/icons/history.tsx +0 -22
- package/src/components/Icon/icons/house.tsx +0 -21
- package/src/components/Icon/icons/inbox.tsx +0 -21
- package/src/components/Icon/icons/index.ts +0 -394
- package/src/components/Icon/icons/info.tsx +0 -22
- package/src/components/Icon/icons/italic.tsx +0 -22
- package/src/components/Icon/icons/layers.tsx +0 -22
- package/src/components/Icon/icons/layout-dashboard.tsx +0 -23
- package/src/components/Icon/icons/layout-grid.tsx +0 -23
- package/src/components/Icon/icons/link.tsx +0 -21
- package/src/components/Icon/icons/list-ordered.tsx +0 -25
- package/src/components/Icon/icons/list.tsx +0 -25
- package/src/components/Icon/icons/lock.tsx +0 -21
- package/src/components/Icon/icons/log-out.tsx +0 -22
- package/src/components/Icon/icons/luggage.tsx +0 -24
- package/src/components/Icon/icons/mail.tsx +0 -21
- package/src/components/Icon/icons/map-pin.tsx +0 -21
- package/src/components/Icon/icons/menu.tsx +0 -22
- package/src/components/Icon/icons/milk.tsx +0 -22
- package/src/components/Icon/icons/minus.tsx +0 -20
- package/src/components/Icon/icons/package.tsx +0 -23
- package/src/components/Icon/icons/paint-bucket.tsx +0 -23
- package/src/components/Icon/icons/panel-left.tsx +0 -21
- package/src/components/Icon/icons/pencil.tsx +0 -21
- package/src/components/Icon/icons/pin.tsx +0 -21
- package/src/components/Icon/icons/pizza.tsx +0 -24
- package/src/components/Icon/icons/plus.tsx +0 -21
- package/src/components/Icon/icons/rectangle-ellipsis.tsx +0 -23
- package/src/components/Icon/icons/refresh-cw.tsx +0 -23
- package/src/components/Icon/icons/rotate-ccw.tsx +0 -21
- package/src/components/Icon/icons/rotate-cw.tsx +0 -21
- package/src/components/Icon/icons/route.tsx +0 -22
- package/src/components/Icon/icons/salad.tsx +0 -24
- package/src/components/Icon/icons/search.tsx +0 -21
- package/src/components/Icon/icons/send.tsx +0 -21
- package/src/components/Icon/icons/settings.tsx +0 -21
- package/src/components/Icon/icons/share-2.tsx +0 -24
- package/src/components/Icon/icons/sheet.tsx +0 -24
- package/src/components/Icon/icons/shield.tsx +0 -20
- package/src/components/Icon/icons/shopping-basket.tsx +0 -26
- package/src/components/Icon/icons/sliders-horizontal.tsx +0 -28
- package/src/components/Icon/icons/smartphone.tsx +0 -21
- package/src/components/Icon/icons/snowflake.tsx +0 -31
- package/src/components/Icon/icons/spray-can.tsx +0 -29
- package/src/components/Icon/icons/square-kanban.tsx +0 -23
- package/src/components/Icon/icons/table.tsx +0 -23
- package/src/components/Icon/icons/trash-2.tsx +0 -24
- package/src/components/Icon/icons/upload.tsx +0 -22
- package/src/components/Icon/icons/user-round-plus.tsx +0 -23
- package/src/components/Icon/icons/user.tsx +0 -21
- package/src/components/Icon/icons/users.tsx +0 -23
- package/src/components/Icon/icons/wine.tsx +0 -23
- package/src/components/Icon/icons/x.tsx +0 -21
- package/src/components/IconPicker/IconPicker.module.css +0 -63
- package/src/components/IconPicker/IconPicker.stories.tsx +0 -84
- package/src/components/IconPicker/IconPicker.tsx +0 -90
- package/src/components/Input/Input.module.css +0 -52
- package/src/components/Input/Input.stories.tsx +0 -86
- package/src/components/Input/Input.tsx +0 -20
- package/src/components/Input/__tests__/Input.test.tsx +0 -22
- package/src/components/Item/Item.module.css +0 -70
- package/src/components/Item/Item.stories.tsx +0 -62
- package/src/components/Item/Item.tsx +0 -54
- package/src/components/Item/__tests__/Item.test.tsx +0 -39
- package/src/components/Kbd/Kbd.module.css +0 -14
- package/src/components/Kbd/Kbd.stories.tsx +0 -32
- package/src/components/Kbd/Kbd.tsx +0 -12
- package/src/components/Kbd/__tests__/Kbd.test.tsx +0 -14
- package/src/components/Label/Label.module.css +0 -11
- package/src/components/Label/Label.stories.tsx +0 -40
- package/src/components/Label/Label.tsx +0 -24
- package/src/components/Label/__tests__/Label.test.tsx +0 -32
- package/src/components/LegalLinks/LegalLinks.module.css +0 -24
- package/src/components/LegalLinks/LegalLinks.stories.tsx +0 -22
- package/src/components/LegalLinks/LegalLinks.tsx +0 -40
- package/src/components/Markdown/Markdown.module.css +0 -73
- package/src/components/Markdown/Markdown.stories.tsx +0 -40
- package/src/components/Markdown/Markdown.tsx +0 -305
- package/src/components/Markdown/__tests__/Markdown.test.tsx +0 -144
- package/src/components/Marker/Marker.module.css +0 -33
- package/src/components/Marker/Marker.stories.tsx +0 -39
- package/src/components/Marker/Marker.tsx +0 -34
- package/src/components/Marker/__tests__/Marker.test.tsx +0 -23
- package/src/components/MemberMultiSelect/MemberMultiSelect.module.css +0 -27
- package/src/components/MemberMultiSelect/MemberMultiSelect.stories.tsx +0 -74
- package/src/components/MemberMultiSelect/MemberMultiSelect.tsx +0 -67
- package/src/components/Menu/Menu.module.css +0 -90
- package/src/components/Menu/Menu.tsx +0 -209
- package/src/components/Menu/__tests__/Menu.test.tsx +0 -227
- package/src/components/Menubar/Menubar.stories.tsx +0 -52
- package/src/components/Menubar/Menubar.tsx +0 -42
- package/src/components/Menubar/__tests__/Menubar.test.tsx +0 -45
- package/src/components/Message/Message.module.css +0 -99
- package/src/components/Message/Message.stories.tsx +0 -79
- package/src/components/Message/Message.tsx +0 -41
- package/src/components/Message/__tests__/Message.test.tsx +0 -46
- package/src/components/MessageScroller/MessageScroller.module.css +0 -65
- package/src/components/MessageScroller/MessageScroller.stories.tsx +0 -84
- package/src/components/MessageScroller/MessageScroller.tsx +0 -84
- package/src/components/MessageScroller/__tests__/MessageScroller.test.tsx +0 -105
- package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +0 -82
- package/src/components/MobileAppsDrawer/MobileAppsDrawer.tsx +0 -78
- package/src/components/MobileAppsDrawer/__tests__/MobileAppsDrawer.test.tsx +0 -80
- package/src/components/MobileFooter/MobileFooter.module.css +0 -73
- package/src/components/MobileFooter/MobileFooter.stories.tsx +0 -47
- package/src/components/MobileFooter/MobileFooter.tsx +0 -122
- package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +0 -129
- package/src/components/MobileHeader/MobileHeader.module.css +0 -76
- package/src/components/MobileHeader/MobileHeader.stories.tsx +0 -57
- package/src/components/MobileHeader/MobileHeader.tsx +0 -90
- package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +0 -113
- package/src/components/NavList/NavList.module.css +0 -130
- package/src/components/NavList/NavList.tsx +0 -136
- package/src/components/NavList/__tests__/NavList.test.tsx +0 -109
- package/src/components/NavTabs/NavTabs.module.css +0 -50
- package/src/components/NavTabs/NavTabs.tsx +0 -61
- package/src/components/NavigationMenu/NavigationMenu.module.css +0 -53
- package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -58
- package/src/components/NavigationMenu/NavigationMenu.tsx +0 -125
- package/src/components/NavigationMenu/__tests__/NavigationMenu.test.tsx +0 -93
- package/src/components/NotificationsPanel/NotificationsPanel.module.css +0 -258
- package/src/components/NotificationsPanel/NotificationsPanel.stories.tsx +0 -61
- package/src/components/NotificationsPanel/NotificationsPanel.tsx +0 -187
- package/src/components/NotificationsPanel/__tests__/NotificationsPanel.test.tsx +0 -78
- package/src/components/OfflineGate/OfflineGate.tsx +0 -44
- package/src/components/OfflineGate/__tests__/OfflineGate.test.tsx +0 -66
- package/src/components/OverlayHeader/OverlayHeader.module.css +0 -98
- package/src/components/OverlayHeader/OverlayHeader.tsx +0 -77
- package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +0 -69
- package/src/components/PageContainer/PageContainer.module.css +0 -82
- package/src/components/PageContainer/PageContainer.tsx +0 -64
- package/src/components/PageContainer/__tests__/PageContainer.test.tsx +0 -70
- package/src/components/PageHeader/PageHeader.module.css +0 -86
- package/src/components/PageHeader/PageHeader.tsx +0 -176
- package/src/components/PageHeader/__tests__/PageHeader.test.tsx +0 -103
- package/src/components/PageLayout/PageLayout.module.css +0 -51
- package/src/components/PageLayout/PageLayout.stories.tsx +0 -73
- package/src/components/PageLayout/PageLayout.tsx +0 -51
- package/src/components/PageLayout/__tests__/PageLayout.test.tsx +0 -34
- package/src/components/Pagination/Pagination.module.css +0 -98
- package/src/components/Pagination/Pagination.stories.tsx +0 -49
- package/src/components/Pagination/Pagination.tsx +0 -87
- package/src/components/Pagination/__tests__/Pagination.test.tsx +0 -56
- package/src/components/Popover/Popover.module.css +0 -74
- package/src/components/Popover/Popover.stories.tsx +0 -357
- package/src/components/Popover/Popover.tsx +0 -290
- package/src/components/Popover/__tests__/Popover.test.tsx +0 -263
- package/src/components/Progress/Progress.module.css +0 -20
- package/src/components/Progress/Progress.stories.tsx +0 -40
- package/src/components/Progress/Progress.tsx +0 -35
- package/src/components/Progress/__tests__/Progress.test.tsx +0 -31
- package/src/components/QuantityStepper/QuantityStepper.module.css +0 -67
- package/src/components/QuantityStepper/QuantityStepper.stories.tsx +0 -79
- package/src/components/QuantityStepper/QuantityStepper.tsx +0 -107
- package/src/components/RadioGroup/RadioGroup.module.css +0 -88
- package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -69
- package/src/components/RadioGroup/RadioGroup.tsx +0 -99
- package/src/components/RadioGroup/__tests__/RadioGroup.test.tsx +0 -59
- package/src/components/Resizable/Resizable.module.css +0 -70
- package/src/components/Resizable/Resizable.stories.tsx +0 -82
- package/src/components/Resizable/Resizable.tsx +0 -313
- package/src/components/Resizable/__tests__/Resizable.test.tsx +0 -128
- package/src/components/ResponsiveSurface/ResponsiveSurface.tsx +0 -24
- package/src/components/ResponsiveSurface/__tests__/ResponsiveSurface.test.tsx +0 -73
- package/src/components/RootLayout/RootLayout.module.css +0 -12
- package/src/components/RootLayout/RootLayout.stories.tsx +0 -125
- package/src/components/RootLayout/RootLayout.tsx +0 -185
- package/src/components/RootLayout/__tests__/RootLayout.test.tsx +0 -161
- package/src/components/ScrollArea/ScrollArea.module.css +0 -20
- package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -57
- package/src/components/ScrollArea/ScrollArea.tsx +0 -27
- package/src/components/ScrollArea/__tests__/ScrollArea.test.tsx +0 -39
- package/src/components/SegmentedControl/SegmentedControl.module.css +0 -55
- package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -118
- package/src/components/SegmentedControl/SegmentedControl.tsx +0 -56
- package/src/components/SegmentedControl/__tests__/SegmentedControl.test.tsx +0 -63
- package/src/components/Select/Select.module.css +0 -82
- package/src/components/Select/Select.stories.tsx +0 -115
- package/src/components/Select/Select.tsx +0 -48
- package/src/components/Select/__tests__/Select.test.tsx +0 -59
- package/src/components/Sheet/Sheet.module.css +0 -58
- package/src/components/Sheet/Sheet.tsx +0 -109
- package/src/components/Sheet/__tests__/Sheet.test.tsx +0 -99
- package/src/components/Slider/Slider.module.css +0 -95
- package/src/components/Slider/Slider.stories.tsx +0 -64
- package/src/components/Slider/Slider.tsx +0 -77
- package/src/components/Slider/__tests__/Slider.test.tsx +0 -45
- package/src/components/Spinner/Spinner.module.css +0 -39
- package/src/components/Spinner/Spinner.tsx +0 -23
- package/src/components/SplitMethodSelector/SplitMethodSelector.stories.tsx +0 -33
- package/src/components/SplitMethodSelector/SplitMethodSelector.tsx +0 -43
- package/src/components/SplitPane/SplitPane.module.css +0 -85
- package/src/components/SplitPane/SplitPane.stories.tsx +0 -160
- package/src/components/SplitPane/SplitPane.tsx +0 -149
- package/src/components/SplitPane/__tests__/SplitPane.test.tsx +0 -51
- package/src/components/StatusBadge/StatusBadge.module.css +0 -59
- package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -74
- package/src/components/StatusBadge/StatusBadge.tsx +0 -65
- package/src/components/StepStrip/StepStrip.module.css +0 -53
- package/src/components/StepStrip/StepStrip.tsx +0 -74
- package/src/components/SuggestionInput/SuggestionInput.module.css +0 -103
- package/src/components/SuggestionInput/SuggestionInput.stories.tsx +0 -144
- package/src/components/SuggestionInput/SuggestionInput.tsx +0 -207
- package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +0 -64
- package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +0 -243
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlide.tsx +0 -35
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody.tsx +0 -42
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideFooter.tsx +0 -18
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader.tsx +0 -21
- package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideParts.module.css +0 -29
- package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +0 -214
- package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarouselDevGuard.test.tsx +0 -61
- package/src/components/SwipableMobileCarousel/context.ts +0 -13
- package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +0 -64
- package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +0 -73
- package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +0 -63
- package/src/components/SwipeStack/SwipeStack.module.css +0 -101
- package/src/components/SwipeStack/SwipeStack.tsx +0 -199
- package/src/components/SwipeStack/SwipeStackCard.tsx +0 -22
- package/src/components/SwipeStack/__tests__/SwipeStack.test.tsx +0 -169
- package/src/components/SystemBanner/SystemBanner.module.css +0 -79
- package/src/components/SystemBanner/SystemBanner.stories.tsx +0 -86
- package/src/components/SystemBanner/SystemBanner.tsx +0 -50
- package/src/components/SystemBanner/__tests__/SystemBanner.test.tsx +0 -50
- package/src/components/Table/Table.module.css +0 -45
- package/src/components/Table/Table.stories.tsx +0 -125
- package/src/components/Table/Table.tsx +0 -51
- package/src/components/Table/__tests__/Table.test.tsx +0 -50
- package/src/components/Tabs/Tabs.module.css +0 -56
- package/src/components/Tabs/Tabs.stories.tsx +0 -100
- package/src/components/Tabs/Tabs.tsx +0 -46
- package/src/components/Tabs/__tests__/Tabs.test.tsx +0 -45
- package/src/components/TagInput/TagInput.module.css +0 -141
- package/src/components/TagInput/TagInput.stories.tsx +0 -109
- package/src/components/TagInput/TagInput.tsx +0 -174
- package/src/components/TagInput/__tests__/TagInput.test.tsx +0 -69
- package/src/components/Textarea/Textarea.module.css +0 -47
- package/src/components/Textarea/Textarea.tsx +0 -38
- package/src/components/Textarea/__tests__/Textarea.test.tsx +0 -51
- package/src/components/ThreeColumnLayout/ThreeColumnLayout.module.css +0 -35
- package/src/components/ThreeColumnLayout/ThreeColumnLayout.stories.tsx +0 -152
- package/src/components/ThreeColumnLayout/ThreeColumnLayout.tsx +0 -87
- package/src/components/ThreeColumnLayout/__tests__/ThreeColumnLayout.test.tsx +0 -78
- package/src/components/Toast/Toast.module.css +0 -191
- package/src/components/Toast/Toast.stories.tsx +0 -191
- package/src/components/Toast/Toast.tsx +0 -139
- package/src/components/Toggle/Toggle.module.css +0 -57
- package/src/components/Toggle/Toggle.stories.tsx +0 -95
- package/src/components/Toggle/Toggle.tsx +0 -39
- package/src/components/Toggle/__tests__/Toggle.test.tsx +0 -47
- package/src/components/Tooltip/Tooltip.module.css +0 -56
- package/src/components/Tooltip/Tooltip.tsx +0 -30
- package/src/components/Typography/Typography.module.css +0 -47
- package/src/components/Typography/Typography.stories.tsx +0 -62
- package/src/components/Typography/Typography.tsx +0 -30
- package/src/components/Typography/__tests__/Typography.test.tsx +0 -34
- package/src/components/UserMenu/UserMenu.module.css +0 -90
- package/src/components/UserMenu/UserMenu.stories.tsx +0 -49
- package/src/components/UserMenu/UserMenu.tsx +0 -132
- package/src/components/UserMenu/__tests__/UserMenu.test.tsx +0 -77
- package/src/css-modules.d.ts +0 -4
- package/src/hooks/__tests__/useCarouselRouteSync.test.tsx +0 -126
- package/src/hooks/__tests__/useDoubleTap.test.tsx +0 -117
- package/src/hooks/__tests__/useIsMobile.test.tsx +0 -80
- package/src/hooks/__tests__/useIsOffline.test.tsx +0 -53
- package/src/hooks/__tests__/useLongPress.test.tsx +0 -158
- package/src/hooks/__tests__/useOfflineTileState.test.tsx +0 -69
- package/src/hooks/__tests__/usePublishShellChromeHeight.test.tsx +0 -118
- package/src/hooks/__tests__/useReorderSensors.test.ts +0 -26
- package/src/hooks/__tests__/useResponsiveLayout.test.tsx +0 -87
- package/src/hooks/__tests__/useSnapCarousel.test.tsx +0 -175
- package/src/hooks/__tests__/useSwipeReveal.test.tsx +0 -110
- package/src/hooks/__tests__/useSwipeStack.test.tsx +0 -155
- package/src/hooks/index.ts +0 -33
- package/src/hooks/useCarouselRouteSync.ts +0 -92
- package/src/hooks/useCommitOnEnterOrBlur.ts +0 -39
- package/src/hooks/useDoubleTap.ts +0 -91
- package/src/hooks/useIsMobile.ts +0 -33
- package/src/hooks/useIsOffline.ts +0 -41
- package/src/hooks/useLongPress.ts +0 -185
- package/src/hooks/useOfflineTileState.ts +0 -45
- package/src/hooks/usePublishShellChromeHeight.ts +0 -96
- package/src/hooks/useReorderSensors.ts +0 -88
- package/src/hooks/useResponsiveLayout.ts +0 -36
- package/src/hooks/useSnapCarousel.ts +0 -284
- package/src/hooks/useSwipeReveal.ts +0 -107
- package/src/hooks/useSwipeStack.ts +0 -235
- package/src/index.ts +0 -311
- package/src/motion.ts +0 -78
- package/src/overlay-shell.ts +0 -159
- package/src/scroll-lock.ts +0 -22
- package/src/stories/Avatar.stories.tsx +0 -44
- package/src/stories/Card.stories.tsx +0 -35
- package/src/stories/Checkbox.stories.tsx +0 -45
- package/src/stories/DesignSystemOverview.stories.tsx +0 -3793
- package/src/stories/DeviceOnlyGate.stories.tsx +0 -35
- package/src/stories/DeviceStorageKeyGate.stories.tsx +0 -57
- package/src/stories/DragHandleRow.stories.tsx +0 -41
- package/src/stories/EmptyState.stories.tsx +0 -33
- package/src/stories/FileDropzone.stories.tsx +0 -69
- package/src/stories/FormField.stories.tsx +0 -47
- package/src/stories/GripIcon.stories.tsx +0 -29
- package/src/stories/InteractionHooks.stories.tsx +0 -925
- package/src/stories/LayoutSystem.stories.tsx +0 -639
- package/src/stories/MenuEntries.stories.tsx +0 -86
- package/src/stories/MobilePatterns.stories.tsx +0 -1536
- package/src/stories/NavList.stories.tsx +0 -147
- package/src/stories/NavTabs.stories.tsx +0 -53
- package/src/stories/OfflineGate.stories.tsx +0 -42
- package/src/stories/PageContainer.stories.tsx +0 -82
- package/src/stories/PageHeader.stories.tsx +0 -95
- package/src/stories/ResponsiveSurface.stories.tsx +0 -47
- package/src/stories/Spinner.stories.tsx +0 -25
- package/src/stories/StepStrip.stories.tsx +0 -76
- package/src/stories/SwipableMobileCarousel.stories.tsx +0 -362
- package/src/stories/SwipeStack.stories.tsx +0 -200
- package/src/stories/Textarea.stories.tsx +0 -63
- package/src/stories/TokenGallery.stories.tsx +0 -652
- package/src/stories/Tooltip.stories.tsx +0 -59
- package/src/tokens/primitives.css +0 -168
- package/src/tokens/semantic.css +0 -162
- package/src/tokens/theme-presets.css +0 -33
- package/src/tokens/theme-presets.ts +0 -72
- package/src/tokens.css +0 -5
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
.wrap {
|
|
2
|
-
display: flex;
|
|
3
|
-
flex-direction: column;
|
|
4
|
-
gap: var(--sv-space-3);
|
|
5
|
-
height: 100%;
|
|
6
|
-
width: 100%;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.stack {
|
|
10
|
-
position: relative;
|
|
11
|
-
flex: 1 1 auto;
|
|
12
|
-
min-height: 0;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
.peek {
|
|
16
|
-
position: absolute;
|
|
17
|
-
inset: 0;
|
|
18
|
-
transform: scale(0.94) translateY(var(--sv-space-3));
|
|
19
|
-
opacity: 0.6;
|
|
20
|
-
pointer-events: none;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.cardSlot {
|
|
24
|
-
position: absolute;
|
|
25
|
-
inset: 0;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/* Styled directly rather than wrapping the Card component: Card doesn't
|
|
29
|
-
forward a ref, and this element must be the exact node useSwipeStack
|
|
30
|
-
translates/rotates as one unit — a Card wrapping an inner dragged div
|
|
31
|
-
would leave its own border/shadow visually static while only the inner
|
|
32
|
-
div moved. */
|
|
33
|
-
.card {
|
|
34
|
-
position: relative;
|
|
35
|
-
height: 100%;
|
|
36
|
-
width: 100%;
|
|
37
|
-
overflow: hidden;
|
|
38
|
-
background: var(--sv-color-surface-raised);
|
|
39
|
-
border: var(--sv-border-width-hairline) solid var(--sv-color-border);
|
|
40
|
-
border-radius: var(--sv-radius-lg);
|
|
41
|
-
box-shadow: var(--sv-shadow-card);
|
|
42
|
-
touch-action: none; /* always overridden inline with useSwipeStack's computed value */
|
|
43
|
-
user-select: none;
|
|
44
|
-
cursor: grab;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.card:active {
|
|
48
|
-
cursor: grabbing;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.stamp {
|
|
52
|
-
position: absolute;
|
|
53
|
-
z-index: 1;
|
|
54
|
-
display: flex;
|
|
55
|
-
align-items: center;
|
|
56
|
-
gap: var(--sv-space-1);
|
|
57
|
-
padding: var(--sv-space-1) var(--sv-space-3);
|
|
58
|
-
border: 2px solid var(--sv-color-text-primary);
|
|
59
|
-
border-radius: var(--sv-radius-md);
|
|
60
|
-
background: var(--sv-color-surface-raised);
|
|
61
|
-
color: var(--sv-color-text-primary);
|
|
62
|
-
font-family: var(--sv-font-family);
|
|
63
|
-
font-size: var(--sv-font-size-sm);
|
|
64
|
-
font-weight: var(--sv-font-weight-semibold);
|
|
65
|
-
pointer-events: none;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.stampUp {
|
|
69
|
-
top: var(--sv-space-4);
|
|
70
|
-
left: 50%;
|
|
71
|
-
transform: translateX(-50%);
|
|
72
|
-
opacity: var(--sv-stack-progress-up, 0);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.stampDown {
|
|
76
|
-
bottom: var(--sv-space-4);
|
|
77
|
-
left: 50%;
|
|
78
|
-
transform: translateX(-50%);
|
|
79
|
-
opacity: var(--sv-stack-progress-down, 0);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.stampLeft {
|
|
83
|
-
top: var(--sv-space-4);
|
|
84
|
-
left: var(--sv-space-4);
|
|
85
|
-
transform: rotate(-8deg);
|
|
86
|
-
opacity: var(--sv-stack-progress-left, 0);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.stampRight {
|
|
90
|
-
top: var(--sv-space-4);
|
|
91
|
-
right: var(--sv-space-4);
|
|
92
|
-
transform: rotate(8deg);
|
|
93
|
-
opacity: var(--sv-stack-progress-right, 0);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.actions {
|
|
97
|
-
display: flex;
|
|
98
|
-
justify-content: center;
|
|
99
|
-
gap: var(--sv-space-2);
|
|
100
|
-
flex: 0 0 auto;
|
|
101
|
-
}
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Children, isValidElement, useEffect, useRef, useState } from 'react';
|
|
4
|
-
import type { ReactElement, ReactNode } from 'react';
|
|
5
|
-
import { Button } from '../Button/Button';
|
|
6
|
-
import { Icon, type IconName } from '../Icon/Icon';
|
|
7
|
-
import { useSwipeStack, SWIPE_STACK_TRANSITION_MS } from '../../hooks/useSwipeStack';
|
|
8
|
-
import type { SwipeDirection } from '../../hooks/useSwipeStack';
|
|
9
|
-
import { SwipeStackCard } from './SwipeStackCard';
|
|
10
|
-
import styles from './SwipeStack.module.css';
|
|
11
|
-
|
|
12
|
-
export interface SwipeDirectionMeta {
|
|
13
|
-
/** Visible text on the fallback button and the in-drag stamp. */
|
|
14
|
-
label: string;
|
|
15
|
-
icon?: IconName;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface SwipeStackProps {
|
|
19
|
-
/** Required — labels the swipeable region for assistive tech. No generic
|
|
20
|
-
* fallback, since one would be wrong for every actual consumer. */
|
|
21
|
-
'aria-label': string;
|
|
22
|
-
/** Which of the 4 directions are live, and what each is called. A
|
|
23
|
-
* direction absent here cannot be dragged toward at all (useSwipeStack
|
|
24
|
-
* treats it as a wall) and gets no fallback button or stamp. SwipeStack
|
|
25
|
-
* itself has no opinion on what a direction *means* — that vocabulary
|
|
26
|
-
* belongs entirely to the caller. */
|
|
27
|
-
directions: Partial<Record<SwipeDirection, SwipeDirectionMeta>>;
|
|
28
|
-
/** Fires once a drag (or a fallback button) commits to a direction. Every
|
|
29
|
-
* configured direction behaves the same way: the card leaves for good —
|
|
30
|
-
* there is no reversible "go back" state. SwipeStack has no opinion on
|
|
31
|
-
* where card data lives; the caller is responsible for eventually no
|
|
32
|
-
* longer including this cardId in children (e.g. once a mutation lands). */
|
|
33
|
-
onSwipe: (direction: SwipeDirection, cardId: string) => void;
|
|
34
|
-
/** Effective drag distance (px) required to commit. Passed straight
|
|
35
|
-
* through to useSwipeStack. */
|
|
36
|
-
threshold?: number;
|
|
37
|
-
className?: string;
|
|
38
|
-
/** Must be SwipeStackCard elements (nullish/boolean children are safely
|
|
39
|
-
* skipped for conditional cards). A dev-mode warning is logged for any
|
|
40
|
-
* other child type — see resolveCards below. */
|
|
41
|
-
children: ReactNode;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
interface ResolvedCard {
|
|
45
|
-
key: string;
|
|
46
|
-
element: ReactElement;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const DIRECTION_KEYS: readonly SwipeDirection[] = ['up', 'down', 'left', 'right'];
|
|
50
|
-
|
|
51
|
-
const STAMP_CLASS: Record<SwipeDirection, string> = {
|
|
52
|
-
up: styles.stampUp as string,
|
|
53
|
-
down: styles.stampDown as string,
|
|
54
|
-
left: styles.stampLeft as string,
|
|
55
|
-
right: styles.stampRight as string,
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
function describeChild(child: unknown): string {
|
|
59
|
-
if (isValidElement(child)) {
|
|
60
|
-
const type = child.type;
|
|
61
|
-
if (typeof type === 'string') return `<${type}>`;
|
|
62
|
-
if (typeof type === 'function') {
|
|
63
|
-
const named = type as { displayName?: string; name?: string };
|
|
64
|
-
return `<${named.displayName ?? named.name ?? 'Component'}>`;
|
|
65
|
-
}
|
|
66
|
-
return '<unknown>';
|
|
67
|
-
}
|
|
68
|
-
if (typeof child === 'string') return `string "${child}"`;
|
|
69
|
-
return String(child);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function resolveCards(children: ReactNode): ResolvedCard[] {
|
|
73
|
-
const cards: ResolvedCard[] = [];
|
|
74
|
-
Children.forEach(children, (child, index) => {
|
|
75
|
-
if (child === null || child === undefined || child === false || child === true) return;
|
|
76
|
-
if (!isValidElement(child) || child.type !== SwipeStackCard) {
|
|
77
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
78
|
-
console.error(
|
|
79
|
-
'[SwipeStack] Every child must be a <SwipeStackCard>. ' +
|
|
80
|
-
`Found ${describeChild(child)} at position ${index}.`,
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const cardProps = child.props as { cardId: string };
|
|
86
|
-
cards.push({ key: cardProps.cardId, element: child });
|
|
87
|
-
});
|
|
88
|
-
return cards;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* SwipeStack — a compound component for triaging one card at a time by
|
|
93
|
-
* dragging it left/right/up/down (wrapping useSwipeStack), plus an
|
|
94
|
-
* always-visible non-gesture fallback: a button per configured direction,
|
|
95
|
-
* wired to the identical commit path and exit animation as a real drag.
|
|
96
|
-
*
|
|
97
|
-
* Every direction is independently optional and behaves the same way once
|
|
98
|
-
* triggered — the card leaves for good, there is no reversible "go back".
|
|
99
|
-
* SwipeStack owns rendering, drag physics, and the stamp/fallback UI only;
|
|
100
|
-
* it has no opinion on where card data lives or what a direction means —
|
|
101
|
-
* see SwipeStackProps.onSwipe.
|
|
102
|
-
*/
|
|
103
|
-
export function SwipeStack({
|
|
104
|
-
'aria-label': ariaLabel,
|
|
105
|
-
directions,
|
|
106
|
-
onSwipe,
|
|
107
|
-
threshold,
|
|
108
|
-
className,
|
|
109
|
-
children,
|
|
110
|
-
}: SwipeStackProps) {
|
|
111
|
-
const cards = resolveCards(children);
|
|
112
|
-
const [dismissed, setDismissed] = useState<ReadonlySet<string>>(() => new Set());
|
|
113
|
-
const [exiting, setExiting] = useState<ResolvedCard | null>(null);
|
|
114
|
-
const exitTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
115
|
-
|
|
116
|
-
useEffect(
|
|
117
|
-
() => () => {
|
|
118
|
-
if (exitTimerRef.current) clearTimeout(exitTimerRef.current);
|
|
119
|
-
},
|
|
120
|
-
[],
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
const available = cards.filter((c) => !dismissed.has(c.key));
|
|
124
|
-
const nextUp = available[0];
|
|
125
|
-
const current = exiting ?? nextUp ?? null;
|
|
126
|
-
const peek = exiting ? nextUp : available[1];
|
|
127
|
-
|
|
128
|
-
const liveDirections = DIRECTION_KEYS.filter((d) => directions[d]);
|
|
129
|
-
|
|
130
|
-
const { cardRef, wrapRef, handlers, touchAction, triggerCommit } = useSwipeStack({
|
|
131
|
-
directions: liveDirections,
|
|
132
|
-
threshold,
|
|
133
|
-
disabled: !!exiting || !nextUp,
|
|
134
|
-
onCommit(direction) {
|
|
135
|
-
const committed = current;
|
|
136
|
-
if (!committed) return;
|
|
137
|
-
setDismissed((prev) => new Set(prev).add(committed.key));
|
|
138
|
-
setExiting(committed);
|
|
139
|
-
if (exitTimerRef.current) clearTimeout(exitTimerRef.current);
|
|
140
|
-
exitTimerRef.current = setTimeout(() => {
|
|
141
|
-
setExiting((prev) => (prev?.key === committed.key ? null : prev));
|
|
142
|
-
}, SWIPE_STACK_TRANSITION_MS);
|
|
143
|
-
onSwipe(direction, committed.key);
|
|
144
|
-
},
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
return (
|
|
148
|
-
<div className={[styles.wrap, className].filter(Boolean).join(' ')}>
|
|
149
|
-
<div className={styles.stack} role="region" aria-label={ariaLabel}>
|
|
150
|
-
{peek && (
|
|
151
|
-
<div className={styles.peek} key={peek.key} aria-hidden="true">
|
|
152
|
-
{peek.element}
|
|
153
|
-
</div>
|
|
154
|
-
)}
|
|
155
|
-
{current && (
|
|
156
|
-
<div className={styles.cardSlot} key={current.key} ref={wrapRef}>
|
|
157
|
-
{liveDirections.map((d) => {
|
|
158
|
-
const meta = directions[d];
|
|
159
|
-
if (!meta) return null;
|
|
160
|
-
return (
|
|
161
|
-
<div
|
|
162
|
-
key={d}
|
|
163
|
-
className={[styles.stamp, STAMP_CLASS[d]].join(' ')}
|
|
164
|
-
aria-hidden="true"
|
|
165
|
-
>
|
|
166
|
-
{meta.icon && <Icon name={meta.icon} size="sm" aria-hidden />}
|
|
167
|
-
<span>{meta.label}</span>
|
|
168
|
-
</div>
|
|
169
|
-
);
|
|
170
|
-
})}
|
|
171
|
-
<div className={styles.card} ref={cardRef} style={{ touchAction }} {...handlers}>
|
|
172
|
-
{current.element}
|
|
173
|
-
</div>
|
|
174
|
-
</div>
|
|
175
|
-
)}
|
|
176
|
-
</div>
|
|
177
|
-
{liveDirections.length > 0 && (
|
|
178
|
-
<div className={styles.actions} role="group" aria-label={`${ariaLabel} actions`}>
|
|
179
|
-
{liveDirections.map((d) => {
|
|
180
|
-
const meta = directions[d];
|
|
181
|
-
if (!meta) return null;
|
|
182
|
-
return (
|
|
183
|
-
<Button
|
|
184
|
-
key={d}
|
|
185
|
-
variant="secondary"
|
|
186
|
-
size="sm"
|
|
187
|
-
disabled={!current}
|
|
188
|
-
onClick={() => triggerCommit(d)}
|
|
189
|
-
>
|
|
190
|
-
{meta.icon && <Icon name={meta.icon} size="sm" aria-hidden />}
|
|
191
|
-
{meta.label}
|
|
192
|
-
</Button>
|
|
193
|
-
);
|
|
194
|
-
})}
|
|
195
|
-
</div>
|
|
196
|
-
)}
|
|
197
|
-
</div>
|
|
198
|
-
);
|
|
199
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
export interface SwipeStackCardProps {
|
|
4
|
-
/** Stable identity for this card, independent of its position among
|
|
5
|
-
* siblings — required. This is what SwipeStack reads (via child.props,
|
|
6
|
-
* not React's own `key`, which a component can't see on itself) to know
|
|
7
|
-
* which card is on top and what id to report through onSwipe. Reuse
|
|
8
|
-
* whatever id the caller already keys their `.map()` on. */
|
|
9
|
-
cardId: string;
|
|
10
|
-
children: ReactNode;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* SwipeStackCard — a single card of a SwipeStack. Unlike
|
|
15
|
-
* SwipableMobileCarouselSlide, this has no mount-window logic of its own:
|
|
16
|
-
* SwipeStack only ever renders the top two cards' elements at all (there is
|
|
17
|
-
* no scroll-position reason to keep every sibling in the DOM the way the
|
|
18
|
-
* carousel's scroll-snap track does), so there is nothing here to gate.
|
|
19
|
-
*/
|
|
20
|
-
export function SwipeStackCard({ children }: SwipeStackCardProps) {
|
|
21
|
-
return <>{children}</>;
|
|
22
|
-
}
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
import { act, cleanup, fireEvent, render } from '@testing-library/react';
|
|
4
|
-
import { SwipeStack } from '../SwipeStack';
|
|
5
|
-
import { SwipeStackCard } from '../SwipeStackCard';
|
|
6
|
-
import { SWIPE_STACK_TRANSITION_MS } from '../../../hooks/useSwipeStack';
|
|
7
|
-
|
|
8
|
-
// jsdom doesn't implement pointer capture — stub it as a no-op so
|
|
9
|
-
// `e.currentTarget.setPointerCapture(...)` doesn't throw.
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
if (!HTMLElement.prototype.setPointerCapture) {
|
|
12
|
-
HTMLElement.prototype.setPointerCapture = vi.fn();
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
cleanup();
|
|
18
|
-
vi.restoreAllMocks();
|
|
19
|
-
vi.useRealTimers();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
function pointer(x: number, y: number) {
|
|
23
|
-
return { clientX: x, clientY: y, pointerId: 1 };
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function renderStack(onSwipe = vi.fn()) {
|
|
27
|
-
const utils = render(
|
|
28
|
-
<SwipeStack
|
|
29
|
-
aria-label="Today's agenda"
|
|
30
|
-
directions={{
|
|
31
|
-
up: { label: 'Done', icon: 'check' },
|
|
32
|
-
down: { label: 'Defer', icon: 'history' },
|
|
33
|
-
}}
|
|
34
|
-
onSwipe={onSwipe}
|
|
35
|
-
>
|
|
36
|
-
<SwipeStackCard cardId="a">Card A</SwipeStackCard>
|
|
37
|
-
<SwipeStackCard cardId="b">Card B</SwipeStackCard>
|
|
38
|
-
<SwipeStackCard cardId="c">Card C</SwipeStackCard>
|
|
39
|
-
</SwipeStack>,
|
|
40
|
-
);
|
|
41
|
-
return { ...utils, onSwipe };
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
describe('SwipeStack', () => {
|
|
45
|
-
it('renders the topmost card', () => {
|
|
46
|
-
const { getByText, queryByText } = renderStack();
|
|
47
|
-
expect(getByText('Card A')).toBeDefined();
|
|
48
|
-
expect(queryByText('Card C')).toBeNull();
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('labels the swipeable region', () => {
|
|
52
|
-
const { getByRole } = renderStack();
|
|
53
|
-
expect(getByRole('region', { name: "Today's agenda" })).toBeDefined();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('only renders a fallback button for configured directions', () => {
|
|
57
|
-
const { getByRole, queryByRole } = renderStack();
|
|
58
|
-
expect(getByRole('button', { name: 'Done' })).toBeDefined();
|
|
59
|
-
expect(getByRole('button', { name: 'Defer' })).toBeDefined();
|
|
60
|
-
expect(queryByRole('button', { name: 'Skip' })).toBeNull();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('calls onSwipe with the direction and cardId when a drag crosses threshold', () => {
|
|
64
|
-
const { getByText, onSwipe } = renderStack();
|
|
65
|
-
const card = getByText('Card A');
|
|
66
|
-
fireEvent.pointerDown(card, pointer(0, 0));
|
|
67
|
-
fireEvent.pointerMove(card, pointer(0, -200));
|
|
68
|
-
fireEvent.pointerUp(card, pointer(0, -200));
|
|
69
|
-
expect(onSwipe).toHaveBeenCalledWith('up', 'a');
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('does not call onSwipe when dragging toward a direction that is not configured', () => {
|
|
73
|
-
const { getByText, onSwipe } = renderStack();
|
|
74
|
-
const card = getByText('Card A');
|
|
75
|
-
fireEvent.pointerDown(card, pointer(0, 0));
|
|
76
|
-
fireEvent.pointerMove(card, pointer(200, 0));
|
|
77
|
-
fireEvent.pointerUp(card, pointer(200, 0));
|
|
78
|
-
expect(onSwipe).not.toHaveBeenCalled();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('calls onSwipe when a fallback button is clicked, without any drag', () => {
|
|
82
|
-
const { getByRole, onSwipe } = renderStack();
|
|
83
|
-
fireEvent.click(getByRole('button', { name: 'Defer' }));
|
|
84
|
-
expect(onSwipe).toHaveBeenCalledWith('down', 'a');
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('advances to the next card only after the exit animation completes', () => {
|
|
88
|
-
vi.useFakeTimers();
|
|
89
|
-
const { getByRole, getByText, queryByText } = renderStack();
|
|
90
|
-
expect(getByText('Card A')).toBeDefined();
|
|
91
|
-
|
|
92
|
-
fireEvent.click(getByRole('button', { name: 'Done' }));
|
|
93
|
-
// Still mid-animation — the committed card stays put (so the fling-out
|
|
94
|
-
// it already started doesn't get cut off by a remount) and is still the
|
|
95
|
-
// one the fallback buttons act on; Card B is already visible as the
|
|
96
|
-
// peek behind it, but only decoratively (aria-hidden, not interactive).
|
|
97
|
-
expect(getByText('Card A')).toBeDefined();
|
|
98
|
-
const peekedB = getByText('Card B');
|
|
99
|
-
expect(peekedB.closest('[aria-hidden="true"]')).not.toBeNull();
|
|
100
|
-
|
|
101
|
-
act(() => {
|
|
102
|
-
vi.advanceTimersByTime(SWIPE_STACK_TRANSITION_MS);
|
|
103
|
-
});
|
|
104
|
-
expect(queryByText('Card A')).toBeNull();
|
|
105
|
-
expect(getByText('Card B').closest('[aria-hidden="true"]')).toBeNull();
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('never shows a dismissed card again, even if the caller still passes it as a child', () => {
|
|
109
|
-
vi.useFakeTimers();
|
|
110
|
-
const onSwipe = vi.fn();
|
|
111
|
-
const directions = { up: { label: 'Done', icon: 'check' as const } };
|
|
112
|
-
const { getByRole, getByText, queryByText, rerender } = render(
|
|
113
|
-
<SwipeStack aria-label="Today's agenda" directions={directions} onSwipe={onSwipe}>
|
|
114
|
-
<SwipeStackCard cardId="a">Card A</SwipeStackCard>
|
|
115
|
-
<SwipeStackCard cardId="b">Card B</SwipeStackCard>
|
|
116
|
-
</SwipeStack>,
|
|
117
|
-
);
|
|
118
|
-
fireEvent.click(getByRole('button', { name: 'Done' }));
|
|
119
|
-
act(() => {
|
|
120
|
-
vi.advanceTimersByTime(SWIPE_STACK_TRANSITION_MS);
|
|
121
|
-
});
|
|
122
|
-
expect(getByText('Card B')).toBeDefined();
|
|
123
|
-
|
|
124
|
-
// Re-render with the exact same children — a caller slow to remove the
|
|
125
|
-
// dismissed card from its own data. SwipeStack must not show it again.
|
|
126
|
-
rerender(
|
|
127
|
-
<SwipeStack aria-label="Today's agenda" directions={directions} onSwipe={onSwipe}>
|
|
128
|
-
<SwipeStackCard cardId="a">Card A</SwipeStackCard>
|
|
129
|
-
<SwipeStackCard cardId="b">Card B</SwipeStackCard>
|
|
130
|
-
</SwipeStack>,
|
|
131
|
-
);
|
|
132
|
-
expect(queryByText('Card A')).toBeNull();
|
|
133
|
-
expect(getByText('Card B')).toBeDefined();
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
describe('SwipeStack dev-mode child-type guard', () => {
|
|
138
|
-
function renderWithStrayChild() {
|
|
139
|
-
return render(
|
|
140
|
-
<SwipeStack aria-label="Today's agenda" directions={{}} onSwipe={() => {}}>
|
|
141
|
-
<SwipeStackCard cardId="a">Card A</SwipeStackCard>
|
|
142
|
-
{/* stray non-SwipeStackCard child */}
|
|
143
|
-
<div>oops</div>
|
|
144
|
-
</SwipeStack>,
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
it('warns via console.error in development, mentioning the offending child', () => {
|
|
149
|
-
const originalEnv = process.env.NODE_ENV;
|
|
150
|
-
vi.stubEnv('NODE_ENV', 'development');
|
|
151
|
-
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
152
|
-
|
|
153
|
-
expect(() => renderWithStrayChild()).not.toThrow();
|
|
154
|
-
|
|
155
|
-
expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('<div>'));
|
|
156
|
-
vi.stubEnv('NODE_ENV', originalEnv ?? 'test');
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('does not call console.error in production', () => {
|
|
160
|
-
const originalEnv = process.env.NODE_ENV;
|
|
161
|
-
vi.stubEnv('NODE_ENV', 'production');
|
|
162
|
-
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
163
|
-
|
|
164
|
-
expect(() => renderWithStrayChild()).not.toThrow();
|
|
165
|
-
|
|
166
|
-
expect(errorSpy).not.toHaveBeenCalled();
|
|
167
|
-
vi.stubEnv('NODE_ENV', originalEnv ?? 'test');
|
|
168
|
-
});
|
|
169
|
-
});
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
.banner {
|
|
2
|
-
position: sticky;
|
|
3
|
-
top: 0;
|
|
4
|
-
/* Sits above sidebar rail (z-index ~10) but below dialogs/overlays (z-index 100) */
|
|
5
|
-
z-index: 50;
|
|
6
|
-
/* WebKit momentum-scroll re-tiling quirk: a position: sticky element with
|
|
7
|
-
no compositing layer of its own can go stale/blank for a stretch of
|
|
8
|
-
frames during a fast scroll on iOS Safari instead of repainting at its
|
|
9
|
-
stuck position. translateZ(0) promotes it to its own layer, rasterized
|
|
10
|
-
independently of the scroller's tile grid. See
|
|
11
|
-
docs/architecture-rules.md — found and fixed across three sticky
|
|
12
|
-
elements in sovereign-tasks, applied here proactively since this
|
|
13
|
-
component is exactly the same pattern (sticky, inside scrolling
|
|
14
|
-
content). */
|
|
15
|
-
transform: translateZ(0);
|
|
16
|
-
display: flex;
|
|
17
|
-
align-items: center;
|
|
18
|
-
justify-content: center;
|
|
19
|
-
gap: var(--sv-space-3);
|
|
20
|
-
padding: var(--sv-space-2) var(--sv-space-4);
|
|
21
|
-
border-bottom-width: 1px;
|
|
22
|
-
border-bottom-style: solid;
|
|
23
|
-
font-family: var(--sv-font-family);
|
|
24
|
-
font-size: var(--sv-font-size-sm);
|
|
25
|
-
line-height: 1.4;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.content {
|
|
29
|
-
flex: 1;
|
|
30
|
-
text-align: center;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/* Dismiss button — inherits the variant text colour */
|
|
34
|
-
.dismiss {
|
|
35
|
-
display: inline-flex;
|
|
36
|
-
align-items: center;
|
|
37
|
-
justify-content: center;
|
|
38
|
-
flex-shrink: 0;
|
|
39
|
-
width: 24px;
|
|
40
|
-
height: 24px;
|
|
41
|
-
padding: 0;
|
|
42
|
-
border: none;
|
|
43
|
-
border-radius: var(--sv-radius-sm);
|
|
44
|
-
background: transparent;
|
|
45
|
-
color: inherit;
|
|
46
|
-
cursor: pointer;
|
|
47
|
-
opacity: 0.7;
|
|
48
|
-
transition: opacity 0.12s ease;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@media (hover: hover) {
|
|
52
|
-
.dismiss:hover {
|
|
53
|
-
opacity: 1;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.dismiss:focus-visible {
|
|
58
|
-
outline: 2px solid currentColor;
|
|
59
|
-
outline-offset: 1px;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/* Variants */
|
|
63
|
-
.info {
|
|
64
|
-
background: var(--sv-color-info-surface);
|
|
65
|
-
color: var(--sv-color-info-text);
|
|
66
|
-
border-bottom-color: var(--sv-color-info-border);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.warning {
|
|
70
|
-
background: var(--sv-color-warning-surface);
|
|
71
|
-
color: var(--sv-color-warning-text);
|
|
72
|
-
border-bottom-color: var(--sv-color-warning-border);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
.error {
|
|
76
|
-
background: var(--sv-color-error-surface);
|
|
77
|
-
color: var(--sv-color-error-text);
|
|
78
|
-
border-bottom-color: var(--sv-color-error-border);
|
|
79
|
-
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
2
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
-
import { SystemBanner } from './SystemBanner';
|
|
4
|
-
|
|
5
|
-
const meta = {
|
|
6
|
-
title: 'Components/SystemBanner',
|
|
7
|
-
component: SystemBanner,
|
|
8
|
-
parameters: {
|
|
9
|
-
layout: 'fullscreen',
|
|
10
|
-
docs: {
|
|
11
|
-
description: {
|
|
12
|
-
component:
|
|
13
|
-
'Full-width `position: sticky` strip for platform-level notices. Stack multiple banners by rendering multiple `<SystemBanner>` elements. Dismiss button only appears when `onDismiss` is provided.',
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
argTypes: {
|
|
18
|
-
variant: { control: 'select', options: ['info', 'warning', 'error'] },
|
|
19
|
-
},
|
|
20
|
-
args: {
|
|
21
|
-
children: 'Notice',
|
|
22
|
-
},
|
|
23
|
-
} satisfies Meta<typeof SystemBanner>;
|
|
24
|
-
|
|
25
|
-
export default meta;
|
|
26
|
-
type Story = StoryObj<typeof meta>;
|
|
27
|
-
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
export const Info: Story = {
|
|
31
|
-
args: {
|
|
32
|
-
variant: 'info',
|
|
33
|
-
children: 'Platform is in read-only mode during migration.',
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const Warning: Story = {
|
|
38
|
-
args: {
|
|
39
|
-
variant: 'warning',
|
|
40
|
-
children: 'License for Example: Monetized expires in 7 days.',
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export const Error: Story = {
|
|
45
|
-
args: {
|
|
46
|
-
variant: 'error',
|
|
47
|
-
children: 'Maintenance mode is active — only admins can sign in.',
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export const Dismissible: Story = {
|
|
52
|
-
render: (_args) => {
|
|
53
|
-
const [visible, setVisible] = useState(true);
|
|
54
|
-
return visible ? (
|
|
55
|
-
<SystemBanner variant="warning" onDismiss={() => setVisible(false)}>
|
|
56
|
-
License for Example: Monetized expires in 7 days.
|
|
57
|
-
</SystemBanner>
|
|
58
|
-
) : (
|
|
59
|
-
<div
|
|
60
|
-
style={{
|
|
61
|
-
padding: 16,
|
|
62
|
-
fontFamily: 'var(--sv-font-family)',
|
|
63
|
-
fontSize: 'var(--sv-font-size-sm)',
|
|
64
|
-
color: 'var(--sv-color-text-muted)',
|
|
65
|
-
}}
|
|
66
|
-
>
|
|
67
|
-
Banner dismissed.
|
|
68
|
-
</div>
|
|
69
|
-
);
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/** All three variants stacked — as they appear when multiple notices are active. */
|
|
74
|
-
export const Stacked: Story = {
|
|
75
|
-
render: (_args) => (
|
|
76
|
-
<div>
|
|
77
|
-
<SystemBanner variant="error">
|
|
78
|
-
Maintenance mode is active — only admins can sign in.
|
|
79
|
-
</SystemBanner>
|
|
80
|
-
<SystemBanner variant="warning">
|
|
81
|
-
License for Example: Monetized expires in 7 days.
|
|
82
|
-
</SystemBanner>
|
|
83
|
-
<SystemBanner variant="info">Platform is in read-only mode during migration.</SystemBanner>
|
|
84
|
-
</div>
|
|
85
|
-
),
|
|
86
|
-
};
|