@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,324 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { expect, userEvent, within } from 'storybook/test';
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import { Button } from '../Button/Button';
|
|
5
|
-
import { Dialog, useOverlaySecondRow } from './Dialog';
|
|
6
|
-
|
|
7
|
-
// Controlled wrapper so the play function can open/inspect the dialog.
|
|
8
|
-
function DialogDemo({
|
|
9
|
-
size = 'lg',
|
|
10
|
-
label = 'Example dialog',
|
|
11
|
-
}: {
|
|
12
|
-
size?: 'sm' | 'md' | 'lg' | 'auto' | 'fixed';
|
|
13
|
-
label?: string;
|
|
14
|
-
}) {
|
|
15
|
-
const [open, setOpen] = useState(false);
|
|
16
|
-
return (
|
|
17
|
-
<>
|
|
18
|
-
<Button onClick={() => setOpen(true)}>Open {size} dialog</Button>
|
|
19
|
-
<Dialog open={open} onClose={() => setOpen(false)} size={size} aria-label={label}>
|
|
20
|
-
<div style={{ padding: 24, fontFamily: 'system-ui' }}>
|
|
21
|
-
<h2
|
|
22
|
-
style={{
|
|
23
|
-
fontSize: 18,
|
|
24
|
-
fontWeight: 600,
|
|
25
|
-
color: 'var(--sv-color-text-primary)',
|
|
26
|
-
marginBottom: 12,
|
|
27
|
-
}}
|
|
28
|
-
>
|
|
29
|
-
{label}
|
|
30
|
-
</h2>
|
|
31
|
-
<p style={{ color: 'var(--sv-color-text-muted)', marginBottom: 24 }}>
|
|
32
|
-
This is a <strong>{size}</strong> dialog. Press Esc or click the scrim to dismiss.
|
|
33
|
-
</p>
|
|
34
|
-
<Button variant="secondary" onClick={() => setOpen(false)}>
|
|
35
|
-
Close
|
|
36
|
-
</Button>
|
|
37
|
-
</div>
|
|
38
|
-
</Dialog>
|
|
39
|
-
</>
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const meta = {
|
|
44
|
-
title: 'Components/Dialog',
|
|
45
|
-
component: Dialog,
|
|
46
|
-
parameters: {
|
|
47
|
-
layout: 'centered',
|
|
48
|
-
docs: {
|
|
49
|
-
description: {
|
|
50
|
-
component:
|
|
51
|
-
'Modal surface (scrim + panel). Router-agnostic — caller provides `onClose`. Supports Esc, scrim-click, focus trap and focus restoration. Sizes: `sm` / `md` / `lg` / `auto` / `fixed`. `sm`/`md` are fixed-width, content-driven height; `auto` is content-driven on both width and height; `lg` is a true fixed 100%/100% box; `fixed` is also a true fixed box (width and height both set, content never resizes it) but capped at 64rem×44rem rather than filling the viewport. Mobile always renders as a full-screen sheet. Three composition shapes via the optional `header`/`footer` props: Body only (both omitted, the default), Header + Body, Header + Body + Footer — see the stories below the size examples.',
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
} satisfies Meta<typeof Dialog>;
|
|
56
|
-
|
|
57
|
-
export default meta;
|
|
58
|
-
type Story = StoryObj<typeof meta>;
|
|
59
|
-
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
|
|
62
|
-
export const Small: Story = {
|
|
63
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
64
|
-
render: (_args) => <DialogDemo size="sm" label="Small dialog" />,
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export const Medium: Story = {
|
|
68
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
69
|
-
render: (_args) => <DialogDemo size="md" label="Medium dialog" />,
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
export const Large: Story = {
|
|
73
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
74
|
-
render: (_args) => <DialogDemo size="lg" label="Large dialog" />,
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* `fixed` is a true fixed box like `lg` (width AND height both set — content
|
|
79
|
-
* never resizes it) but capped at 64rem×44rem rather than filling the
|
|
80
|
-
* viewport. Added for epic task 14.5 (Account's vertical nav): a plugin
|
|
81
|
-
* whose route tree includes a client-side redirect through a near-empty
|
|
82
|
-
* intermediate page needs a size that won't visibly shrink to fit that empty
|
|
83
|
-
* page and then grow once real content lands — every other size is
|
|
84
|
-
* content-driven on at least one axis and would do exactly that.
|
|
85
|
-
*/
|
|
86
|
-
export const Fixed: Story = {
|
|
87
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
88
|
-
render: (_args) => <DialogDemo size="fixed" label="Fixed dialog" />,
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* `auto` sizes to content on both width and height, unlike `sm`/`md` (fixed
|
|
93
|
-
* width, content-driven height only) — capped, not fixed, on either axis.
|
|
94
|
-
* This demo's own content is deliberately narrower than `md`'s 36rem, so the
|
|
95
|
-
* panel visibly shrinks below it — a fixed-width size can't do that.
|
|
96
|
-
*/
|
|
97
|
-
export const AutoSize: Story = {
|
|
98
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
99
|
-
render: (_args) => {
|
|
100
|
-
function Demo() {
|
|
101
|
-
const [open, setOpen] = useState(false);
|
|
102
|
-
return (
|
|
103
|
-
<>
|
|
104
|
-
<Button onClick={() => setOpen(true)}>Open auto-sized dialog</Button>
|
|
105
|
-
<Dialog open={open} onClose={() => setOpen(false)} size="auto" aria-label="Delete item?">
|
|
106
|
-
<div style={{ padding: 24, fontFamily: 'system-ui', maxWidth: '18rem' }}>
|
|
107
|
-
<h2
|
|
108
|
-
style={{
|
|
109
|
-
fontSize: 18,
|
|
110
|
-
fontWeight: 600,
|
|
111
|
-
color: 'var(--sv-color-text-primary)',
|
|
112
|
-
marginBottom: 12,
|
|
113
|
-
}}
|
|
114
|
-
>
|
|
115
|
-
Delete item?
|
|
116
|
-
</h2>
|
|
117
|
-
<p style={{ color: 'var(--sv-color-text-muted)', marginBottom: 24 }}>
|
|
118
|
-
This panel is narrower than `md`'s fixed 36rem — `auto` shrank to fit this short
|
|
119
|
-
message instead of padding out a fixed width.
|
|
120
|
-
</p>
|
|
121
|
-
<Button variant="secondary" onClick={() => setOpen(false)}>
|
|
122
|
-
Close
|
|
123
|
-
</Button>
|
|
124
|
-
</div>
|
|
125
|
-
</Dialog>
|
|
126
|
-
</>
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
return <Demo />;
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
export const Closed: Story = {
|
|
134
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
135
|
-
render: (_args) => (
|
|
136
|
-
<Dialog open={false} onClose={() => {}} aria-label="Closed dialog">
|
|
137
|
-
<p>Never seen</p>
|
|
138
|
-
</Dialog>
|
|
139
|
-
),
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
/** Play function opens the dialog and asserts it is visible. */
|
|
143
|
-
export const OpenViaInteraction: Story = {
|
|
144
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
145
|
-
render: (_args) => <DialogDemo size="md" label="Interaction test dialog" />,
|
|
146
|
-
play: async ({ canvasElement }) => {
|
|
147
|
-
const canvas = within(canvasElement);
|
|
148
|
-
const trigger = canvas.getByRole('button', { name: /open md dialog/i });
|
|
149
|
-
await userEvent.click(trigger);
|
|
150
|
-
const dialog = canvas.getByRole('dialog');
|
|
151
|
-
await expect(dialog).toBeVisible();
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
// A stand-in for a plugin's own route layout — several component layers below
|
|
156
|
-
// wherever <Dialog> itself is instantiated, exactly like the real
|
|
157
|
-
// AccountLayout/ConsoleLayout usage this hook was built for.
|
|
158
|
-
function NestedTabStrip() {
|
|
159
|
-
const insideOverlay = useOverlaySecondRow(
|
|
160
|
-
<div style={{ display: 'flex', gap: 16, padding: '0 16px' }}>
|
|
161
|
-
{['Profile', 'Security', 'Preferences'].map((tab) => (
|
|
162
|
-
<span key={tab} style={{ fontSize: 14, color: 'var(--sv-color-text-primary)' }}>
|
|
163
|
-
{tab}
|
|
164
|
-
</span>
|
|
165
|
-
))}
|
|
166
|
-
</div>,
|
|
167
|
-
);
|
|
168
|
-
return (
|
|
169
|
-
<p style={{ color: 'var(--sv-color-text-muted)', fontSize: 13 }}>
|
|
170
|
-
useOverlaySecondRow found a Dialog ancestor: <strong>{String(insideOverlay)}</strong>. Switch
|
|
171
|
-
the viewport toolbar to a mobile width to see the tab strip render inside the Dialog's own
|
|
172
|
-
mobile OverlayHeader instead of here.
|
|
173
|
-
</p>
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Demonstrates useOverlaySecondRow — solves the "double header" problem for
|
|
179
|
-
* overlay-shell plugins (Console, Account): a deeply-nested layout hands its
|
|
180
|
-
* tab strip up to the enclosing Dialog's mobile OverlayHeader instead of
|
|
181
|
-
* rendering a second header bar as ordinary content. Only visible at mobile
|
|
182
|
-
* widths, where Dialog's own OverlayHeader takes over; at desktop widths the
|
|
183
|
-
* secondRow prop has no visible effect (OverlayHeader is desktop-hidden).
|
|
184
|
-
*/
|
|
185
|
-
export const WithOverlaySecondRow: Story = {
|
|
186
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
187
|
-
render: (_args) => {
|
|
188
|
-
function Demo() {
|
|
189
|
-
const [open, setOpen] = useState(false);
|
|
190
|
-
return (
|
|
191
|
-
<>
|
|
192
|
-
<Button onClick={() => setOpen(true)}>Open dialog with tab strip</Button>
|
|
193
|
-
<Dialog open={open} onClose={() => setOpen(false)} title="Account" aria-label="Account">
|
|
194
|
-
<div style={{ padding: 24, fontFamily: 'system-ui' }}>
|
|
195
|
-
<NestedTabStrip />
|
|
196
|
-
</div>
|
|
197
|
-
</Dialog>
|
|
198
|
-
</>
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
return <Demo />;
|
|
202
|
-
},
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
// ---------------------------------------------------------------------------
|
|
206
|
-
// Composition shapes (header/footer props) — Body only is every story above
|
|
207
|
-
// this point (both props omitted); these three demonstrate the other two.
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* "Body only" — the default shape (both `header` and `footer` omitted).
|
|
211
|
-
* Included explicitly alongside the size stories above as the baseline the
|
|
212
|
-
* other two composition shapes are compared against: no visible header on
|
|
213
|
-
* desktop, a floating close button instead, and any actions live inside the
|
|
214
|
-
* scrollable body.
|
|
215
|
-
*/
|
|
216
|
-
export const BodyOnly: Story = {
|
|
217
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
218
|
-
render: (_args) => {
|
|
219
|
-
function Demo() {
|
|
220
|
-
const [open, setOpen] = useState(false);
|
|
221
|
-
return (
|
|
222
|
-
<>
|
|
223
|
-
<Button onClick={() => setOpen(true)}>Open body-only dialog</Button>
|
|
224
|
-
<Dialog open={open} onClose={() => setOpen(false)} size="sm" aria-label="Body only">
|
|
225
|
-
<div style={{ padding: 24, fontFamily: 'system-ui' }}>
|
|
226
|
-
<p style={{ color: 'var(--sv-color-text-muted)' }}>
|
|
227
|
-
No `header` or `footer` prop — today's default. Desktop shows only the floating
|
|
228
|
-
close button; actions (if any) live in this scrolling body, same as before this
|
|
229
|
-
task.
|
|
230
|
-
</p>
|
|
231
|
-
</div>
|
|
232
|
-
</Dialog>
|
|
233
|
-
</>
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
return <Demo />;
|
|
237
|
-
},
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* "Header + Body" — the `header` prop renders a persistent title/close row
|
|
242
|
-
* on both desktop and mobile (unlike the plain `title` prop, which is
|
|
243
|
-
* mobile-only). Resize the viewport to confirm the header stays visible and
|
|
244
|
-
* identically styled at both widths.
|
|
245
|
-
*/
|
|
246
|
-
export const HeaderAndBody: Story = {
|
|
247
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
248
|
-
render: (_args) => {
|
|
249
|
-
function Demo() {
|
|
250
|
-
const [open, setOpen] = useState(false);
|
|
251
|
-
return (
|
|
252
|
-
<>
|
|
253
|
-
<Button onClick={() => setOpen(true)}>Open header + body dialog</Button>
|
|
254
|
-
<Dialog
|
|
255
|
-
open={open}
|
|
256
|
-
onClose={() => setOpen(false)}
|
|
257
|
-
size="sm"
|
|
258
|
-
header="Card detail"
|
|
259
|
-
aria-label="Card detail"
|
|
260
|
-
>
|
|
261
|
-
<div style={{ padding: 24, fontFamily: 'system-ui' }}>
|
|
262
|
-
<p style={{ color: 'var(--sv-color-text-muted)' }}>
|
|
263
|
-
The "Card detail" title above is the `header` prop, rendered via the same shared
|
|
264
|
-
header row on both desktop and mobile — resize the viewport to confirm it doesn't
|
|
265
|
-
disappear on desktop the way a plain `title` would.
|
|
266
|
-
</p>
|
|
267
|
-
</div>
|
|
268
|
-
</Dialog>
|
|
269
|
-
</>
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
return <Demo />;
|
|
273
|
-
},
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* "Header + Body + Footer" — both `header` and `footer` are pinned flex
|
|
278
|
-
* siblings around `.content`; only the body between them scrolls. The body
|
|
279
|
-
* here is long enough to actually scroll, so header/footer staying put is
|
|
280
|
-
* visible, not just theoretical — check this at both a desktop and a
|
|
281
|
-
* ≤768px viewport per this task's own review checklist.
|
|
282
|
-
*/
|
|
283
|
-
export const HeaderBodyFooter: Story = {
|
|
284
|
-
args: { open: false, onClose: () => {}, children: null },
|
|
285
|
-
render: (_args) => {
|
|
286
|
-
function Demo() {
|
|
287
|
-
const [open, setOpen] = useState(false);
|
|
288
|
-
return (
|
|
289
|
-
<>
|
|
290
|
-
<Button onClick={() => setOpen(true)}>Open header + body + footer dialog</Button>
|
|
291
|
-
<Dialog
|
|
292
|
-
open={open}
|
|
293
|
-
onClose={() => setOpen(false)}
|
|
294
|
-
size="sm"
|
|
295
|
-
header="Edit card"
|
|
296
|
-
footer={
|
|
297
|
-
<div style={{ display: 'flex', gap: 12, justifyContent: 'flex-end' }}>
|
|
298
|
-
<Button variant="secondary" onClick={() => setOpen(false)}>
|
|
299
|
-
Cancel
|
|
300
|
-
</Button>
|
|
301
|
-
<Button onClick={() => setOpen(false)}>Save</Button>
|
|
302
|
-
</div>
|
|
303
|
-
}
|
|
304
|
-
aria-label="Edit card"
|
|
305
|
-
>
|
|
306
|
-
<div style={{ padding: 24, fontFamily: 'system-ui', display: 'grid', gap: 16 }}>
|
|
307
|
-
<p style={{ color: 'var(--sv-color-text-muted)' }}>
|
|
308
|
-
Scroll this body — the "Edit card" header above and the Cancel/Save footer below
|
|
309
|
-
both stay pinned; only this region between them moves.
|
|
310
|
-
</p>
|
|
311
|
-
{Array.from({ length: 12 }, (_, i) => (
|
|
312
|
-
<p key={i} style={{ color: 'var(--sv-color-text-muted)' }}>
|
|
313
|
-
Field {i + 1} of 12 — filler content long enough to force `.content` to actually
|
|
314
|
-
scroll, so the pinned header/footer behavior is visible rather than theoretical.
|
|
315
|
-
</p>
|
|
316
|
-
))}
|
|
317
|
-
</div>
|
|
318
|
-
</Dialog>
|
|
319
|
-
</>
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
return <Demo />;
|
|
323
|
-
},
|
|
324
|
-
};
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { createContext, type ReactNode, useContext, useEffect, useRef, useState } from 'react';
|
|
4
|
-
import { useMountTransition, usePrefersReducedMotion } from '../../motion';
|
|
5
|
-
import {
|
|
6
|
-
OVERLAY_MOTION_DURATION_MS,
|
|
7
|
-
useOverlayFocusCapture,
|
|
8
|
-
useOverlayKeyboardTrap,
|
|
9
|
-
useOverlayScrollLock,
|
|
10
|
-
} from '../../overlay-shell';
|
|
11
|
-
import { Icon } from '../Icon/Icon';
|
|
12
|
-
import { OverlayHeader } from '../OverlayHeader/OverlayHeader';
|
|
13
|
-
import styles from './Dialog.module.css';
|
|
14
|
-
|
|
15
|
-
// undefined (the default, outside any Provider) means "no Dialog ancestor" —
|
|
16
|
-
// distinct from a real setter function, so useOverlaySecondRow can silently
|
|
17
|
-
// no-op when called outside a Dialog instead of throwing.
|
|
18
|
-
const OverlaySecondRowContext = createContext<((node: ReactNode | null) => void) | undefined>(
|
|
19
|
-
undefined,
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Lets content deep inside a `Dialog` (e.g. a plugin's own route layout,
|
|
24
|
-
* rendered several levels below wherever the `Dialog` itself is
|
|
25
|
-
* instantiated) supply the second-row content of the Dialog's `OverlayHeader`
|
|
26
|
-
* — typically a tab strip. Solves the "double header" problem: without this,
|
|
27
|
-
* a plugin's own tab strip has no way to reach the Dialog's header and ends
|
|
28
|
-
* up rendered a second time, as its own sticky bar, inside the scrolling
|
|
29
|
-
* content area. Reaches the header regardless of whether it's showing via
|
|
30
|
-
* the `header` prop (both breakpoints) or the default `title`-driven mobile
|
|
31
|
-
* bar (mobile only) — see `DialogProps.header`'s own doc comment.
|
|
32
|
-
*
|
|
33
|
-
* A no-op when there is no enclosing `Dialog` (e.g. the same plugin layout
|
|
34
|
-
* also rendered on a plain, non-overlay route) — safe to call unconditionally.
|
|
35
|
-
* Returns whether an enclosing `Dialog` actually received the content, so a
|
|
36
|
-
* caller that also renders its own inline header/tab-strip copy for the
|
|
37
|
-
* no-Dialog case can hide that copy on mobile specifically when this
|
|
38
|
-
* returned `true` (the Dialog's own header is showing it instead there).
|
|
39
|
-
*
|
|
40
|
-
* ```tsx
|
|
41
|
-
* function AccountLayout({ children }) {
|
|
42
|
-
* const insideOverlay = useOverlaySecondRow(<nav>...tab strip...</nav>);
|
|
43
|
-
* return <div>{children}</div>;
|
|
44
|
-
* }
|
|
45
|
-
* ```
|
|
46
|
-
*/
|
|
47
|
-
export function useOverlaySecondRow(node: ReactNode | null): boolean {
|
|
48
|
-
const setSecondRow = useContext(OverlaySecondRowContext);
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
if (!setSecondRow) return;
|
|
51
|
-
setSecondRow(node);
|
|
52
|
-
return () => setSecondRow(null);
|
|
53
|
-
}, [setSecondRow, node]);
|
|
54
|
-
return setSecondRow !== undefined;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// BREAKING (packages/ui minor bump + docs/upgrade.md migration note): `xl`
|
|
58
|
-
// and `full` were removed here — `full` was a dead alias of `lg` (identical
|
|
59
|
-
// CSS), and `xl` was a fixed-width variant with no distinct behavior `auto`
|
|
60
|
-
// doesn't now cover better. `auto` sizes to content on BOTH width and
|
|
61
|
-
// height, capped rather than fixed on either axis — for content whose
|
|
62
|
-
// natural size varies a lot (a card detail modal with an optional
|
|
63
|
-
// checklist/comments section) rather than reliably filling a fixed width.
|
|
64
|
-
// `lg` is a true fixed 100%/100% box — the panel holds still regardless of
|
|
65
|
-
// content, at the cost of always filling the viewport.
|
|
66
|
-
//
|
|
67
|
-
// `fixed` (added for epic task 14.5, Account's vertical nav): a true fixed
|
|
68
|
-
// box like `lg` — width AND height set, content never resizes it — but
|
|
69
|
-
// capped rather than filling the viewport. Named distinctly from the
|
|
70
|
-
// component's own always-applied `.panel` CSS class (Dialog.module.css),
|
|
71
|
-
// not from `lg`'s own fixed-ness. For a plugin that needs a stable
|
|
72
|
-
// footprint (e.g. one whose route tree includes a client-side redirect
|
|
73
|
-
// through a near-empty intermediate page — `auto`/`sm`/`md`'s
|
|
74
|
-
// content-driven sizing would visibly shrink to fit that empty page, then
|
|
75
|
-
// grow once the real content lands) without reading as heavy as `lg`'s
|
|
76
|
-
// full-screen box for what is a compact settings surface.
|
|
77
|
-
export type DialogSize = 'sm' | 'md' | 'lg' | 'auto' | 'fixed';
|
|
78
|
-
|
|
79
|
-
export interface DialogProps {
|
|
80
|
-
/** Whether the dialog is shown. When false, nothing renders. */
|
|
81
|
-
open: boolean;
|
|
82
|
-
/** Called on Esc, scrim click, or the close button. */
|
|
83
|
-
onClose: () => void;
|
|
84
|
-
/** Panel size on desktop. Mobile always renders as a full-screen sheet. */
|
|
85
|
-
size?: DialogSize;
|
|
86
|
-
/** Accessible name for the dialog (sets `aria-label` on the panel). Falls
|
|
87
|
-
* back to `title` when omitted — this still applies even when `header` is
|
|
88
|
-
* used instead of `title` for the visible header (see `header`'s own doc
|
|
89
|
-
* comment), so pass `aria-label` explicitly in that case if `title` is
|
|
90
|
-
* also omitted. */
|
|
91
|
-
'aria-label'?: string;
|
|
92
|
-
/** Shown in the top bar alongside the close button, on mobile only —
|
|
93
|
-
* desktop has no header row by default (see `header` for that). Ignored
|
|
94
|
-
* as visible content when `header` is provided; still used as the
|
|
95
|
-
* `aria-label` fallback either way. */
|
|
96
|
-
title?: string;
|
|
97
|
-
/** Renders a persistent header row (via the same `OverlayHeader` component
|
|
98
|
-
* `title` alone only shows on mobile) on **both** desktop and mobile —
|
|
99
|
-
* the "Header + Body" / "Header + Body + Footer" shapes. Supersedes
|
|
100
|
-
* `title` for visible content when provided; `title` remains the
|
|
101
|
-
* `aria-label` fallback if `aria-label` is also omitted. Omitting both
|
|
102
|
-
* `header` and `footer` is "Body only" — today's default, unchanged. */
|
|
103
|
-
header?: ReactNode;
|
|
104
|
-
/** Renders a persistent footer row below the scrollable body — pinned on
|
|
105
|
-
* both desktop and mobile the same way `header`/the mobile title bar are
|
|
106
|
-
* (a non-scrolling flex sibling, not `position: sticky`): only the region
|
|
107
|
-
* between header and footer scrolls. Typically action buttons (Save/
|
|
108
|
-
* Cancel). Omit for no footer — today's default, where any actions live
|
|
109
|
-
* inside `children` and scroll with the rest of the body. Layout-agnostic
|
|
110
|
-
* (no built-in button alignment) — arrange the footer's own content as
|
|
111
|
-
* needed, same as `children`. */
|
|
112
|
-
footer?: ReactNode;
|
|
113
|
-
/** Forwarded to the active `OverlayHeader` instance's own `rowClassName`
|
|
114
|
-
* (whichever is showing — `header` or the mobile `title` bar) — restyle
|
|
115
|
-
* the title row (e.g. tighter padding to match a consumer's own compact
|
|
116
|
-
* header elsewhere) without changing its title/close layout. */
|
|
117
|
-
rowClassName?: string;
|
|
118
|
-
/** Forwarded to the active `OverlayHeader` instance's own `titleClassName`
|
|
119
|
-
* — restyle the title text (e.g. a smaller font size to match a
|
|
120
|
-
* consumer's own compact header elsewhere). */
|
|
121
|
-
titleClassName?: string;
|
|
122
|
-
children: ReactNode;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Dialog — a modal surface (scrim + panel) for overlay-shell plugins and any
|
|
127
|
-
* plugin that needs a dismissable layer. Router-agnostic: the caller decides
|
|
128
|
-
* what `onClose` does (the runtime's `@modal` slot wires it to `router.back()`).
|
|
129
|
-
*
|
|
130
|
-
* Behaviour: Esc and scrim-click dismiss; focus moves into the panel on open and
|
|
131
|
-
* is restored to the previously-focused element on close; Tab is trapped within
|
|
132
|
-
* the panel. Styling references `--sv-*` tokens only; on mobile the panel becomes
|
|
133
|
-
* a full-screen sheet regardless of `size`.
|
|
134
|
-
*
|
|
135
|
-
* Animated open/close: fade + scale on desktop, slide-up on mobile (matching
|
|
136
|
-
* the "feels like a page push" framing of the mobile sheet). The `open`/
|
|
137
|
-
* `onClose` API is unchanged — closing still stays mounted internally for the
|
|
138
|
-
* exit transition before actually unmounting; `prefers-reduced-motion: reduce`
|
|
139
|
-
* collapses both to near-instant.
|
|
140
|
-
*
|
|
141
|
-
* Three composition shapes, chosen by which of `header`/`footer` are passed:
|
|
142
|
-
* Body only (both omitted — today's default), Header + Body (`header` only),
|
|
143
|
-
* Header + Body + Footer (`header` and `footer`). Whichever of header/footer
|
|
144
|
-
* are present render as non-scrolling flex siblings around `.content`, which
|
|
145
|
-
* stays the only scrollable region in every shape.
|
|
146
|
-
*/
|
|
147
|
-
export function Dialog({
|
|
148
|
-
open,
|
|
149
|
-
onClose,
|
|
150
|
-
size = 'lg',
|
|
151
|
-
'aria-label': ariaLabel,
|
|
152
|
-
title,
|
|
153
|
-
header,
|
|
154
|
-
footer,
|
|
155
|
-
rowClassName,
|
|
156
|
-
titleClassName,
|
|
157
|
-
children,
|
|
158
|
-
}: DialogProps) {
|
|
159
|
-
const panelRef = useRef<HTMLDivElement>(null);
|
|
160
|
-
const reducedMotion = usePrefersReducedMotion();
|
|
161
|
-
const { mounted, phase } = useMountTransition(
|
|
162
|
-
open,
|
|
163
|
-
reducedMotion ? 0 : OVERLAY_MOTION_DURATION_MS,
|
|
164
|
-
);
|
|
165
|
-
const [secondRow, setSecondRow] = useState<ReactNode | null>(null);
|
|
166
|
-
|
|
167
|
-
useOverlayScrollLock(mounted);
|
|
168
|
-
useOverlayFocusCapture(panelRef, open);
|
|
169
|
-
useOverlayKeyboardTrap(panelRef, open, onClose);
|
|
170
|
-
|
|
171
|
-
if (!mounted) return null;
|
|
172
|
-
const isOpenPhase = phase === 'open';
|
|
173
|
-
|
|
174
|
-
return (
|
|
175
|
-
// role="presentation" removes the scrim from the AT (it is purely visual).
|
|
176
|
-
// e.target check lets clicks inside the panel bubble without triggering dismiss.
|
|
177
|
-
// No onKeyDown here — useOverlayKeyboardTrap above already owns Escape via a
|
|
178
|
-
// document-level listener; a second handler here used to double-fire onClose
|
|
179
|
-
// per keypress (the keydown bubbles through this element on its way to
|
|
180
|
-
// document), which is exactly the kind of bug that turns a single Escape
|
|
181
|
-
// press into two router.back() calls for @modal-driven consumers.
|
|
182
|
-
<div
|
|
183
|
-
className={[styles.scrim, isOpenPhase ? styles.scrimOpen : ''].filter(Boolean).join(' ')}
|
|
184
|
-
role="presentation"
|
|
185
|
-
onClick={(e) => {
|
|
186
|
-
if (e.target === e.currentTarget) onClose();
|
|
187
|
-
}}
|
|
188
|
-
>
|
|
189
|
-
<div
|
|
190
|
-
ref={panelRef}
|
|
191
|
-
role="dialog"
|
|
192
|
-
aria-modal="true"
|
|
193
|
-
aria-label={ariaLabel ?? title}
|
|
194
|
-
tabIndex={-1}
|
|
195
|
-
className={[styles.panel, styles[size], isOpenPhase ? styles.panelOpen : '']
|
|
196
|
-
.filter(Boolean)
|
|
197
|
-
.join(' ')}
|
|
198
|
-
>
|
|
199
|
-
{header ? (
|
|
200
|
-
/* header supersedes the mobile-only title bar below — OverlayHeader
|
|
201
|
-
itself has no internal breakpoint gating (see its own module
|
|
202
|
-
CSS), so rendering it with no Dialog-level display-toggling
|
|
203
|
-
className, as here, is what makes it show on both desktop and
|
|
204
|
-
mobile. It carries its own close button, so the separate
|
|
205
|
-
desktop-only .close button below is skipped entirely in this
|
|
206
|
-
branch — never render both at once. */
|
|
207
|
-
<OverlayHeader
|
|
208
|
-
title={header}
|
|
209
|
-
onClose={onClose}
|
|
210
|
-
secondRow={secondRow}
|
|
211
|
-
rowClassName={rowClassName}
|
|
212
|
-
titleClassName={titleClassName}
|
|
213
|
-
/>
|
|
214
|
-
) : (
|
|
215
|
-
<>
|
|
216
|
-
{/* Mobile: shared OverlayHeader (title + close in one row, hidden
|
|
217
|
-
on desktop via CSS — see .mobileHeader). secondRow is
|
|
218
|
-
populated by a descendant's useOverlaySecondRow call, e.g. a
|
|
219
|
-
plugin's own tab strip — see that hook's doc comment for why. */}
|
|
220
|
-
<OverlayHeader
|
|
221
|
-
title={title}
|
|
222
|
-
onClose={onClose}
|
|
223
|
-
secondRow={secondRow}
|
|
224
|
-
className={styles.mobileHeader}
|
|
225
|
-
rowClassName={rowClassName}
|
|
226
|
-
titleClassName={titleClassName}
|
|
227
|
-
/>
|
|
228
|
-
{/* Desktop: absolute close button (hidden on mobile via CSS).
|
|
229
|
-
Plain `x`, matching the mobile OverlayHeader's own close icon
|
|
230
|
-
above it (OverlayHeader.tsx) — a single consistent close
|
|
231
|
-
affordance across breakpoints instead of desktop's own
|
|
232
|
-
separate `circle-x` glyph (the previous choice here).
|
|
233
|
-
Platform-wide: every `Dialog` consumer without a `header`
|
|
234
|
-
gets this, not just the one it was requested against —
|
|
235
|
-
`Dialog` has no per-instance override for its own close
|
|
236
|
-
button. */}
|
|
237
|
-
<button type="button" className={styles.close} aria-label="Close" onClick={onClose}>
|
|
238
|
-
<Icon name="x" size="md" aria-hidden={true} />
|
|
239
|
-
</button>
|
|
240
|
-
</>
|
|
241
|
-
)}
|
|
242
|
-
{/* The panel is a fixed-size box; only this region scrolls, so the
|
|
243
|
-
panel never resizes with its content and the header/close button
|
|
244
|
-
and footer (if present) stay pinned. */}
|
|
245
|
-
<div className={styles.content}>
|
|
246
|
-
<OverlaySecondRowContext.Provider value={setSecondRow}>
|
|
247
|
-
{children}
|
|
248
|
-
</OverlaySecondRowContext.Provider>
|
|
249
|
-
</div>
|
|
250
|
-
{footer && <div className={styles.footer}>{footer}</div>}
|
|
251
|
-
</div>
|
|
252
|
-
</div>
|
|
253
|
-
);
|
|
254
|
-
}
|