@sovereignfs/ui 0.54.0 → 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.
Files changed (473) hide show
  1. package/LICENSE +373 -661
  2. package/NOTICE +8 -0
  3. package/README.md +4 -6
  4. package/dist/Accordion.module.css +1 -1
  5. package/dist/Alert.module.css +1 -1
  6. package/dist/AppsLauncher.module.css +102 -0
  7. package/dist/Avatar.module.css +1 -1
  8. package/dist/Badge.module.css +30 -7
  9. package/dist/BalanceChip.module.css +1 -1
  10. package/dist/Button.module.css +23 -2
  11. package/dist/Card.module.css +7 -1
  12. package/dist/CardTile.module.css +187 -0
  13. package/dist/CheckableListRow.module.css +8 -0
  14. package/dist/Checkbox.module.css +8 -0
  15. package/dist/CodeTextarea.module.css +7 -1
  16. package/dist/Collapsible.module.css +1 -1
  17. package/dist/ColorPicker.module.css +138 -0
  18. package/dist/Combobox.module.css +8 -2
  19. package/dist/Command.module.css +7 -1
  20. package/dist/ConfirmDialog.module.css +8 -2
  21. package/dist/ConsentPrompt.module.css +21 -0
  22. package/dist/DatePicker.module.css +7 -1
  23. package/dist/Dialog.module.css +130 -21
  24. package/dist/DragHandleRow.module.css +6 -0
  25. package/dist/Drawer.module.css +36 -7
  26. package/dist/FileDropzone.module.css +25 -1
  27. package/dist/Header.module.css +68 -0
  28. package/dist/HeaderFooterLayout.module.css +21 -0
  29. package/dist/IconPicker.module.css +15 -5
  30. package/dist/Input.module.css +7 -1
  31. package/dist/Kbd.module.css +1 -1
  32. package/dist/LegalLinks.module.css +9 -2
  33. package/dist/Markdown.module.css +29 -0
  34. package/dist/Menu.module.css +1 -0
  35. package/dist/Message.module.css +10 -1
  36. package/dist/MessageScroller.module.css +12 -1
  37. package/dist/MobileAppsDrawer.module.css +19 -14
  38. package/dist/MobileFooter.module.css +7 -1
  39. package/dist/MobileHeader.module.css +14 -1
  40. package/dist/NavList.module.css +139 -0
  41. package/dist/NavTabs.module.css +8 -2
  42. package/dist/NotificationsPanel.module.css +268 -0
  43. package/dist/OverlayHeader.module.css +1 -1
  44. package/dist/PageContainer.module.css +62 -0
  45. package/dist/PageHeader.module.css +54 -0
  46. package/dist/PageLayout.module.css +51 -0
  47. package/dist/Popover.module.css +1 -1
  48. package/dist/QrCode.module.css +17 -0
  49. package/dist/QuantityStepper.module.css +5 -3
  50. package/dist/RadioGroup.module.css +6 -0
  51. package/dist/Resizable.module.css +3 -3
  52. package/dist/RootLayout.module.css +12 -0
  53. package/dist/SegmentedControl.module.css +7 -1
  54. package/dist/Select.module.css +7 -1
  55. package/dist/Sheet.module.css +20 -2
  56. package/dist/SplitPane.module.css +5 -5
  57. package/dist/StatusBadge.module.css +1 -1
  58. package/dist/StepStrip.module.css +55 -0
  59. package/dist/SuggestionInput.module.css +14 -3
  60. package/dist/SwipableMobileCarousel.module.css +12 -3
  61. package/dist/SwipableMobileCarouselDots.module.css +21 -0
  62. package/dist/SwipeStack.module.css +101 -0
  63. package/dist/SystemBanner.module.css +16 -0
  64. package/dist/Table.module.css +2 -2
  65. package/dist/Tabs.module.css +7 -1
  66. package/dist/TagInput.module.css +8 -2
  67. package/dist/Textarea.module.css +15 -1
  68. package/dist/ThreeColumnLayout.module.css +35 -0
  69. package/dist/Toast.module.css +67 -3
  70. package/dist/Toggle.module.css +7 -0
  71. package/dist/Tooltip.module.css +7 -1
  72. package/dist/UserMenu.module.css +95 -0
  73. package/dist/fonts/OFL.txt +93 -0
  74. package/dist/fonts/hanken-grotesk-cyrillic-ext-wght-normal.woff2 +0 -0
  75. package/dist/fonts/hanken-grotesk-latin-ext-wght-normal.woff2 +0 -0
  76. package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
  77. package/dist/fonts/hanken-grotesk-vietnamese-wght-normal.woff2 +0 -0
  78. package/dist/index.d.ts +1156 -76
  79. package/dist/index.js +4223 -1513
  80. package/dist/tokens/fonts.css +53 -0
  81. package/dist/tokens/primitives.css +23 -12
  82. package/dist/tokens/semantic.css +32 -0
  83. package/dist/tokens/theme-presets.css +33 -0
  84. package/dist/tokens.css +2 -1
  85. package/package.json +46 -19
  86. package/src/__tests__/motion.test.tsx +0 -105
  87. package/src/components/Accordion/Accordion.module.css +0 -3
  88. package/src/components/Accordion/Accordion.stories.tsx +0 -110
  89. package/src/components/Accordion/Accordion.tsx +0 -53
  90. package/src/components/Accordion/__tests__/Accordion.test.tsx +0 -61
  91. package/src/components/Alert/Alert.module.css +0 -62
  92. package/src/components/Alert/Alert.stories.tsx +0 -96
  93. package/src/components/Alert/Alert.tsx +0 -58
  94. package/src/components/Alert/__tests__/Alert.test.tsx +0 -75
  95. package/src/components/AspectRatio/AspectRatio.module.css +0 -15
  96. package/src/components/AspectRatio/AspectRatio.stories.tsx +0 -78
  97. package/src/components/AspectRatio/AspectRatio.tsx +0 -21
  98. package/src/components/AspectRatio/__tests__/AspectRatio.test.tsx +0 -27
  99. package/src/components/Avatar/Avatar.module.css +0 -38
  100. package/src/components/Avatar/Avatar.tsx +0 -42
  101. package/src/components/Badge/Badge.module.css +0 -154
  102. package/src/components/Badge/Badge.stories.tsx +0 -226
  103. package/src/components/Badge/Badge.tsx +0 -81
  104. package/src/components/Badge/__tests__/Badge.test.tsx +0 -88
  105. package/src/components/BalanceChip/BalanceChip.module.css +0 -32
  106. package/src/components/BalanceChip/BalanceChip.stories.tsx +0 -45
  107. package/src/components/BalanceChip/BalanceChip.tsx +0 -33
  108. package/src/components/Breadcrumb/Breadcrumb.module.css +0 -49
  109. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -47
  110. package/src/components/Breadcrumb/Breadcrumb.tsx +0 -57
  111. package/src/components/Breadcrumb/__tests__/Breadcrumb.test.tsx +0 -52
  112. package/src/components/Button/Button.module.css +0 -153
  113. package/src/components/Button/Button.stories.tsx +0 -83
  114. package/src/components/Button/Button.tsx +0 -52
  115. package/src/components/Button/__tests__/Button.test.tsx +0 -66
  116. package/src/components/ButtonGroup/ButtonGroup.module.css +0 -29
  117. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -57
  118. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -27
  119. package/src/components/ButtonGroup/__tests__/ButtonGroup.test.tsx +0 -29
  120. package/src/components/Calendar/Calendar.module.css +0 -126
  121. package/src/components/Calendar/Calendar.tsx +0 -213
  122. package/src/components/Calendar/__tests__/Calendar.test.tsx +0 -98
  123. package/src/components/Calendar/dateUtils.ts +0 -97
  124. package/src/components/Card/Card.module.css +0 -42
  125. package/src/components/Card/Card.tsx +0 -34
  126. package/src/components/CheckableListRow/CheckableListRow.module.css +0 -95
  127. package/src/components/CheckableListRow/CheckableListRow.stories.tsx +0 -99
  128. package/src/components/CheckableListRow/CheckableListRow.tsx +0 -89
  129. package/src/components/Checkbox/Checkbox.module.css +0 -111
  130. package/src/components/Checkbox/Checkbox.tsx +0 -78
  131. package/src/components/CodeTextarea/CodeTextarea.module.css +0 -53
  132. package/src/components/CodeTextarea/CodeTextarea.stories.tsx +0 -77
  133. package/src/components/CodeTextarea/CodeTextarea.tsx +0 -36
  134. package/src/components/Collapsible/Collapsible.module.css +0 -70
  135. package/src/components/Collapsible/Collapsible.stories.tsx +0 -62
  136. package/src/components/Collapsible/Collapsible.tsx +0 -66
  137. package/src/components/Collapsible/__tests__/Collapsible.test.tsx +0 -71
  138. package/src/components/Combobox/Combobox.module.css +0 -122
  139. package/src/components/Combobox/Combobox.stories.tsx +0 -79
  140. package/src/components/Combobox/Combobox.tsx +0 -186
  141. package/src/components/Combobox/__tests__/Combobox.test.tsx +0 -158
  142. package/src/components/Command/Command.module.css +0 -80
  143. package/src/components/Command/Command.stories.tsx +0 -104
  144. package/src/components/Command/Command.tsx +0 -168
  145. package/src/components/Command/__tests__/Command.test.tsx +0 -162
  146. package/src/components/ConfirmDialog/ConfirmDialog.module.css +0 -113
  147. package/src/components/ConfirmDialog/ConfirmDialog.tsx +0 -124
  148. package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +0 -146
  149. package/src/components/ContextMenu/ContextMenu.stories.tsx +0 -81
  150. package/src/components/ContextMenu/ContextMenu.tsx +0 -100
  151. package/src/components/ContextMenu/__tests__/ContextMenu.test.tsx +0 -87
  152. package/src/components/CurrencyInput/CurrencyInput.stories.tsx +0 -50
  153. package/src/components/CurrencyInput/CurrencyInput.tsx +0 -60
  154. package/src/components/DataTable/DataTable.module.css +0 -28
  155. package/src/components/DataTable/DataTable.stories.tsx +0 -74
  156. package/src/components/DataTable/DataTable.tsx +0 -154
  157. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -123
  158. package/src/components/DatePicker/DatePicker.module.css +0 -61
  159. package/src/components/DatePicker/DatePicker.tsx +0 -103
  160. package/src/components/DatePicker/__tests__/DatePicker.test.tsx +0 -89
  161. package/src/components/DeviceOnlyGate/DeviceOnlyGate.tsx +0 -58
  162. package/src/components/DeviceOnlyGate/__tests__/DeviceOnlyGate.test.tsx +0 -45
  163. package/src/components/DeviceStorageKeyGate/DeviceStorageKeyGate.tsx +0 -100
  164. package/src/components/DeviceStorageKeyGate/__tests__/DeviceStorageKeyGate.test.tsx +0 -119
  165. package/src/components/Dialog/Dialog.module.css +0 -226
  166. package/src/components/Dialog/Dialog.stories.tsx +0 -147
  167. package/src/components/Dialog/Dialog.tsx +0 -160
  168. package/src/components/Dialog/__tests__/Dialog.test.tsx +0 -137
  169. package/src/components/DragHandleRow/DragHandleRow.module.css +0 -57
  170. package/src/components/DragHandleRow/DragHandleRow.tsx +0 -61
  171. package/src/components/Drawer/Drawer.module.css +0 -92
  172. package/src/components/Drawer/Drawer.stories.tsx +0 -132
  173. package/src/components/Drawer/Drawer.tsx +0 -176
  174. package/src/components/Drawer/__tests__/Drawer.test.tsx +0 -199
  175. package/src/components/EmptyState/EmptyState.module.css +0 -27
  176. package/src/components/EmptyState/EmptyState.tsx +0 -27
  177. package/src/components/FileDropzone/FileDropzone.module.css +0 -63
  178. package/src/components/FileDropzone/FileDropzone.tsx +0 -109
  179. package/src/components/FileDropzone/__tests__/FileDropzone.test.tsx +0 -67
  180. package/src/components/FormField/FormField.module.css +0 -33
  181. package/src/components/FormField/FormField.tsx +0 -78
  182. package/src/components/FormField/__tests__/FormField.test.tsx +0 -83
  183. package/src/components/HoverCard/HoverCard.module.css +0 -3
  184. package/src/components/HoverCard/HoverCard.stories.tsx +0 -66
  185. package/src/components/HoverCard/HoverCard.tsx +0 -111
  186. package/src/components/HoverCard/__tests__/HoverCard.test.tsx +0 -99
  187. package/src/components/Icon/Icon.module.css +0 -27
  188. package/src/components/Icon/Icon.stories.tsx +0 -95
  189. package/src/components/Icon/Icon.tsx +0 -43
  190. package/src/components/Icon/__tests__/Icon.test.tsx +0 -40
  191. package/src/components/Icon/icons/activity.tsx +0 -20
  192. package/src/components/Icon/icons/alert-triangle.tsx +0 -22
  193. package/src/components/Icon/icons/apple.tsx +0 -21
  194. package/src/components/Icon/icons/banana.tsx +0 -21
  195. package/src/components/Icon/icons/beef.tsx +0 -22
  196. package/src/components/Icon/icons/beer.tsx +0 -24
  197. package/src/components/Icon/icons/bell.tsx +0 -21
  198. package/src/components/Icon/icons/calendar.tsx +0 -23
  199. package/src/components/Icon/icons/candy.tsx +0 -24
  200. package/src/components/Icon/icons/carrot.tsx +0 -22
  201. package/src/components/Icon/icons/check.tsx +0 -20
  202. package/src/components/Icon/icons/chevron-down.tsx +0 -20
  203. package/src/components/Icon/icons/chevron-left.tsx +0 -20
  204. package/src/components/Icon/icons/chevron-right.tsx +0 -20
  205. package/src/components/Icon/icons/chevron-up.tsx +0 -20
  206. package/src/components/Icon/icons/circle-check.tsx +0 -21
  207. package/src/components/Icon/icons/circle-x.tsx +0 -22
  208. package/src/components/Icon/icons/coffee.tsx +0 -23
  209. package/src/components/Icon/icons/cookie.tsx +0 -25
  210. package/src/components/Icon/icons/croissant.tsx +0 -24
  211. package/src/components/Icon/icons/cup-soda.tsx +0 -23
  212. package/src/components/Icon/icons/drumstick.tsx +0 -21
  213. package/src/components/Icon/icons/egg.tsx +0 -20
  214. package/src/components/Icon/icons/ellipsis-vertical.tsx +0 -22
  215. package/src/components/Icon/icons/external-link.tsx +0 -22
  216. package/src/components/Icon/icons/eye-off.tsx +0 -23
  217. package/src/components/Icon/icons/eye.tsx +0 -21
  218. package/src/components/Icon/icons/file.tsx +0 -21
  219. package/src/components/Icon/icons/fish.tsx +0 -25
  220. package/src/components/Icon/icons/grid-2x2.tsx +0 -22
  221. package/src/components/Icon/icons/house.tsx +0 -21
  222. package/src/components/Icon/icons/index.ts +0 -234
  223. package/src/components/Icon/icons/info.tsx +0 -22
  224. package/src/components/Icon/icons/lock.tsx +0 -21
  225. package/src/components/Icon/icons/log-out.tsx +0 -22
  226. package/src/components/Icon/icons/mail.tsx +0 -21
  227. package/src/components/Icon/icons/menu.tsx +0 -22
  228. package/src/components/Icon/icons/milk.tsx +0 -22
  229. package/src/components/Icon/icons/package.tsx +0 -23
  230. package/src/components/Icon/icons/pencil.tsx +0 -21
  231. package/src/components/Icon/icons/pizza.tsx +0 -24
  232. package/src/components/Icon/icons/plus.tsx +0 -21
  233. package/src/components/Icon/icons/rotate-ccw.tsx +0 -21
  234. package/src/components/Icon/icons/salad.tsx +0 -24
  235. package/src/components/Icon/icons/search.tsx +0 -21
  236. package/src/components/Icon/icons/settings.tsx +0 -21
  237. package/src/components/Icon/icons/shield.tsx +0 -20
  238. package/src/components/Icon/icons/shopping-basket.tsx +0 -26
  239. package/src/components/Icon/icons/sliders-horizontal.tsx +0 -28
  240. package/src/components/Icon/icons/smartphone.tsx +0 -21
  241. package/src/components/Icon/icons/snowflake.tsx +0 -31
  242. package/src/components/Icon/icons/spray-can.tsx +0 -29
  243. package/src/components/Icon/icons/trash-2.tsx +0 -24
  244. package/src/components/Icon/icons/upload.tsx +0 -22
  245. package/src/components/Icon/icons/user.tsx +0 -21
  246. package/src/components/Icon/icons/wine.tsx +0 -23
  247. package/src/components/Icon/icons/x.tsx +0 -21
  248. package/src/components/IconPicker/IconPicker.module.css +0 -63
  249. package/src/components/IconPicker/IconPicker.stories.tsx +0 -84
  250. package/src/components/IconPicker/IconPicker.tsx +0 -90
  251. package/src/components/Input/Input.module.css +0 -52
  252. package/src/components/Input/Input.stories.tsx +0 -86
  253. package/src/components/Input/Input.tsx +0 -14
  254. package/src/components/Input/__tests__/Input.test.tsx +0 -22
  255. package/src/components/Item/Item.module.css +0 -70
  256. package/src/components/Item/Item.stories.tsx +0 -62
  257. package/src/components/Item/Item.tsx +0 -54
  258. package/src/components/Item/__tests__/Item.test.tsx +0 -39
  259. package/src/components/Kbd/Kbd.module.css +0 -14
  260. package/src/components/Kbd/Kbd.stories.tsx +0 -32
  261. package/src/components/Kbd/Kbd.tsx +0 -12
  262. package/src/components/Kbd/__tests__/Kbd.test.tsx +0 -14
  263. package/src/components/Label/Label.module.css +0 -11
  264. package/src/components/Label/Label.stories.tsx +0 -40
  265. package/src/components/Label/Label.tsx +0 -24
  266. package/src/components/Label/__tests__/Label.test.tsx +0 -32
  267. package/src/components/LegalLinks/LegalLinks.module.css +0 -24
  268. package/src/components/LegalLinks/LegalLinks.stories.tsx +0 -22
  269. package/src/components/LegalLinks/LegalLinks.tsx +0 -40
  270. package/src/components/Markdown/Markdown.module.css +0 -49
  271. package/src/components/Markdown/Markdown.stories.tsx +0 -30
  272. package/src/components/Markdown/Markdown.tsx +0 -168
  273. package/src/components/Marker/Marker.module.css +0 -33
  274. package/src/components/Marker/Marker.stories.tsx +0 -39
  275. package/src/components/Marker/Marker.tsx +0 -34
  276. package/src/components/Marker/__tests__/Marker.test.tsx +0 -23
  277. package/src/components/MemberMultiSelect/MemberMultiSelect.module.css +0 -27
  278. package/src/components/MemberMultiSelect/MemberMultiSelect.stories.tsx +0 -74
  279. package/src/components/MemberMultiSelect/MemberMultiSelect.tsx +0 -67
  280. package/src/components/Menu/Menu.module.css +0 -89
  281. package/src/components/Menu/Menu.tsx +0 -159
  282. package/src/components/Menu/__tests__/Menu.test.tsx +0 -197
  283. package/src/components/Menubar/Menubar.stories.tsx +0 -52
  284. package/src/components/Menubar/Menubar.tsx +0 -42
  285. package/src/components/Menubar/__tests__/Menubar.test.tsx +0 -45
  286. package/src/components/Message/Message.module.css +0 -99
  287. package/src/components/Message/Message.stories.tsx +0 -79
  288. package/src/components/Message/Message.tsx +0 -41
  289. package/src/components/Message/__tests__/Message.test.tsx +0 -46
  290. package/src/components/MessageScroller/MessageScroller.module.css +0 -54
  291. package/src/components/MessageScroller/MessageScroller.stories.tsx +0 -84
  292. package/src/components/MessageScroller/MessageScroller.tsx +0 -72
  293. package/src/components/MessageScroller/__tests__/MessageScroller.test.tsx +0 -105
  294. package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +0 -81
  295. package/src/components/MobileAppsDrawer/MobileAppsDrawer.tsx +0 -78
  296. package/src/components/MobileAppsDrawer/__tests__/MobileAppsDrawer.test.tsx +0 -80
  297. package/src/components/MobileFooter/MobileFooter.module.css +0 -73
  298. package/src/components/MobileFooter/MobileFooter.stories.tsx +0 -47
  299. package/src/components/MobileFooter/MobileFooter.tsx +0 -109
  300. package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +0 -71
  301. package/src/components/MobileHeader/MobileHeader.module.css +0 -63
  302. package/src/components/MobileHeader/MobileHeader.stories.tsx +0 -57
  303. package/src/components/MobileHeader/MobileHeader.tsx +0 -77
  304. package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +0 -58
  305. package/src/components/NavTabs/NavTabs.module.css +0 -50
  306. package/src/components/NavTabs/NavTabs.tsx +0 -61
  307. package/src/components/NavigationMenu/NavigationMenu.module.css +0 -53
  308. package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -58
  309. package/src/components/NavigationMenu/NavigationMenu.tsx +0 -125
  310. package/src/components/NavigationMenu/__tests__/NavigationMenu.test.tsx +0 -93
  311. package/src/components/OfflineGate/OfflineGate.tsx +0 -44
  312. package/src/components/OfflineGate/__tests__/OfflineGate.test.tsx +0 -66
  313. package/src/components/OverlayHeader/OverlayHeader.module.css +0 -98
  314. package/src/components/OverlayHeader/OverlayHeader.tsx +0 -62
  315. package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +0 -51
  316. package/src/components/PageContainer/PageContainer.module.css +0 -20
  317. package/src/components/PageContainer/PageContainer.tsx +0 -31
  318. package/src/components/PageContainer/__tests__/PageContainer.test.tsx +0 -37
  319. package/src/components/PageHeader/PageHeader.module.css +0 -32
  320. package/src/components/PageHeader/PageHeader.tsx +0 -35
  321. package/src/components/Pagination/Pagination.module.css +0 -98
  322. package/src/components/Pagination/Pagination.stories.tsx +0 -49
  323. package/src/components/Pagination/Pagination.tsx +0 -87
  324. package/src/components/Pagination/__tests__/Pagination.test.tsx +0 -56
  325. package/src/components/Popover/Popover.module.css +0 -74
  326. package/src/components/Popover/Popover.stories.tsx +0 -357
  327. package/src/components/Popover/Popover.tsx +0 -208
  328. package/src/components/Popover/__tests__/Popover.test.tsx +0 -98
  329. package/src/components/Progress/Progress.module.css +0 -20
  330. package/src/components/Progress/Progress.stories.tsx +0 -40
  331. package/src/components/Progress/Progress.tsx +0 -35
  332. package/src/components/Progress/__tests__/Progress.test.tsx +0 -31
  333. package/src/components/QuantityStepper/QuantityStepper.module.css +0 -67
  334. package/src/components/QuantityStepper/QuantityStepper.stories.tsx +0 -79
  335. package/src/components/QuantityStepper/QuantityStepper.tsx +0 -107
  336. package/src/components/RadioGroup/RadioGroup.module.css +0 -88
  337. package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -69
  338. package/src/components/RadioGroup/RadioGroup.tsx +0 -99
  339. package/src/components/RadioGroup/__tests__/RadioGroup.test.tsx +0 -59
  340. package/src/components/Resizable/Resizable.module.css +0 -70
  341. package/src/components/Resizable/Resizable.stories.tsx +0 -82
  342. package/src/components/Resizable/Resizable.tsx +0 -313
  343. package/src/components/Resizable/__tests__/Resizable.test.tsx +0 -128
  344. package/src/components/ResponsiveSurface/ResponsiveSurface.tsx +0 -24
  345. package/src/components/ResponsiveSurface/__tests__/ResponsiveSurface.test.tsx +0 -73
  346. package/src/components/ScrollArea/ScrollArea.module.css +0 -20
  347. package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -57
  348. package/src/components/ScrollArea/ScrollArea.tsx +0 -27
  349. package/src/components/ScrollArea/__tests__/ScrollArea.test.tsx +0 -39
  350. package/src/components/SegmentedControl/SegmentedControl.module.css +0 -55
  351. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -118
  352. package/src/components/SegmentedControl/SegmentedControl.tsx +0 -56
  353. package/src/components/SegmentedControl/__tests__/SegmentedControl.test.tsx +0 -63
  354. package/src/components/Select/Select.module.css +0 -82
  355. package/src/components/Select/Select.stories.tsx +0 -115
  356. package/src/components/Select/Select.tsx +0 -48
  357. package/src/components/Select/__tests__/Select.test.tsx +0 -59
  358. package/src/components/Sheet/Sheet.module.css +0 -55
  359. package/src/components/Sheet/Sheet.tsx +0 -109
  360. package/src/components/Sheet/__tests__/Sheet.test.tsx +0 -99
  361. package/src/components/Slider/Slider.module.css +0 -95
  362. package/src/components/Slider/Slider.stories.tsx +0 -64
  363. package/src/components/Slider/Slider.tsx +0 -77
  364. package/src/components/Slider/__tests__/Slider.test.tsx +0 -45
  365. package/src/components/Spinner/Spinner.module.css +0 -39
  366. package/src/components/Spinner/Spinner.tsx +0 -23
  367. package/src/components/SplitMethodSelector/SplitMethodSelector.stories.tsx +0 -33
  368. package/src/components/SplitMethodSelector/SplitMethodSelector.tsx +0 -43
  369. package/src/components/SplitPane/SplitPane.module.css +0 -85
  370. package/src/components/SplitPane/SplitPane.stories.tsx +0 -160
  371. package/src/components/SplitPane/SplitPane.tsx +0 -149
  372. package/src/components/SplitPane/__tests__/SplitPane.test.tsx +0 -51
  373. package/src/components/StatusBadge/StatusBadge.module.css +0 -59
  374. package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -74
  375. package/src/components/StatusBadge/StatusBadge.tsx +0 -65
  376. package/src/components/SuggestionInput/SuggestionInput.module.css +0 -103
  377. package/src/components/SuggestionInput/SuggestionInput.stories.tsx +0 -144
  378. package/src/components/SuggestionInput/SuggestionInput.tsx +0 -207
  379. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +0 -55
  380. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +0 -227
  381. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlide.tsx +0 -35
  382. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody.tsx +0 -42
  383. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideFooter.tsx +0 -18
  384. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader.tsx +0 -21
  385. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideParts.module.css +0 -29
  386. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +0 -133
  387. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarouselDevGuard.test.tsx +0 -61
  388. package/src/components/SwipableMobileCarousel/context.ts +0 -13
  389. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +0 -49
  390. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +0 -62
  391. package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +0 -63
  392. package/src/components/SystemBanner/SystemBanner.module.css +0 -69
  393. package/src/components/SystemBanner/SystemBanner.stories.tsx +0 -86
  394. package/src/components/SystemBanner/SystemBanner.tsx +0 -50
  395. package/src/components/SystemBanner/__tests__/SystemBanner.test.tsx +0 -50
  396. package/src/components/Table/Table.module.css +0 -45
  397. package/src/components/Table/Table.stories.tsx +0 -125
  398. package/src/components/Table/Table.tsx +0 -51
  399. package/src/components/Table/__tests__/Table.test.tsx +0 -50
  400. package/src/components/Tabs/Tabs.module.css +0 -56
  401. package/src/components/Tabs/Tabs.stories.tsx +0 -100
  402. package/src/components/Tabs/Tabs.tsx +0 -46
  403. package/src/components/Tabs/__tests__/Tabs.test.tsx +0 -45
  404. package/src/components/TagInput/TagInput.module.css +0 -141
  405. package/src/components/TagInput/TagInput.stories.tsx +0 -109
  406. package/src/components/TagInput/TagInput.tsx +0 -174
  407. package/src/components/TagInput/__tests__/TagInput.test.tsx +0 -69
  408. package/src/components/Textarea/Textarea.module.css +0 -39
  409. package/src/components/Textarea/Textarea.tsx +0 -15
  410. package/src/components/Textarea/__tests__/Textarea.test.tsx +0 -29
  411. package/src/components/Toast/Toast.module.css +0 -132
  412. package/src/components/Toast/Toast.stories.tsx +0 -191
  413. package/src/components/Toast/Toast.tsx +0 -139
  414. package/src/components/Toggle/Toggle.module.css +0 -57
  415. package/src/components/Toggle/Toggle.stories.tsx +0 -95
  416. package/src/components/Toggle/Toggle.tsx +0 -39
  417. package/src/components/Toggle/__tests__/Toggle.test.tsx +0 -47
  418. package/src/components/Tooltip/Tooltip.module.css +0 -56
  419. package/src/components/Tooltip/Tooltip.tsx +0 -30
  420. package/src/components/Typography/Typography.module.css +0 -47
  421. package/src/components/Typography/Typography.stories.tsx +0 -62
  422. package/src/components/Typography/Typography.tsx +0 -30
  423. package/src/components/Typography/__tests__/Typography.test.tsx +0 -34
  424. package/src/css-modules.d.ts +0 -4
  425. package/src/hooks/__tests__/useCarouselRouteSync.test.tsx +0 -126
  426. package/src/hooks/__tests__/useDoubleTap.test.tsx +0 -117
  427. package/src/hooks/__tests__/useIsMobile.test.tsx +0 -80
  428. package/src/hooks/__tests__/useIsOffline.test.tsx +0 -53
  429. package/src/hooks/__tests__/useLongPress.test.tsx +0 -158
  430. package/src/hooks/__tests__/useOfflineTileState.test.tsx +0 -69
  431. package/src/hooks/__tests__/useResponsiveLayout.test.tsx +0 -87
  432. package/src/hooks/__tests__/useSnapCarousel.test.tsx +0 -93
  433. package/src/hooks/__tests__/useSwipeReveal.test.tsx +0 -110
  434. package/src/hooks/index.ts +0 -24
  435. package/src/hooks/useCarouselRouteSync.ts +0 -92
  436. package/src/hooks/useCommitOnEnterOrBlur.ts +0 -39
  437. package/src/hooks/useDoubleTap.ts +0 -91
  438. package/src/hooks/useIsMobile.ts +0 -33
  439. package/src/hooks/useIsOffline.ts +0 -41
  440. package/src/hooks/useLongPress.ts +0 -185
  441. package/src/hooks/useOfflineTileState.ts +0 -45
  442. package/src/hooks/useResponsiveLayout.ts +0 -36
  443. package/src/hooks/useSnapCarousel.ts +0 -79
  444. package/src/hooks/useSwipeReveal.ts +0 -107
  445. package/src/index.ts +0 -251
  446. package/src/motion.ts +0 -78
  447. package/src/overlay-shell.ts +0 -94
  448. package/src/scroll-lock.ts +0 -22
  449. package/src/stories/Avatar.stories.tsx +0 -44
  450. package/src/stories/Card.stories.tsx +0 -35
  451. package/src/stories/Checkbox.stories.tsx +0 -45
  452. package/src/stories/DesignSystemOverview.stories.tsx +0 -3187
  453. package/src/stories/DeviceOnlyGate.stories.tsx +0 -35
  454. package/src/stories/DeviceStorageKeyGate.stories.tsx +0 -57
  455. package/src/stories/DragHandleRow.stories.tsx +0 -41
  456. package/src/stories/EmptyState.stories.tsx +0 -33
  457. package/src/stories/FileDropzone.stories.tsx +0 -69
  458. package/src/stories/FormField.stories.tsx +0 -47
  459. package/src/stories/InteractionHooks.stories.tsx +0 -925
  460. package/src/stories/MobilePatterns.stories.tsx +0 -1536
  461. package/src/stories/NavTabs.stories.tsx +0 -53
  462. package/src/stories/OfflineGate.stories.tsx +0 -42
  463. package/src/stories/PageContainer.stories.tsx +0 -37
  464. package/src/stories/PageHeader.stories.tsx +0 -42
  465. package/src/stories/ResponsiveSurface.stories.tsx +0 -47
  466. package/src/stories/Spinner.stories.tsx +0 -25
  467. package/src/stories/SwipableMobileCarousel.stories.tsx +0 -304
  468. package/src/stories/Textarea.stories.tsx +0 -51
  469. package/src/stories/TokenGallery.stories.tsx +0 -602
  470. package/src/stories/Tooltip.stories.tsx +0 -59
  471. package/src/tokens/primitives.css +0 -157
  472. package/src/tokens/semantic.css +0 -130
  473. package/src/tokens.css +0 -5
@@ -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,226 +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
- * Each size is a FIXED box (width AND height) — the panel never grows or
5
- * shrinks with its content, so switching views inside it (e.g. overlay-plugin
6
- * tabs) keeps the dialog the exact same size. Overflow scrolls inside `.content`
7
- * while the panel and its close button stay put. The scrim's padding is the
8
- * fixed margin `lg` leaves around the viewport; `sm`/`md` are centered and cap
9
- * to that available space on short screens. On mobile every size becomes a
10
- * full-screen sheet.
11
- *
12
- * `--sv-dialog-inset-left` lets a host inset the scrim past a fixed left nav
13
- * rail (e.g. the platform sidebar) so the overlay's left margin is measured
14
- * from the rail, not the viewport edge, and the rail stays visible/usable.
15
- * `--sv-dialog-inset-top` (RFC 0013) mirrors this on the vertical axis: the
16
- * shell sets it to the mobile header height so the header stays visible and
17
- * interactive above the dialog sheet. Defaults to 0 for standalone use. */
18
-
19
- .scrim {
20
- position: fixed;
21
- top: var(--sv-dialog-inset-top, 0);
22
- right: 0;
23
- bottom: 0;
24
- left: 0;
25
- z-index: 100;
26
- display: flex;
27
- align-items: center;
28
- justify-content: center;
29
- /* left edge always 0 so the backdrop covers the full viewport incl. sidebar.
30
- padding-left offsets the panel's available area to start at the rail edge. */
31
- padding: var(--sv-space-8);
32
- padding-left: calc(var(--sv-dialog-inset-left, 0px) + var(--sv-space-8));
33
- background: var(--sv-color-scrim);
34
- /* Entrance/exit fade. The Dialog component drives this via a two-phase
35
- mount (see motion.ts) — .scrimOpen is added one frame after mount so this
36
- transition has somewhere to animate from, and removed (while staying
37
- mounted) for the exit before the component actually unmounts. */
38
- opacity: 0;
39
- transition: opacity var(--sv-motion-duration-base) var(--sv-motion-ease-out);
40
- }
41
-
42
- .scrimOpen {
43
- opacity: 1;
44
- }
45
-
46
- .panel {
47
- position: relative;
48
- display: flex;
49
- flex-direction: column;
50
- overflow: hidden;
51
- background: var(--sv-color-surface-raised);
52
- color: var(--sv-color-text-primary);
53
- border: 1px solid var(--sv-color-border);
54
- border-radius: var(--sv-radius-lg);
55
- box-shadow: var(--sv-shadow-overlay);
56
- /* Desktop entrance: fade + gentle scale-up. Same two-phase-mount pattern as
57
- .scrim above. Mobile overrides this to a slide-up instead (below). */
58
- opacity: 0;
59
- transform: scale(0.96);
60
- transition:
61
- opacity var(--sv-motion-duration-base) var(--sv-motion-ease-out),
62
- transform var(--sv-motion-duration-base) var(--sv-motion-ease-out);
63
- }
64
-
65
- .panelOpen {
66
- opacity: 1;
67
- transform: scale(1);
68
- }
69
-
70
- /* prefers-reduced-motion: collapse both fade/scale and slide to near-instant.
71
- Not literally 0 — a 0ms transition can skip applying entirely in some
72
- engines, and the JS unmount timer (Dialog.tsx's MOTION_DURATION_MS,
73
- switched to ~0 via usePrefersReducedMotion) needs a transition to still be
74
- "present" for the visual state to actually reach its end value in time. */
75
- @media (prefers-reduced-motion: reduce) {
76
- .scrim,
77
- .panel {
78
- transition-duration: 0.01ms;
79
- }
80
- }
81
-
82
- /* Sizing audit: reviewed padding/radius against this scale's other
83
- surfaces. --sv-radius-lg (shared with Card via .panel below) left
84
- unchanged for the same blast-radius reason as Card.module.css. */
85
- .content {
86
- flex: 1 1 auto;
87
- overflow-y: auto;
88
- overflow-x: hidden;
89
- padding: var(--sv-space-6);
90
- /* Disable elastic overscroll within the dialog: `none` stops both scroll-
91
- chaining to the parent and the iOS rubber-band bounce inside the panel.
92
- `contain` only prevents chaining — the panel itself still bounces, which
93
- reveals white panel-background between OverlayHeader and the sticky tab
94
- strip on iOS PWA. A dialog is a bounded surface where bounce is a visual
95
- bug, not a feature. */
96
- overscroll-behavior: none;
97
- }
98
-
99
- /* Fixed sizes. `max-*: 100%` caps to the scrim's content box (viewport minus
100
- * margin) so a size never overflows a small viewport. */
101
- .sm {
102
- width: 24rem;
103
- height: 28rem;
104
- max-width: 100%;
105
- max-height: 100%;
106
- }
107
-
108
- .md {
109
- width: 36rem;
110
- height: 42rem;
111
- max-width: 100%;
112
- max-height: 100%;
113
- }
114
-
115
- .lg,
116
- .full {
117
- width: 100%;
118
- height: 100%;
119
- }
120
-
121
- .close {
122
- position: absolute;
123
- top: var(--sv-space-3);
124
- right: var(--sv-space-3);
125
- z-index: 1;
126
- display: inline-flex;
127
- align-items: center;
128
- justify-content: center;
129
- width: var(--sv-space-8);
130
- height: var(--sv-space-8);
131
- border: none;
132
- border-radius: var(--sv-radius-md);
133
- background: transparent;
134
- color: var(--sv-color-text-muted);
135
- font-size: var(--sv-font-size-xl);
136
- line-height: 1;
137
- cursor: pointer;
138
- }
139
-
140
- @media (hover: hover) {
141
- .close:hover {
142
- background: var(--sv-color-surface-sunken);
143
- color: var(--sv-color-text-primary);
144
- }
145
- }
146
-
147
- .close:focus-visible {
148
- outline: 2px solid var(--sv-color-focus-ring);
149
- outline-offset: 2px;
150
- }
151
-
152
- /* Hidden on desktop; shown only on mobile where it replaces the close button.
153
- * OverlayHeader owns its own background/border/padding — this wrapper class
154
- * only toggles visibility per breakpoint. */
155
- .mobileHeader {
156
- display: none;
157
- }
158
-
159
- /* Mobile: full-screen sheet (RFC 0001 §3, breakpoint unified to 768px per
160
- * RFC 0013). Every size fills the scrim's available area (which is already
161
- * inset from the top by --sv-dialog-inset-top when a fixed header is shown).
162
- * The panel therefore fills height: 100% of the remaining space, not 100dvh. */
163
- @media (max-width: 768px) {
164
- /* On mobile the overlay feels like a full-page push, not a floating modal.
165
- Remove the dim scrim and panel chrome so it's indistinguishable from a
166
- regular page render. router.back() still closes it correctly.
167
- bottom stops the scrim above the footer nav (matching Drawer) instead of
168
- running the full viewport height — the panel used to extend under the
169
- footer with only .content's own padding compensating for it. */
170
- .scrim {
171
- padding: 0;
172
- background: transparent;
173
- bottom: var(--sv-shell-footer-height, 0);
174
- }
175
-
176
- .panel,
177
- .sm,
178
- .md,
179
- .lg,
180
- .full {
181
- width: 100%;
182
- height: 100%;
183
- max-width: none;
184
- max-height: none;
185
- border: none;
186
- border-radius: 0;
187
- box-shadow: none;
188
- background: var(--sv-color-surface);
189
- }
190
-
191
- /* Mobile entrance is a slide-up, not the desktop fade+scale — matches "page
192
- push" framing above. No opacity change (the panel is opaque full-screen
193
- content, not a floating box), so only transform needs a transition here. */
194
- .panel {
195
- opacity: 1;
196
- transform: translateY(100%);
197
- transition: transform var(--sv-motion-duration-base) var(--sv-motion-ease-out);
198
- }
199
-
200
- .panelOpen {
201
- transform: translateY(0);
202
- }
203
-
204
- /* Desktop close button is replaced by OverlayHeader on mobile. */
205
- .close {
206
- display: none;
207
- }
208
-
209
- /* Title + close button in one solid row, via the shared OverlayHeader
210
- component. Being a flex sibling before .content means it never scrolls —
211
- the content area scrolls below it.
212
- .content itself needs no mobile override here any more: it used to zero
213
- out padding-top so a plugin's hand-rolled sticky header (rendered as
214
- .content's own first child, right below OverlayHeader) would sit flush
215
- against it. That case no longer exists — a plugin with a tab strip/
216
- secondary nav now hands it to OverlayHeader's own secondRow slot
217
- (useOverlaySecondRow) instead of rendering it inside .content; Account
218
- and Console both migrated to this (mobile design-system plan, Phase
219
- C1b). With .content's first child back to being genuine page content, it
220
- needs the same breathing room from the header that .content's own base
221
- padding (var(--sv-space-6) on every side) already provides everywhere
222
- else. */
223
- .mobileHeader {
224
- display: block;
225
- }
226
- }
@@ -1,147 +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' | 'full';
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` / `full`. Mobile always renders as a full-screen sheet.',
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
- export const Closed: Story = {
78
- args: { open: false, onClose: () => {}, children: null },
79
- render: (_args) => (
80
- <Dialog open={false} onClose={() => {}} aria-label="Closed dialog">
81
- <p>Never seen</p>
82
- </Dialog>
83
- ),
84
- };
85
-
86
- /** Play function opens the dialog and asserts it is visible. */
87
- export const OpenViaInteraction: Story = {
88
- args: { open: false, onClose: () => {}, children: null },
89
- render: (_args) => <DialogDemo size="md" label="Interaction test dialog" />,
90
- play: async ({ canvasElement }) => {
91
- const canvas = within(canvasElement);
92
- const trigger = canvas.getByRole('button', { name: /open md dialog/i });
93
- await userEvent.click(trigger);
94
- const dialog = canvas.getByRole('dialog');
95
- await expect(dialog).toBeVisible();
96
- },
97
- };
98
-
99
- // A stand-in for a plugin's own route layout — several component layers below
100
- // wherever <Dialog> itself is instantiated, exactly like the real
101
- // AccountLayout/ConsoleLayout usage this hook was built for.
102
- function NestedTabStrip() {
103
- const insideOverlay = useOverlaySecondRow(
104
- <div style={{ display: 'flex', gap: 16, padding: '0 16px' }}>
105
- {['Profile', 'Security', 'Preferences'].map((tab) => (
106
- <span key={tab} style={{ fontSize: 14, color: 'var(--sv-color-text-primary)' }}>
107
- {tab}
108
- </span>
109
- ))}
110
- </div>,
111
- );
112
- return (
113
- <p style={{ color: 'var(--sv-color-text-muted)', fontSize: 13 }}>
114
- useOverlaySecondRow found a Dialog ancestor: <strong>{String(insideOverlay)}</strong>. Switch
115
- the viewport toolbar to a mobile width to see the tab strip render inside the Dialog's own
116
- mobile OverlayHeader instead of here.
117
- </p>
118
- );
119
- }
120
-
121
- /**
122
- * Demonstrates useOverlaySecondRow — solves the "double header" problem for
123
- * overlay-shell plugins (Console, Account): a deeply-nested layout hands its
124
- * tab strip up to the enclosing Dialog's mobile OverlayHeader instead of
125
- * rendering a second header bar as ordinary content. Only visible at mobile
126
- * widths, where Dialog's own OverlayHeader takes over; at desktop widths the
127
- * secondRow prop has no visible effect (OverlayHeader is desktop-hidden).
128
- */
129
- export const WithOverlaySecondRow: Story = {
130
- args: { open: false, onClose: () => {}, children: null },
131
- render: (_args) => {
132
- function Demo() {
133
- const [open, setOpen] = useState(false);
134
- return (
135
- <>
136
- <Button onClick={() => setOpen(true)}>Open dialog with tab strip</Button>
137
- <Dialog open={open} onClose={() => setOpen(false)} title="Account" aria-label="Account">
138
- <div style={{ padding: 24, fontFamily: 'system-ui' }}>
139
- <NestedTabStrip />
140
- </div>
141
- </Dialog>
142
- </>
143
- );
144
- }
145
- return <Demo />;
146
- },
147
- };