@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,58 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import type { ReactNode } from 'react';
|
|
4
|
-
import { EmptyState } from '../EmptyState/EmptyState';
|
|
5
|
-
|
|
6
|
-
export interface DeviceOnlyGateProps {
|
|
7
|
-
children: ReactNode;
|
|
8
|
-
/** Defaults to a generic "this app" phrasing — pass the plugin's own name. */
|
|
9
|
-
surfaceName?: string;
|
|
10
|
-
/**
|
|
11
|
-
* The caller's own `isDeviceOnlyTierAvailable()` result (from
|
|
12
|
-
* `@sovereignfs/sdk/device-client`) — taken as a plain boolean rather than
|
|
13
|
-
* computed inside this component, so `@sovereignfs/ui` never depends on
|
|
14
|
-
* `@sovereignfs/sdk` (this package must stay usable standalone, outside the
|
|
15
|
-
* plugin runtime — RFC 0073).
|
|
16
|
-
*/
|
|
17
|
-
available: boolean;
|
|
18
|
-
className?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* DeviceOnlyGate — blocks a `device-only`-tier plugin's content from
|
|
23
|
-
* rendering on a surface that cannot provide the durable, encrypted,
|
|
24
|
-
* device-auth-gated store that tier requires, showing an explanatory empty
|
|
25
|
-
* state instead of a broken screen (research 0012, epic tasks 2.33 + 3.36).
|
|
26
|
-
*
|
|
27
|
-
* A `device-only` plugin wraps its own root content in this the same way
|
|
28
|
-
* Console and Account wrap theirs in `OfflineGate` — an opt-in pattern each
|
|
29
|
-
* surface applies to itself, not a platform-level route gate. The launcher
|
|
30
|
-
* tile's own "Phone only" badge (`useOfflineTileState`) is advisory UI on top
|
|
31
|
-
* of this; this component is the actual gate, since a user can always reach a
|
|
32
|
-
* route directly (a bookmark, a deep link) without passing through the
|
|
33
|
-
* launcher tile at all.
|
|
34
|
-
*
|
|
35
|
-
* **Not a security boundary.** Availability here is a capability signal, not
|
|
36
|
-
* an authorization check — the real protection for `device-only` data is
|
|
37
|
-
* that it is encrypted and the key requires device auth to release (epic task
|
|
38
|
-
* 1.22), so it stays inaccessible regardless of whether this gate is present,
|
|
39
|
-
* bypassed, or simply never reached (e.g. a hand-crafted request against the
|
|
40
|
-
* plugin's own API routes).
|
|
41
|
-
*/
|
|
42
|
-
export function DeviceOnlyGate({
|
|
43
|
-
children,
|
|
44
|
-
surfaceName,
|
|
45
|
-
available,
|
|
46
|
-
className,
|
|
47
|
-
}: DeviceOnlyGateProps) {
|
|
48
|
-
if (available) return <>{children}</>;
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<EmptyState
|
|
52
|
-
icon="smartphone"
|
|
53
|
-
heading="Phone only"
|
|
54
|
-
description={`${surfaceName ?? 'This app'} is only available on a phone with secure storage set up.`}
|
|
55
|
-
className={className}
|
|
56
|
-
/>
|
|
57
|
-
);
|
|
58
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
|
-
import { cleanup, render, screen } from '@testing-library/react';
|
|
4
|
-
import { DeviceOnlyGate } from '../DeviceOnlyGate';
|
|
5
|
-
|
|
6
|
-
describe('DeviceOnlyGate', () => {
|
|
7
|
-
afterEach(cleanup);
|
|
8
|
-
|
|
9
|
-
it('renders children unchanged when available', () => {
|
|
10
|
-
render(
|
|
11
|
-
<DeviceOnlyGate available={true}>
|
|
12
|
-
<p>Wallet content</p>
|
|
13
|
-
</DeviceOnlyGate>,
|
|
14
|
-
);
|
|
15
|
-
expect(screen.getByText('Wallet content')).toBeDefined();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('replaces children with an explanatory empty state when unavailable', () => {
|
|
19
|
-
render(
|
|
20
|
-
<DeviceOnlyGate available={false}>
|
|
21
|
-
<p>Wallet content</p>
|
|
22
|
-
</DeviceOnlyGate>,
|
|
23
|
-
);
|
|
24
|
-
expect(screen.queryByText('Wallet content')).toBeNull();
|
|
25
|
-
expect(screen.getByText('Phone only')).toBeDefined();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('names the surface in the message when provided', () => {
|
|
29
|
-
render(
|
|
30
|
-
<DeviceOnlyGate available={false} surfaceName="Wallet">
|
|
31
|
-
<p>Wallet content</p>
|
|
32
|
-
</DeviceOnlyGate>,
|
|
33
|
-
);
|
|
34
|
-
expect(screen.getByText(/Wallet is only available on a phone/)).toBeDefined();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('falls back to generic phrasing with no surface name', () => {
|
|
38
|
-
render(
|
|
39
|
-
<DeviceOnlyGate available={false}>
|
|
40
|
-
<p>Wallet content</p>
|
|
41
|
-
</DeviceOnlyGate>,
|
|
42
|
-
);
|
|
43
|
-
expect(screen.getByText(/This app is only available on a phone/)).toBeDefined();
|
|
44
|
-
});
|
|
45
|
-
});
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import type { ReactNode } from 'react';
|
|
4
|
-
import { EmptyState } from '../EmptyState/EmptyState';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* `'checking'` covers the moment before the caller's own async status check
|
|
8
|
-
* resolves — same transitional-state pattern `EncryptionSection`'s local
|
|
9
|
-
* `LocalState` uses, so this gate never flashes an empty state before the
|
|
10
|
-
* real answer is known. `'no-device-auth'` is the hard-block case (RFC 0093
|
|
11
|
-
* §5, epic task 1.22): the environment supports the tier, but this device
|
|
12
|
-
* has no passcode, fingerprint, or face unlock configured, so a key cannot
|
|
13
|
-
* be created here at all — distinct from `'not-set-up'`, where it can.
|
|
14
|
-
*/
|
|
15
|
-
export type DeviceStorageKeyGateStatus =
|
|
16
|
-
'checking' | 'unsupported' | 'no-device-auth' | 'not-set-up' | 'set-up';
|
|
17
|
-
|
|
18
|
-
export interface DeviceStorageKeyGateProps {
|
|
19
|
-
children: ReactNode;
|
|
20
|
-
/** Defaults to a generic "This app" phrasing — pass the plugin's own name. */
|
|
21
|
-
surfaceName?: string;
|
|
22
|
-
/**
|
|
23
|
-
* The caller's own `getDeviceStorageKeyStatus()` result (from
|
|
24
|
-
* `@sovereignfs/sdk/device-only-storage`) — taken as a plain status rather
|
|
25
|
-
* than computed inside this component, so `@sovereignfs/ui` never depends
|
|
26
|
-
* on `@sovereignfs/sdk` (same boundary `DeviceOnlyGate`'s `available` prop
|
|
27
|
-
* draws — this package must stay usable standalone, outside the plugin
|
|
28
|
-
* runtime — RFC 0073).
|
|
29
|
-
*/
|
|
30
|
-
status: DeviceStorageKeyGateStatus;
|
|
31
|
-
/**
|
|
32
|
-
* Rendered under the "not set up" message — typically a link to Account →
|
|
33
|
-
* Security. Not built in here: this package depends on no router, so the
|
|
34
|
-
* caller supplies its own navigable element (a plain `<a>`, a framework
|
|
35
|
-
* `<Link>`, whatever the host app uses).
|
|
36
|
-
*/
|
|
37
|
-
setupAction?: ReactNode;
|
|
38
|
-
className?: string;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* DeviceStorageKeyGate — blocks a `device-only`-tier plugin's content until
|
|
43
|
-
* the user has set up their Device Storage Key (RFC 0093 §2, epic task
|
|
44
|
-
* 1.22). Distinct from `DeviceOnlyGate`: that one checks whether the *tier
|
|
45
|
-
* itself* is available on this surface (native shell, secure-storage bridge
|
|
46
|
-
* present); this one checks whether the user has actually completed the
|
|
47
|
-
* one-time, per-device enrollment that tier depends on. A `device-only`
|
|
48
|
-
* plugin typically wants both — `DeviceOnlyGate` outermost (no point
|
|
49
|
-
* checking enrollment on a surface that cannot offer the tier at all), this
|
|
50
|
-
* gate inside it.
|
|
51
|
-
*
|
|
52
|
-
* Enrollment is centralized and decoupled from any single plugin (RFC 0093
|
|
53
|
-
* §2): a plugin that finds no key set up does not run its own enrollment
|
|
54
|
-
* ceremony inline. It stops here and points the user at Account → Security —
|
|
55
|
-
* the one place enrollment happens for every `device-only` plugin on this
|
|
56
|
-
* device — via `setupAction`, the same opt-in, self-applied pattern
|
|
57
|
-
* `OfflineGate`/`DeviceOnlyGate` already use for their own surfaces.
|
|
58
|
-
*/
|
|
59
|
-
export function DeviceStorageKeyGate({
|
|
60
|
-
children,
|
|
61
|
-
surfaceName,
|
|
62
|
-
status,
|
|
63
|
-
setupAction,
|
|
64
|
-
className,
|
|
65
|
-
}: DeviceStorageKeyGateProps) {
|
|
66
|
-
if (status === 'checking') return null;
|
|
67
|
-
if (status === 'set-up') return <>{children}</>;
|
|
68
|
-
|
|
69
|
-
if (status === 'unsupported') {
|
|
70
|
-
return (
|
|
71
|
-
<EmptyState
|
|
72
|
-
icon="smartphone"
|
|
73
|
-
heading="Phone only"
|
|
74
|
-
description={`${surfaceName ?? 'This app'} needs a security feature (WebAuthn PRF and Origin Private File System support) that isn't available here.`}
|
|
75
|
-
className={className}
|
|
76
|
-
/>
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (status === 'no-device-auth') {
|
|
81
|
-
return (
|
|
82
|
-
<EmptyState
|
|
83
|
-
icon="alert-triangle"
|
|
84
|
-
heading="Set up a device passcode"
|
|
85
|
-
description={`${surfaceName ?? 'This app'} needs a passcode, fingerprint, or face unlock set up on this device before its Device Storage Key can be created. Set one up in your device's system settings, then come back.`}
|
|
86
|
-
className={className}
|
|
87
|
-
/>
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<EmptyState
|
|
93
|
-
icon="lock"
|
|
94
|
-
heading="Set up your Device Storage Key"
|
|
95
|
-
description={`${surfaceName ?? 'This app'} keeps its data only on this device, protected by a Device Storage Key you set up once in Account → Security.`}
|
|
96
|
-
action={setupAction}
|
|
97
|
-
className={className}
|
|
98
|
-
/>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
|
-
import { cleanup, render, screen } from '@testing-library/react';
|
|
4
|
-
import { DeviceStorageKeyGate } from '../DeviceStorageKeyGate';
|
|
5
|
-
|
|
6
|
-
describe('DeviceStorageKeyGate', () => {
|
|
7
|
-
afterEach(cleanup);
|
|
8
|
-
|
|
9
|
-
it('renders nothing while checking', () => {
|
|
10
|
-
const { container } = render(
|
|
11
|
-
<DeviceStorageKeyGate status="checking">
|
|
12
|
-
<p>Notes content</p>
|
|
13
|
-
</DeviceStorageKeyGate>,
|
|
14
|
-
);
|
|
15
|
-
expect(container.firstChild).toBeNull();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('renders children unchanged once set up', () => {
|
|
19
|
-
render(
|
|
20
|
-
<DeviceStorageKeyGate status="set-up">
|
|
21
|
-
<p>Notes content</p>
|
|
22
|
-
</DeviceStorageKeyGate>,
|
|
23
|
-
);
|
|
24
|
-
expect(screen.getByText('Notes content')).toBeDefined();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('shows a "Phone only"-style message when the environment is unsupported', () => {
|
|
28
|
-
render(
|
|
29
|
-
<DeviceStorageKeyGate status="unsupported">
|
|
30
|
-
<p>Notes content</p>
|
|
31
|
-
</DeviceStorageKeyGate>,
|
|
32
|
-
);
|
|
33
|
-
expect(screen.queryByText('Notes content')).toBeNull();
|
|
34
|
-
expect(screen.getByText('Phone only')).toBeDefined();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('shows the setup message and prompt when not-set-up', () => {
|
|
38
|
-
render(
|
|
39
|
-
<DeviceStorageKeyGate status="not-set-up">
|
|
40
|
-
<p>Notes content</p>
|
|
41
|
-
</DeviceStorageKeyGate>,
|
|
42
|
-
);
|
|
43
|
-
expect(screen.queryByText('Notes content')).toBeNull();
|
|
44
|
-
expect(screen.getByText('Set up your Device Storage Key')).toBeDefined();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('names the surface in the not-set-up message when provided', () => {
|
|
48
|
-
render(
|
|
49
|
-
<DeviceStorageKeyGate status="not-set-up" surfaceName="Notes">
|
|
50
|
-
<p>Notes content</p>
|
|
51
|
-
</DeviceStorageKeyGate>,
|
|
52
|
-
);
|
|
53
|
-
expect(screen.getByText(/Notes keeps its data only on this device/)).toBeDefined();
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('falls back to generic phrasing with no surface name', () => {
|
|
57
|
-
render(
|
|
58
|
-
<DeviceStorageKeyGate status="not-set-up">
|
|
59
|
-
<p>Notes content</p>
|
|
60
|
-
</DeviceStorageKeyGate>,
|
|
61
|
-
);
|
|
62
|
-
expect(screen.getByText(/This app keeps its data only on this device/)).toBeDefined();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('renders the caller-supplied setupAction when not-set-up', () => {
|
|
66
|
-
render(
|
|
67
|
-
<DeviceStorageKeyGate
|
|
68
|
-
status="not-set-up"
|
|
69
|
-
setupAction={<a href="/account/security">Go to Account → Security</a>}
|
|
70
|
-
>
|
|
71
|
-
<p>Notes content</p>
|
|
72
|
-
</DeviceStorageKeyGate>,
|
|
73
|
-
);
|
|
74
|
-
expect(screen.getByRole('link', { name: 'Go to Account → Security' })).toBeDefined();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('renders no setupAction when unsupported, even if one is passed', () => {
|
|
78
|
-
render(
|
|
79
|
-
<DeviceStorageKeyGate
|
|
80
|
-
status="unsupported"
|
|
81
|
-
setupAction={<a href="/account/security">Go to Account → Security</a>}
|
|
82
|
-
>
|
|
83
|
-
<p>Notes content</p>
|
|
84
|
-
</DeviceStorageKeyGate>,
|
|
85
|
-
);
|
|
86
|
-
expect(screen.queryByRole('link')).toBeNull();
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('shows the hard-block message when no-device-auth', () => {
|
|
90
|
-
render(
|
|
91
|
-
<DeviceStorageKeyGate status="no-device-auth">
|
|
92
|
-
<p>Notes content</p>
|
|
93
|
-
</DeviceStorageKeyGate>,
|
|
94
|
-
);
|
|
95
|
-
expect(screen.queryByText('Notes content')).toBeNull();
|
|
96
|
-
expect(screen.getByText('Set up a device passcode')).toBeDefined();
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('names the surface in the no-device-auth message when provided', () => {
|
|
100
|
-
render(
|
|
101
|
-
<DeviceStorageKeyGate status="no-device-auth" surfaceName="Notes">
|
|
102
|
-
<p>Notes content</p>
|
|
103
|
-
</DeviceStorageKeyGate>,
|
|
104
|
-
);
|
|
105
|
-
expect(screen.getByText(/Notes needs a passcode, fingerprint, or face unlock/)).toBeDefined();
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('renders no setupAction when no-device-auth, even if one is passed — fixing this is a device settings change, not a Sovereign link', () => {
|
|
109
|
-
render(
|
|
110
|
-
<DeviceStorageKeyGate
|
|
111
|
-
status="no-device-auth"
|
|
112
|
-
setupAction={<a href="/account/security">Go to Account → Security</a>}
|
|
113
|
-
>
|
|
114
|
-
<p>Notes content</p>
|
|
115
|
-
</DeviceStorageKeyGate>,
|
|
116
|
-
);
|
|
117
|
-
expect(screen.queryByRole('link')).toBeNull();
|
|
118
|
-
});
|
|
119
|
-
});
|
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
/* Dialog — scrim + centered panel. Tokens only (z-index is structural, not a
|
|
2
|
-
* theming value, so it has no token).
|
|
3
|
-
*
|
|
4
|
-
* `sm`/`md` are a fixed WIDTH but a content-driven height, capped at a
|
|
5
|
-
* per-size max-height: the panel grows to fit its content and shrinks when
|
|
6
|
-
* content is sparse, only hitting the cap (and scrolling internally, inside
|
|
7
|
-
* `.content`) once content actually exceeds it. Before this, height was
|
|
8
|
-
* fixed too, which left short-content consumers (e.g. a two-field form in
|
|
9
|
-
* console/plugins/PluginAccessDialog.tsx) looking like a near-empty
|
|
10
|
-
* skeleton — see docs/architecture-rules.md. `auto` goes further — content-
|
|
11
|
-
* driven on BOTH width and height, each independently capped rather than
|
|
12
|
-
* either being fixed — for content whose natural footprint varies enough
|
|
13
|
-
* (a card detail modal with an optional checklist/comments section) that a
|
|
14
|
-
* single fixed width doesn't fit it well either short or long. `lg` is a
|
|
15
|
-
* true fixed box (100%/100% of the scrim's available area) — no current
|
|
16
|
-
* overlay-shell plugin renders into it (Console did until workstream 0022
|
|
17
|
-
* moved it to `shell: "default"`; Account never resized off `overlaySize:
|
|
18
|
-
* "lg"`'s original default until epic task 14.5, see `fixed` below).
|
|
19
|
-
* `fixed` (named after its own behavior, not after this file's always-
|
|
20
|
-
* applied `.panel` wrapper class below) is also a true fixed box, width
|
|
21
|
-
* AND height both set — same "content never resizes it" guarantee as `lg`
|
|
22
|
-
* — but capped rather than filling the viewport, for a plugin whose
|
|
23
|
-
* settings-panel-shaped content doesn't warrant `lg`'s full-screen footprint
|
|
24
|
-
* (Account's own case, epic task 14.5 round 3). The close button stays
|
|
25
|
-
* pinned top-right regardless. The scrim's padding is the fixed margin
|
|
26
|
-
* `lg`/`fixed` leave around the viewport; `sm`/`md`/`auto` are centered and
|
|
27
|
-
* cap to that available space on short screens too. On mobile every size
|
|
28
|
-
* becomes a full-screen sheet.
|
|
29
|
-
*
|
|
30
|
-
* `--sv-dialog-inset-left` lets a host inset the scrim past a fixed left nav
|
|
31
|
-
* rail (e.g. the platform sidebar) so the overlay's left margin is measured
|
|
32
|
-
* from the rail, not the viewport edge, and the rail stays visible/usable.
|
|
33
|
-
* `--sv-dialog-inset-top` (RFC 0013) mirrors this on the vertical axis: the
|
|
34
|
-
* shell sets it to the mobile header height so the header stays visible and
|
|
35
|
-
* interactive above the dialog sheet. Defaults to 0 for standalone use. */
|
|
36
|
-
|
|
37
|
-
.scrim {
|
|
38
|
-
position: fixed;
|
|
39
|
-
top: var(--sv-dialog-inset-top, 0);
|
|
40
|
-
right: 0;
|
|
41
|
-
bottom: 0;
|
|
42
|
-
left: 0;
|
|
43
|
-
z-index: 100;
|
|
44
|
-
display: flex;
|
|
45
|
-
align-items: center;
|
|
46
|
-
justify-content: center;
|
|
47
|
-
/* left edge always 0 so the backdrop covers the full viewport incl. sidebar.
|
|
48
|
-
padding-left offsets the panel's available area to start at the rail edge. */
|
|
49
|
-
padding: var(--sv-space-8);
|
|
50
|
-
padding-left: calc(var(--sv-dialog-inset-left, 0px) + var(--sv-space-8));
|
|
51
|
-
background: var(--sv-color-scrim);
|
|
52
|
-
/* Entrance/exit fade. The Dialog component drives this via a two-phase
|
|
53
|
-
mount (see motion.ts) — .scrimOpen is added one frame after mount so this
|
|
54
|
-
transition has somewhere to animate from, and removed (while staying
|
|
55
|
-
mounted) for the exit before the component actually unmounts. */
|
|
56
|
-
opacity: 0;
|
|
57
|
-
transition: opacity var(--sv-motion-duration-base) var(--sv-motion-ease-out);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.scrimOpen {
|
|
61
|
-
opacity: 1;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.panel {
|
|
65
|
-
position: relative;
|
|
66
|
-
display: flex;
|
|
67
|
-
flex-direction: column;
|
|
68
|
-
overflow: hidden;
|
|
69
|
-
background: var(--sv-color-surface-raised);
|
|
70
|
-
color: var(--sv-color-text-primary);
|
|
71
|
-
border: var(--sv-border-width-hairline) solid var(--sv-color-border);
|
|
72
|
-
border-radius: var(--sv-radius-lg);
|
|
73
|
-
box-shadow: var(--sv-shadow-overlay);
|
|
74
|
-
/* Desktop entrance: fade + gentle scale-up. Same two-phase-mount pattern as
|
|
75
|
-
.scrim above. Mobile overrides this to a slide-up instead (below). */
|
|
76
|
-
opacity: 0;
|
|
77
|
-
transform: scale(0.96);
|
|
78
|
-
transition:
|
|
79
|
-
opacity var(--sv-motion-duration-base) var(--sv-motion-ease-out),
|
|
80
|
-
transform var(--sv-motion-duration-base) var(--sv-motion-ease-out);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
.panelOpen {
|
|
84
|
-
opacity: 1;
|
|
85
|
-
transform: scale(1);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/* prefers-reduced-motion: collapse both fade/scale and slide to near-instant.
|
|
89
|
-
Not literally 0 — a 0ms transition can skip applying entirely in some
|
|
90
|
-
engines, and the JS unmount timer (Dialog.tsx's MOTION_DURATION_MS,
|
|
91
|
-
switched to ~0 via usePrefersReducedMotion) needs a transition to still be
|
|
92
|
-
"present" for the visual state to actually reach its end value in time. */
|
|
93
|
-
@media (prefers-reduced-motion: reduce) {
|
|
94
|
-
.scrim,
|
|
95
|
-
.panel {
|
|
96
|
-
transition-duration: 0.01ms;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/* Sizing audit: reviewed padding/radius against this scale's other
|
|
101
|
-
surfaces. --sv-radius-lg (shared with Card via .panel below) left
|
|
102
|
-
unchanged for the same blast-radius reason as Card.module.css. */
|
|
103
|
-
.content {
|
|
104
|
-
flex: 1 1 auto;
|
|
105
|
-
overflow-y: auto;
|
|
106
|
-
overflow-x: hidden;
|
|
107
|
-
/* Same slim, token-colored scrollbar as `ScrollArea`/`MessageScroller` —
|
|
108
|
-
without this, a `sm`/`md` dialog whose content exceeds its max-height
|
|
109
|
-
cap (e.g. on a short viewport where the cap itself shrinks to fit) gets
|
|
110
|
-
the browser's default OS scrollbar, which on non-overlay-scrollbar
|
|
111
|
-
platforms is wide enough to visually cut into `.panel`'s rounded
|
|
112
|
-
corner right where `.content` starts, reading as a layout bug rather
|
|
113
|
-
than an intentional scroll affordance. */
|
|
114
|
-
scrollbar-width: thin;
|
|
115
|
-
scrollbar-color: var(--sv-color-border-strong) transparent;
|
|
116
|
-
padding: var(--sv-space-6);
|
|
117
|
-
/* This region already supplies the page gutter, so a PageContainer rendered
|
|
118
|
-
inside it stands its own down (see PageContainer.module.css). Without
|
|
119
|
-
this, an overlay plugin — one page tree rendered into both the Dialog and
|
|
120
|
-
the full-page shell fallback — would be padded twice here. */
|
|
121
|
-
--sv-page-gutter: 0px;
|
|
122
|
-
/* Disable elastic overscroll within the dialog: `none` stops both scroll-
|
|
123
|
-
chaining to the parent and the iOS rubber-band bounce inside the panel.
|
|
124
|
-
`contain` only prevents chaining — the panel itself still bounces, which
|
|
125
|
-
reveals white panel-background between OverlayHeader and the sticky tab
|
|
126
|
-
strip on iOS PWA. A dialog is a bounded surface where bounce is a visual
|
|
127
|
-
bug, not a feature. */
|
|
128
|
-
overscroll-behavior: none;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.content::-webkit-scrollbar {
|
|
132
|
-
width: 8px;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
.content::-webkit-scrollbar-track {
|
|
136
|
-
background: transparent;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.content::-webkit-scrollbar-thumb {
|
|
140
|
-
background: var(--sv-color-border-strong);
|
|
141
|
-
border-radius: var(--sv-radius-full);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/* `sm`/`md`: fixed width, content-driven height up to the size's own cap
|
|
145
|
-
* (28rem/42rem — the box's old fixed heights, now a ceiling rather than a
|
|
146
|
-
* floor). `min(<cap>, 100%)` also still caps to the scrim's content box
|
|
147
|
-
* (viewport minus margin) so a size never overflows a short viewport. No
|
|
148
|
-
* explicit `height` — the panel's flex column sizes to `.content`'s natural
|
|
149
|
-
* height on its own; see the file-level comment above. */
|
|
150
|
-
.sm {
|
|
151
|
-
width: 24rem;
|
|
152
|
-
max-width: 100%;
|
|
153
|
-
max-height: min(28rem, 100%);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
.md {
|
|
157
|
-
width: 36rem;
|
|
158
|
-
max-width: 100%;
|
|
159
|
-
max-height: min(42rem, 100%);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/* Content-driven on both axes, unlike `sm`/`md` (width fixed, only height
|
|
163
|
-
* content-driven) — for a dialog whose natural footprint varies a lot (a
|
|
164
|
-
* card detail modal with labels/due-date/assignees/description/checklist/
|
|
165
|
-
* comments, the case that originally motivated the now-removed `xl` size
|
|
166
|
-
* this replaces). `width: fit-content` shrink-wraps to the panel's own
|
|
167
|
-
* content (bounded by min/max-width below) the same way a flex item
|
|
168
|
-
* centered in `.scrim` naturally would with no explicit `width` at all —
|
|
169
|
-
* `min-width` just keeps sparse content (e.g. a short message) from reading
|
|
170
|
-
* as an oddly narrow sliver. Caps chosen to span roughly what `sm`/`xl`
|
|
171
|
-
* used to cover between them. */
|
|
172
|
-
.auto {
|
|
173
|
-
width: fit-content;
|
|
174
|
-
min-width: min(24rem, 100%);
|
|
175
|
-
max-width: min(48rem, 100%);
|
|
176
|
-
max-height: min(48rem, 100%);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/* `lg`: a true fixed box, unaffected by the above — see the file-level
|
|
180
|
-
* comment. */
|
|
181
|
-
.lg {
|
|
182
|
-
width: 100%;
|
|
183
|
-
height: 100%;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/* `fixed`: also a true fixed box (width AND height both set, like `lg`) but
|
|
187
|
-
* capped rather than filling the viewport — see the file-level comment.
|
|
188
|
-
* Named distinctly from the dialog's own always-applied `.panel` wrapper
|
|
189
|
-
* class above (every size gets `styles.panel` + `styles[size]` together —
|
|
190
|
-
* see Dialog.tsx) to avoid colliding with it. `max-width`/`max-height` are
|
|
191
|
-
* still needed despite `width`/`height` being fixed rem values, exactly
|
|
192
|
-
* like `sm`/`md`'s own `max-width: 100%` — a short or narrow viewport (a
|
|
193
|
-
* resized desktop window, not yet at the mobile breakpoint) must still be
|
|
194
|
-
* able to shrink this below its rem values instead of overflowing the
|
|
195
|
-
* scrim. */
|
|
196
|
-
.fixed {
|
|
197
|
-
width: 64rem;
|
|
198
|
-
max-width: 100%;
|
|
199
|
-
height: 44rem;
|
|
200
|
-
max-height: 100%;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
.close {
|
|
204
|
-
position: absolute;
|
|
205
|
-
top: var(--sv-space-3);
|
|
206
|
-
right: var(--sv-space-3);
|
|
207
|
-
/* 2, not 1: a plugin's own sticky in-body header (e.g. a card detail
|
|
208
|
-
modal's title row) needs to paint above ordinary scrolling content, so
|
|
209
|
-
it sits at z-index: 1 — if `.close` also sat at 1, tree order would
|
|
210
|
-
decide the tie, and `.close` (rendered earlier in this component's own
|
|
211
|
-
JSX, before `.content` and everything a plugin nests inside it) would
|
|
212
|
-
lose to the plugin's later-in-tree header, disappearing underneath it
|
|
213
|
-
once they overlap on scroll. 2 keeps `.close` unambiguously on top
|
|
214
|
-
without relying on a tie-break plugin authors have no visibility into.
|
|
215
|
-
Found live in `sovereign-plugin-kanban`'s card detail modal — see that
|
|
216
|
-
repo's `kanban.module.css` `.cardHeader` comment for the matching half
|
|
217
|
-
of this fix and the Popover-stacking bug that motivated it. */
|
|
218
|
-
z-index: 2;
|
|
219
|
-
display: inline-flex;
|
|
220
|
-
align-items: center;
|
|
221
|
-
justify-content: center;
|
|
222
|
-
width: var(--sv-space-8);
|
|
223
|
-
height: var(--sv-space-8);
|
|
224
|
-
border: none;
|
|
225
|
-
border-radius: var(--sv-radius-md);
|
|
226
|
-
background: transparent;
|
|
227
|
-
color: var(--sv-color-text-muted);
|
|
228
|
-
cursor: pointer;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
@media (hover: hover) {
|
|
232
|
-
.close:hover {
|
|
233
|
-
background: var(--sv-color-surface-sunken);
|
|
234
|
-
color: var(--sv-color-text-primary);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
.close:focus-visible {
|
|
239
|
-
outline: 2px solid var(--sv-color-focus-ring);
|
|
240
|
-
outline-offset: 2px;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/* Hidden on desktop; shown only on mobile where it replaces the close button.
|
|
244
|
-
* OverlayHeader owns its own background/border/padding — this wrapper class
|
|
245
|
-
* only toggles visibility per breakpoint. Not used at all when the `header`
|
|
246
|
-
* prop is active — that OverlayHeader instance renders with no wrapper
|
|
247
|
-
* class, so it shows unconditionally on both breakpoints (see Dialog.tsx). */
|
|
248
|
-
.mobileHeader {
|
|
249
|
-
display: none;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/* The optional `footer` prop's row — shown on both desktop and mobile (no
|
|
253
|
-
* breakpoint gating, unlike `.mobileHeader`), a flex sibling after `.content`
|
|
254
|
-
* so it never scrolls, mirroring OverlayHeader's own `.header`/`.row`
|
|
255
|
-
* treatment (border on the opposite edge, same padding scale) so header and
|
|
256
|
-
* footer read as a matched pair when both are present. Layout-agnostic
|
|
257
|
-
* beyond that — the footer's own content decides its internal arrangement
|
|
258
|
-
* (e.g. a flex row with `justify-content: flex-end` for action buttons). */
|
|
259
|
-
.footer {
|
|
260
|
-
flex-shrink: 0;
|
|
261
|
-
background: var(--sv-color-surface);
|
|
262
|
-
border-top: var(--sv-border-width-hairline) solid var(--sv-color-border);
|
|
263
|
-
padding: var(--sv-space-3) var(--sv-space-4);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/* Mobile: full-screen sheet (RFC 0001 §3, breakpoint unified to 768px per
|
|
267
|
-
* RFC 0013). Every size fills the scrim's available area (which is already
|
|
268
|
-
* inset from the top by --sv-dialog-inset-top when a fixed header is shown).
|
|
269
|
-
* The panel therefore fills height: 100% of the remaining space, not 100dvh. */
|
|
270
|
-
@media (max-width: 768px) {
|
|
271
|
-
/* On mobile the overlay feels like a full-page push, not a floating modal.
|
|
272
|
-
Remove the dim scrim and panel chrome so it's indistinguishable from a
|
|
273
|
-
regular page render. router.back() still closes it correctly.
|
|
274
|
-
bottom stops the scrim above the footer nav (matching Drawer) instead of
|
|
275
|
-
running the full viewport height — the panel used to extend under the
|
|
276
|
-
footer with only .content's own padding compensating for it. */
|
|
277
|
-
.scrim {
|
|
278
|
-
padding: 0;
|
|
279
|
-
background: transparent;
|
|
280
|
-
bottom: var(--sv-shell-footer-height, 0);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
.panel,
|
|
284
|
-
.sm,
|
|
285
|
-
.md,
|
|
286
|
-
.lg,
|
|
287
|
-
.auto,
|
|
288
|
-
.fixed {
|
|
289
|
-
width: 100%;
|
|
290
|
-
height: 100%;
|
|
291
|
-
min-width: 0;
|
|
292
|
-
max-width: none;
|
|
293
|
-
max-height: none;
|
|
294
|
-
border: none;
|
|
295
|
-
border-radius: 0;
|
|
296
|
-
box-shadow: none;
|
|
297
|
-
background: var(--sv-color-surface);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/* Mobile entrance is a slide-up, not the desktop fade+scale — matches "page
|
|
301
|
-
push" framing above. No opacity change (the panel is opaque full-screen
|
|
302
|
-
content, not a floating box), so only transform needs a transition here. */
|
|
303
|
-
.panel {
|
|
304
|
-
opacity: 1;
|
|
305
|
-
transform: translateY(100%);
|
|
306
|
-
transition: transform var(--sv-motion-duration-base) var(--sv-motion-ease-out);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
.panelOpen {
|
|
310
|
-
transform: translateY(0);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/* Desktop close button is replaced by OverlayHeader on mobile. */
|
|
314
|
-
.close {
|
|
315
|
-
display: none;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/* Title + close button in one solid row, via the shared OverlayHeader
|
|
319
|
-
component. Being a flex sibling before .content means it never scrolls —
|
|
320
|
-
the content area scrolls below it.
|
|
321
|
-
.content itself needs no mobile override here any more: it used to zero
|
|
322
|
-
out padding-top so a plugin's hand-rolled sticky header (rendered as
|
|
323
|
-
.content's own first child, right below OverlayHeader) would sit flush
|
|
324
|
-
against it. That case no longer exists — a plugin with a tab strip/
|
|
325
|
-
secondary nav now hands it to OverlayHeader's own secondRow slot
|
|
326
|
-
(useOverlaySecondRow) instead of rendering it inside .content; Account
|
|
327
|
-
and Console both migrated to this (mobile design-system plan, Phase
|
|
328
|
-
C1b). With .content's first child back to being genuine page content, it
|
|
329
|
-
needs the same breathing room from the header that .content's own base
|
|
330
|
-
padding (var(--sv-space-6) on every side) already provides everywhere
|
|
331
|
-
else. */
|
|
332
|
-
.mobileHeader {
|
|
333
|
-
display: block;
|
|
334
|
-
}
|
|
335
|
-
}
|