@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.
Files changed (556) hide show
  1. package/LICENSE +373 -661
  2. package/NOTICE +8 -0
  3. package/README.md +4 -6
  4. package/dist/AppsLauncher.module.css +6 -0
  5. package/dist/Button.module.css +5 -0
  6. package/dist/Card.module.css +6 -0
  7. package/dist/CardTile.module.css +6 -0
  8. package/dist/CheckableListRow.module.css +8 -0
  9. package/dist/Checkbox.module.css +8 -0
  10. package/dist/CodeTextarea.module.css +6 -0
  11. package/dist/ColorPicker.module.css +6 -0
  12. package/dist/Combobox.module.css +6 -0
  13. package/dist/Command.module.css +6 -0
  14. package/dist/ConfirmDialog.module.css +6 -0
  15. package/dist/DatePicker.module.css +6 -0
  16. package/dist/Dialog.module.css +1 -1
  17. package/dist/DragHandleRow.module.css +6 -0
  18. package/dist/FileDropzone.module.css +25 -1
  19. package/dist/Header.module.css +6 -0
  20. package/dist/IconPicker.module.css +14 -4
  21. package/dist/Input.module.css +6 -0
  22. package/dist/LegalLinks.module.css +9 -2
  23. package/dist/Markdown.module.css +5 -0
  24. package/dist/Message.module.css +9 -0
  25. package/dist/MobileAppsDrawer.module.css +9 -5
  26. package/dist/MobileFooter.module.css +6 -0
  27. package/dist/NavList.module.css +11 -2
  28. package/dist/NavTabs.module.css +7 -1
  29. package/dist/NotificationsPanel.module.css +10 -0
  30. package/dist/QrCode.module.css +17 -0
  31. package/dist/QuantityStepper.module.css +4 -2
  32. package/dist/RadioGroup.module.css +6 -0
  33. package/dist/SegmentedControl.module.css +6 -0
  34. package/dist/Select.module.css +6 -0
  35. package/dist/Sheet.module.css +16 -1
  36. package/dist/SplitPane.module.css +1 -1
  37. package/dist/StepStrip.module.css +5 -3
  38. package/dist/SuggestionInput.module.css +12 -1
  39. package/dist/SwipableMobileCarouselDots.module.css +6 -0
  40. package/dist/SystemBanner.module.css +6 -0
  41. package/dist/Tabs.module.css +6 -0
  42. package/dist/TagInput.module.css +6 -0
  43. package/dist/Textarea.module.css +6 -0
  44. package/dist/Toast.module.css +5 -0
  45. package/dist/Toggle.module.css +7 -0
  46. package/dist/Tooltip.module.css +6 -0
  47. package/dist/UserMenu.module.css +5 -0
  48. package/dist/fonts/OFL.txt +93 -0
  49. package/dist/fonts/hanken-grotesk-cyrillic-ext-wght-normal.woff2 +0 -0
  50. package/dist/fonts/hanken-grotesk-latin-ext-wght-normal.woff2 +0 -0
  51. package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
  52. package/dist/fonts/hanken-grotesk-vietnamese-wght-normal.woff2 +0 -0
  53. package/dist/index.d.ts +121 -43
  54. package/dist/index.js +1410 -1152
  55. package/dist/tokens/fonts.css +53 -0
  56. package/dist/tokens/primitives.css +12 -12
  57. package/dist/tokens.css +2 -1
  58. package/package.json +24 -13
  59. package/src/__tests__/motion.test.tsx +0 -105
  60. package/src/__tests__/package-json.test.ts +0 -8
  61. package/src/components/Accordion/Accordion.module.css +0 -3
  62. package/src/components/Accordion/Accordion.stories.tsx +0 -110
  63. package/src/components/Accordion/Accordion.tsx +0 -53
  64. package/src/components/Accordion/__tests__/Accordion.test.tsx +0 -61
  65. package/src/components/Alert/Alert.module.css +0 -62
  66. package/src/components/Alert/Alert.stories.tsx +0 -96
  67. package/src/components/Alert/Alert.tsx +0 -58
  68. package/src/components/Alert/__tests__/Alert.test.tsx +0 -75
  69. package/src/components/AppsLauncher/AppsLauncher.module.css +0 -96
  70. package/src/components/AppsLauncher/AppsLauncher.stories.tsx +0 -58
  71. package/src/components/AppsLauncher/AppsLauncher.tsx +0 -117
  72. package/src/components/AppsLauncher/__tests__/AppsLauncher.test.tsx +0 -52
  73. package/src/components/AspectRatio/AspectRatio.module.css +0 -15
  74. package/src/components/AspectRatio/AspectRatio.stories.tsx +0 -78
  75. package/src/components/AspectRatio/AspectRatio.tsx +0 -21
  76. package/src/components/AspectRatio/__tests__/AspectRatio.test.tsx +0 -27
  77. package/src/components/Avatar/Avatar.module.css +0 -38
  78. package/src/components/Avatar/Avatar.tsx +0 -42
  79. package/src/components/Badge/Badge.module.css +0 -177
  80. package/src/components/Badge/Badge.stories.tsx +0 -238
  81. package/src/components/Badge/Badge.tsx +0 -84
  82. package/src/components/Badge/__tests__/Badge.test.tsx +0 -90
  83. package/src/components/BalanceChip/BalanceChip.module.css +0 -32
  84. package/src/components/BalanceChip/BalanceChip.stories.tsx +0 -45
  85. package/src/components/BalanceChip/BalanceChip.tsx +0 -33
  86. package/src/components/Breadcrumb/Breadcrumb.module.css +0 -49
  87. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -47
  88. package/src/components/Breadcrumb/Breadcrumb.tsx +0 -57
  89. package/src/components/Breadcrumb/__tests__/Breadcrumb.test.tsx +0 -52
  90. package/src/components/Button/Button.module.css +0 -169
  91. package/src/components/Button/Button.stories.tsx +0 -83
  92. package/src/components/Button/Button.tsx +0 -52
  93. package/src/components/Button/__tests__/Button.test.tsx +0 -66
  94. package/src/components/ButtonGroup/ButtonGroup.module.css +0 -29
  95. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -57
  96. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -27
  97. package/src/components/ButtonGroup/__tests__/ButtonGroup.test.tsx +0 -29
  98. package/src/components/Calendar/Calendar.module.css +0 -126
  99. package/src/components/Calendar/Calendar.tsx +0 -213
  100. package/src/components/Calendar/__tests__/Calendar.test.tsx +0 -98
  101. package/src/components/Calendar/dateUtils.ts +0 -97
  102. package/src/components/Card/Card.module.css +0 -42
  103. package/src/components/Card/Card.tsx +0 -34
  104. package/src/components/CardTile/CardTile.module.css +0 -181
  105. package/src/components/CardTile/CardTile.stories.tsx +0 -86
  106. package/src/components/CardTile/CardTile.tsx +0 -128
  107. package/src/components/CardTile/__tests__/CardTile.test.tsx +0 -56
  108. package/src/components/CheckableListRow/CheckableListRow.module.css +0 -95
  109. package/src/components/CheckableListRow/CheckableListRow.stories.tsx +0 -99
  110. package/src/components/CheckableListRow/CheckableListRow.tsx +0 -89
  111. package/src/components/Checkbox/Checkbox.module.css +0 -111
  112. package/src/components/Checkbox/Checkbox.tsx +0 -78
  113. package/src/components/CodeTextarea/CodeTextarea.module.css +0 -53
  114. package/src/components/CodeTextarea/CodeTextarea.stories.tsx +0 -77
  115. package/src/components/CodeTextarea/CodeTextarea.tsx +0 -36
  116. package/src/components/Collapsible/Collapsible.module.css +0 -70
  117. package/src/components/Collapsible/Collapsible.stories.tsx +0 -62
  118. package/src/components/Collapsible/Collapsible.tsx +0 -66
  119. package/src/components/Collapsible/__tests__/Collapsible.test.tsx +0 -71
  120. package/src/components/ColorPicker/ColorPicker.module.css +0 -132
  121. package/src/components/ColorPicker/ColorPicker.stories.tsx +0 -80
  122. package/src/components/ColorPicker/ColorPicker.tsx +0 -157
  123. package/src/components/ColorPicker/__tests__/ColorPicker.test.tsx +0 -117
  124. package/src/components/Combobox/Combobox.module.css +0 -122
  125. package/src/components/Combobox/Combobox.stories.tsx +0 -79
  126. package/src/components/Combobox/Combobox.tsx +0 -186
  127. package/src/components/Combobox/__tests__/Combobox.test.tsx +0 -158
  128. package/src/components/Command/Command.module.css +0 -80
  129. package/src/components/Command/Command.stories.tsx +0 -104
  130. package/src/components/Command/Command.tsx +0 -168
  131. package/src/components/Command/__tests__/Command.test.tsx +0 -162
  132. package/src/components/ConfirmDialog/ConfirmDialog.module.css +0 -113
  133. package/src/components/ConfirmDialog/ConfirmDialog.tsx +0 -150
  134. package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +0 -214
  135. package/src/components/ConsentPrompt/ConsentPrompt.module.css +0 -21
  136. package/src/components/ConsentPrompt/ConsentPrompt.stories.tsx +0 -31
  137. package/src/components/ConsentPrompt/ConsentPrompt.tsx +0 -66
  138. package/src/components/ContextMenu/ContextMenu.stories.tsx +0 -81
  139. package/src/components/ContextMenu/ContextMenu.tsx +0 -100
  140. package/src/components/ContextMenu/__tests__/ContextMenu.test.tsx +0 -87
  141. package/src/components/CurrencyInput/CurrencyInput.stories.tsx +0 -50
  142. package/src/components/CurrencyInput/CurrencyInput.tsx +0 -60
  143. package/src/components/DataTable/DataTable.module.css +0 -28
  144. package/src/components/DataTable/DataTable.stories.tsx +0 -74
  145. package/src/components/DataTable/DataTable.tsx +0 -154
  146. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -123
  147. package/src/components/DatePicker/DatePicker.module.css +0 -61
  148. package/src/components/DatePicker/DatePicker.tsx +0 -103
  149. package/src/components/DatePicker/__tests__/DatePicker.test.tsx +0 -89
  150. package/src/components/DeviceOnlyGate/DeviceOnlyGate.tsx +0 -58
  151. package/src/components/DeviceOnlyGate/__tests__/DeviceOnlyGate.test.tsx +0 -45
  152. package/src/components/DeviceStorageKeyGate/DeviceStorageKeyGate.tsx +0 -100
  153. package/src/components/DeviceStorageKeyGate/__tests__/DeviceStorageKeyGate.test.tsx +0 -119
  154. package/src/components/Dialog/Dialog.module.css +0 -335
  155. package/src/components/Dialog/Dialog.stories.tsx +0 -324
  156. package/src/components/Dialog/Dialog.tsx +0 -254
  157. package/src/components/Dialog/__tests__/Dialog.test.tsx +0 -318
  158. package/src/components/DragHandleRow/DragHandleRow.module.css +0 -57
  159. package/src/components/DragHandleRow/DragHandleRow.tsx +0 -42
  160. package/src/components/Drawer/Drawer.module.css +0 -121
  161. package/src/components/Drawer/Drawer.stories.tsx +0 -132
  162. package/src/components/Drawer/Drawer.tsx +0 -175
  163. package/src/components/Drawer/__tests__/Drawer.test.tsx +0 -226
  164. package/src/components/EmptyState/EmptyState.module.css +0 -27
  165. package/src/components/EmptyState/EmptyState.tsx +0 -27
  166. package/src/components/FileDropzone/FileDropzone.module.css +0 -63
  167. package/src/components/FileDropzone/FileDropzone.tsx +0 -109
  168. package/src/components/FileDropzone/__tests__/FileDropzone.test.tsx +0 -67
  169. package/src/components/FormField/FormField.module.css +0 -33
  170. package/src/components/FormField/FormField.tsx +0 -78
  171. package/src/components/FormField/__tests__/FormField.test.tsx +0 -83
  172. package/src/components/GripIcon/GripIcon.tsx +0 -27
  173. package/src/components/Header/Header.module.css +0 -62
  174. package/src/components/Header/Header.stories.tsx +0 -452
  175. package/src/components/Header/Header.tsx +0 -102
  176. package/src/components/Header/__tests__/Header.test.tsx +0 -104
  177. package/src/components/HeaderFooterLayout/HeaderFooterLayout.module.css +0 -21
  178. package/src/components/HeaderFooterLayout/HeaderFooterLayout.stories.tsx +0 -111
  179. package/src/components/HeaderFooterLayout/HeaderFooterLayout.tsx +0 -54
  180. package/src/components/HeaderFooterLayout/__tests__/HeaderFooterLayout.test.tsx +0 -58
  181. package/src/components/HoverCard/HoverCard.module.css +0 -3
  182. package/src/components/HoverCard/HoverCard.stories.tsx +0 -66
  183. package/src/components/HoverCard/HoverCard.tsx +0 -111
  184. package/src/components/HoverCard/__tests__/HoverCard.test.tsx +0 -99
  185. package/src/components/Icon/Icon.module.css +0 -27
  186. package/src/components/Icon/Icon.stories.tsx +0 -95
  187. package/src/components/Icon/Icon.tsx +0 -43
  188. package/src/components/Icon/__tests__/Icon.test.tsx +0 -40
  189. package/src/components/Icon/icons/activity.tsx +0 -20
  190. package/src/components/Icon/icons/alert-triangle.tsx +0 -22
  191. package/src/components/Icon/icons/apple.tsx +0 -21
  192. package/src/components/Icon/icons/arrow-left-right.tsx +0 -23
  193. package/src/components/Icon/icons/banana.tsx +0 -21
  194. package/src/components/Icon/icons/beef.tsx +0 -22
  195. package/src/components/Icon/icons/beer.tsx +0 -24
  196. package/src/components/Icon/icons/bell.tsx +0 -21
  197. package/src/components/Icon/icons/bold.tsx +0 -20
  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-chevron-left.tsx +0 -21
  208. package/src/components/Icon/icons/circle-x.tsx +0 -22
  209. package/src/components/Icon/icons/code.tsx +0 -21
  210. package/src/components/Icon/icons/coffee.tsx +0 -23
  211. package/src/components/Icon/icons/cookie.tsx +0 -25
  212. package/src/components/Icon/icons/copy.tsx +0 -21
  213. package/src/components/Icon/icons/credit-card.tsx +0 -21
  214. package/src/components/Icon/icons/croissant.tsx +0 -24
  215. package/src/components/Icon/icons/cup-soda.tsx +0 -23
  216. package/src/components/Icon/icons/database.tsx +0 -22
  217. package/src/components/Icon/icons/download.tsx +0 -22
  218. package/src/components/Icon/icons/drumstick.tsx +0 -21
  219. package/src/components/Icon/icons/egg.tsx +0 -20
  220. package/src/components/Icon/icons/ellipsis-vertical.tsx +0 -22
  221. package/src/components/Icon/icons/external-link.tsx +0 -22
  222. package/src/components/Icon/icons/eye-off.tsx +0 -23
  223. package/src/components/Icon/icons/eye.tsx +0 -21
  224. package/src/components/Icon/icons/file-text.tsx +0 -24
  225. package/src/components/Icon/icons/file.tsx +0 -21
  226. package/src/components/Icon/icons/fish.tsx +0 -25
  227. package/src/components/Icon/icons/folder-closed.tsx +0 -21
  228. package/src/components/Icon/icons/folder-open.tsx +0 -20
  229. package/src/components/Icon/icons/folder.tsx +0 -20
  230. package/src/components/Icon/icons/folders.tsx +0 -21
  231. package/src/components/Icon/icons/grid-2x2.tsx +0 -22
  232. package/src/components/Icon/icons/hat-glasses.tsx +0 -24
  233. package/src/components/Icon/icons/history.tsx +0 -22
  234. package/src/components/Icon/icons/house.tsx +0 -21
  235. package/src/components/Icon/icons/inbox.tsx +0 -21
  236. package/src/components/Icon/icons/index.ts +0 -394
  237. package/src/components/Icon/icons/info.tsx +0 -22
  238. package/src/components/Icon/icons/italic.tsx +0 -22
  239. package/src/components/Icon/icons/layers.tsx +0 -22
  240. package/src/components/Icon/icons/layout-dashboard.tsx +0 -23
  241. package/src/components/Icon/icons/layout-grid.tsx +0 -23
  242. package/src/components/Icon/icons/link.tsx +0 -21
  243. package/src/components/Icon/icons/list-ordered.tsx +0 -25
  244. package/src/components/Icon/icons/list.tsx +0 -25
  245. package/src/components/Icon/icons/lock.tsx +0 -21
  246. package/src/components/Icon/icons/log-out.tsx +0 -22
  247. package/src/components/Icon/icons/luggage.tsx +0 -24
  248. package/src/components/Icon/icons/mail.tsx +0 -21
  249. package/src/components/Icon/icons/map-pin.tsx +0 -21
  250. package/src/components/Icon/icons/menu.tsx +0 -22
  251. package/src/components/Icon/icons/milk.tsx +0 -22
  252. package/src/components/Icon/icons/minus.tsx +0 -20
  253. package/src/components/Icon/icons/package.tsx +0 -23
  254. package/src/components/Icon/icons/paint-bucket.tsx +0 -23
  255. package/src/components/Icon/icons/panel-left.tsx +0 -21
  256. package/src/components/Icon/icons/pencil.tsx +0 -21
  257. package/src/components/Icon/icons/pin.tsx +0 -21
  258. package/src/components/Icon/icons/pizza.tsx +0 -24
  259. package/src/components/Icon/icons/plus.tsx +0 -21
  260. package/src/components/Icon/icons/rectangle-ellipsis.tsx +0 -23
  261. package/src/components/Icon/icons/refresh-cw.tsx +0 -23
  262. package/src/components/Icon/icons/rotate-ccw.tsx +0 -21
  263. package/src/components/Icon/icons/rotate-cw.tsx +0 -21
  264. package/src/components/Icon/icons/route.tsx +0 -22
  265. package/src/components/Icon/icons/salad.tsx +0 -24
  266. package/src/components/Icon/icons/search.tsx +0 -21
  267. package/src/components/Icon/icons/send.tsx +0 -21
  268. package/src/components/Icon/icons/settings.tsx +0 -21
  269. package/src/components/Icon/icons/share-2.tsx +0 -24
  270. package/src/components/Icon/icons/sheet.tsx +0 -24
  271. package/src/components/Icon/icons/shield.tsx +0 -20
  272. package/src/components/Icon/icons/shopping-basket.tsx +0 -26
  273. package/src/components/Icon/icons/sliders-horizontal.tsx +0 -28
  274. package/src/components/Icon/icons/smartphone.tsx +0 -21
  275. package/src/components/Icon/icons/snowflake.tsx +0 -31
  276. package/src/components/Icon/icons/spray-can.tsx +0 -29
  277. package/src/components/Icon/icons/square-kanban.tsx +0 -23
  278. package/src/components/Icon/icons/table.tsx +0 -23
  279. package/src/components/Icon/icons/trash-2.tsx +0 -24
  280. package/src/components/Icon/icons/upload.tsx +0 -22
  281. package/src/components/Icon/icons/user-round-plus.tsx +0 -23
  282. package/src/components/Icon/icons/user.tsx +0 -21
  283. package/src/components/Icon/icons/users.tsx +0 -23
  284. package/src/components/Icon/icons/wine.tsx +0 -23
  285. package/src/components/Icon/icons/x.tsx +0 -21
  286. package/src/components/IconPicker/IconPicker.module.css +0 -63
  287. package/src/components/IconPicker/IconPicker.stories.tsx +0 -84
  288. package/src/components/IconPicker/IconPicker.tsx +0 -90
  289. package/src/components/Input/Input.module.css +0 -52
  290. package/src/components/Input/Input.stories.tsx +0 -86
  291. package/src/components/Input/Input.tsx +0 -20
  292. package/src/components/Input/__tests__/Input.test.tsx +0 -22
  293. package/src/components/Item/Item.module.css +0 -70
  294. package/src/components/Item/Item.stories.tsx +0 -62
  295. package/src/components/Item/Item.tsx +0 -54
  296. package/src/components/Item/__tests__/Item.test.tsx +0 -39
  297. package/src/components/Kbd/Kbd.module.css +0 -14
  298. package/src/components/Kbd/Kbd.stories.tsx +0 -32
  299. package/src/components/Kbd/Kbd.tsx +0 -12
  300. package/src/components/Kbd/__tests__/Kbd.test.tsx +0 -14
  301. package/src/components/Label/Label.module.css +0 -11
  302. package/src/components/Label/Label.stories.tsx +0 -40
  303. package/src/components/Label/Label.tsx +0 -24
  304. package/src/components/Label/__tests__/Label.test.tsx +0 -32
  305. package/src/components/LegalLinks/LegalLinks.module.css +0 -24
  306. package/src/components/LegalLinks/LegalLinks.stories.tsx +0 -22
  307. package/src/components/LegalLinks/LegalLinks.tsx +0 -40
  308. package/src/components/Markdown/Markdown.module.css +0 -73
  309. package/src/components/Markdown/Markdown.stories.tsx +0 -40
  310. package/src/components/Markdown/Markdown.tsx +0 -305
  311. package/src/components/Markdown/__tests__/Markdown.test.tsx +0 -144
  312. package/src/components/Marker/Marker.module.css +0 -33
  313. package/src/components/Marker/Marker.stories.tsx +0 -39
  314. package/src/components/Marker/Marker.tsx +0 -34
  315. package/src/components/Marker/__tests__/Marker.test.tsx +0 -23
  316. package/src/components/MemberMultiSelect/MemberMultiSelect.module.css +0 -27
  317. package/src/components/MemberMultiSelect/MemberMultiSelect.stories.tsx +0 -74
  318. package/src/components/MemberMultiSelect/MemberMultiSelect.tsx +0 -67
  319. package/src/components/Menu/Menu.module.css +0 -90
  320. package/src/components/Menu/Menu.tsx +0 -209
  321. package/src/components/Menu/__tests__/Menu.test.tsx +0 -227
  322. package/src/components/Menubar/Menubar.stories.tsx +0 -52
  323. package/src/components/Menubar/Menubar.tsx +0 -42
  324. package/src/components/Menubar/__tests__/Menubar.test.tsx +0 -45
  325. package/src/components/Message/Message.module.css +0 -99
  326. package/src/components/Message/Message.stories.tsx +0 -79
  327. package/src/components/Message/Message.tsx +0 -41
  328. package/src/components/Message/__tests__/Message.test.tsx +0 -46
  329. package/src/components/MessageScroller/MessageScroller.module.css +0 -65
  330. package/src/components/MessageScroller/MessageScroller.stories.tsx +0 -84
  331. package/src/components/MessageScroller/MessageScroller.tsx +0 -84
  332. package/src/components/MessageScroller/__tests__/MessageScroller.test.tsx +0 -105
  333. package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +0 -82
  334. package/src/components/MobileAppsDrawer/MobileAppsDrawer.tsx +0 -78
  335. package/src/components/MobileAppsDrawer/__tests__/MobileAppsDrawer.test.tsx +0 -80
  336. package/src/components/MobileFooter/MobileFooter.module.css +0 -73
  337. package/src/components/MobileFooter/MobileFooter.stories.tsx +0 -47
  338. package/src/components/MobileFooter/MobileFooter.tsx +0 -122
  339. package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +0 -129
  340. package/src/components/MobileHeader/MobileHeader.module.css +0 -76
  341. package/src/components/MobileHeader/MobileHeader.stories.tsx +0 -57
  342. package/src/components/MobileHeader/MobileHeader.tsx +0 -90
  343. package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +0 -113
  344. package/src/components/NavList/NavList.module.css +0 -130
  345. package/src/components/NavList/NavList.tsx +0 -136
  346. package/src/components/NavList/__tests__/NavList.test.tsx +0 -109
  347. package/src/components/NavTabs/NavTabs.module.css +0 -50
  348. package/src/components/NavTabs/NavTabs.tsx +0 -61
  349. package/src/components/NavigationMenu/NavigationMenu.module.css +0 -53
  350. package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -58
  351. package/src/components/NavigationMenu/NavigationMenu.tsx +0 -125
  352. package/src/components/NavigationMenu/__tests__/NavigationMenu.test.tsx +0 -93
  353. package/src/components/NotificationsPanel/NotificationsPanel.module.css +0 -258
  354. package/src/components/NotificationsPanel/NotificationsPanel.stories.tsx +0 -61
  355. package/src/components/NotificationsPanel/NotificationsPanel.tsx +0 -187
  356. package/src/components/NotificationsPanel/__tests__/NotificationsPanel.test.tsx +0 -78
  357. package/src/components/OfflineGate/OfflineGate.tsx +0 -44
  358. package/src/components/OfflineGate/__tests__/OfflineGate.test.tsx +0 -66
  359. package/src/components/OverlayHeader/OverlayHeader.module.css +0 -98
  360. package/src/components/OverlayHeader/OverlayHeader.tsx +0 -77
  361. package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +0 -69
  362. package/src/components/PageContainer/PageContainer.module.css +0 -82
  363. package/src/components/PageContainer/PageContainer.tsx +0 -64
  364. package/src/components/PageContainer/__tests__/PageContainer.test.tsx +0 -70
  365. package/src/components/PageHeader/PageHeader.module.css +0 -86
  366. package/src/components/PageHeader/PageHeader.tsx +0 -176
  367. package/src/components/PageHeader/__tests__/PageHeader.test.tsx +0 -103
  368. package/src/components/PageLayout/PageLayout.module.css +0 -51
  369. package/src/components/PageLayout/PageLayout.stories.tsx +0 -73
  370. package/src/components/PageLayout/PageLayout.tsx +0 -51
  371. package/src/components/PageLayout/__tests__/PageLayout.test.tsx +0 -34
  372. package/src/components/Pagination/Pagination.module.css +0 -98
  373. package/src/components/Pagination/Pagination.stories.tsx +0 -49
  374. package/src/components/Pagination/Pagination.tsx +0 -87
  375. package/src/components/Pagination/__tests__/Pagination.test.tsx +0 -56
  376. package/src/components/Popover/Popover.module.css +0 -74
  377. package/src/components/Popover/Popover.stories.tsx +0 -357
  378. package/src/components/Popover/Popover.tsx +0 -290
  379. package/src/components/Popover/__tests__/Popover.test.tsx +0 -263
  380. package/src/components/Progress/Progress.module.css +0 -20
  381. package/src/components/Progress/Progress.stories.tsx +0 -40
  382. package/src/components/Progress/Progress.tsx +0 -35
  383. package/src/components/Progress/__tests__/Progress.test.tsx +0 -31
  384. package/src/components/QuantityStepper/QuantityStepper.module.css +0 -67
  385. package/src/components/QuantityStepper/QuantityStepper.stories.tsx +0 -79
  386. package/src/components/QuantityStepper/QuantityStepper.tsx +0 -107
  387. package/src/components/RadioGroup/RadioGroup.module.css +0 -88
  388. package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -69
  389. package/src/components/RadioGroup/RadioGroup.tsx +0 -99
  390. package/src/components/RadioGroup/__tests__/RadioGroup.test.tsx +0 -59
  391. package/src/components/Resizable/Resizable.module.css +0 -70
  392. package/src/components/Resizable/Resizable.stories.tsx +0 -82
  393. package/src/components/Resizable/Resizable.tsx +0 -313
  394. package/src/components/Resizable/__tests__/Resizable.test.tsx +0 -128
  395. package/src/components/ResponsiveSurface/ResponsiveSurface.tsx +0 -24
  396. package/src/components/ResponsiveSurface/__tests__/ResponsiveSurface.test.tsx +0 -73
  397. package/src/components/RootLayout/RootLayout.module.css +0 -12
  398. package/src/components/RootLayout/RootLayout.stories.tsx +0 -125
  399. package/src/components/RootLayout/RootLayout.tsx +0 -185
  400. package/src/components/RootLayout/__tests__/RootLayout.test.tsx +0 -161
  401. package/src/components/ScrollArea/ScrollArea.module.css +0 -20
  402. package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -57
  403. package/src/components/ScrollArea/ScrollArea.tsx +0 -27
  404. package/src/components/ScrollArea/__tests__/ScrollArea.test.tsx +0 -39
  405. package/src/components/SegmentedControl/SegmentedControl.module.css +0 -55
  406. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -118
  407. package/src/components/SegmentedControl/SegmentedControl.tsx +0 -56
  408. package/src/components/SegmentedControl/__tests__/SegmentedControl.test.tsx +0 -63
  409. package/src/components/Select/Select.module.css +0 -82
  410. package/src/components/Select/Select.stories.tsx +0 -115
  411. package/src/components/Select/Select.tsx +0 -48
  412. package/src/components/Select/__tests__/Select.test.tsx +0 -59
  413. package/src/components/Sheet/Sheet.module.css +0 -58
  414. package/src/components/Sheet/Sheet.tsx +0 -109
  415. package/src/components/Sheet/__tests__/Sheet.test.tsx +0 -99
  416. package/src/components/Slider/Slider.module.css +0 -95
  417. package/src/components/Slider/Slider.stories.tsx +0 -64
  418. package/src/components/Slider/Slider.tsx +0 -77
  419. package/src/components/Slider/__tests__/Slider.test.tsx +0 -45
  420. package/src/components/Spinner/Spinner.module.css +0 -39
  421. package/src/components/Spinner/Spinner.tsx +0 -23
  422. package/src/components/SplitMethodSelector/SplitMethodSelector.stories.tsx +0 -33
  423. package/src/components/SplitMethodSelector/SplitMethodSelector.tsx +0 -43
  424. package/src/components/SplitPane/SplitPane.module.css +0 -85
  425. package/src/components/SplitPane/SplitPane.stories.tsx +0 -160
  426. package/src/components/SplitPane/SplitPane.tsx +0 -149
  427. package/src/components/SplitPane/__tests__/SplitPane.test.tsx +0 -51
  428. package/src/components/StatusBadge/StatusBadge.module.css +0 -59
  429. package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -74
  430. package/src/components/StatusBadge/StatusBadge.tsx +0 -65
  431. package/src/components/StepStrip/StepStrip.module.css +0 -53
  432. package/src/components/StepStrip/StepStrip.tsx +0 -74
  433. package/src/components/SuggestionInput/SuggestionInput.module.css +0 -103
  434. package/src/components/SuggestionInput/SuggestionInput.stories.tsx +0 -144
  435. package/src/components/SuggestionInput/SuggestionInput.tsx +0 -207
  436. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +0 -64
  437. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +0 -243
  438. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlide.tsx +0 -35
  439. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody.tsx +0 -42
  440. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideFooter.tsx +0 -18
  441. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader.tsx +0 -21
  442. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideParts.module.css +0 -29
  443. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +0 -214
  444. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarouselDevGuard.test.tsx +0 -61
  445. package/src/components/SwipableMobileCarousel/context.ts +0 -13
  446. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +0 -64
  447. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +0 -73
  448. package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +0 -63
  449. package/src/components/SwipeStack/SwipeStack.module.css +0 -101
  450. package/src/components/SwipeStack/SwipeStack.tsx +0 -199
  451. package/src/components/SwipeStack/SwipeStackCard.tsx +0 -22
  452. package/src/components/SwipeStack/__tests__/SwipeStack.test.tsx +0 -169
  453. package/src/components/SystemBanner/SystemBanner.module.css +0 -79
  454. package/src/components/SystemBanner/SystemBanner.stories.tsx +0 -86
  455. package/src/components/SystemBanner/SystemBanner.tsx +0 -50
  456. package/src/components/SystemBanner/__tests__/SystemBanner.test.tsx +0 -50
  457. package/src/components/Table/Table.module.css +0 -45
  458. package/src/components/Table/Table.stories.tsx +0 -125
  459. package/src/components/Table/Table.tsx +0 -51
  460. package/src/components/Table/__tests__/Table.test.tsx +0 -50
  461. package/src/components/Tabs/Tabs.module.css +0 -56
  462. package/src/components/Tabs/Tabs.stories.tsx +0 -100
  463. package/src/components/Tabs/Tabs.tsx +0 -46
  464. package/src/components/Tabs/__tests__/Tabs.test.tsx +0 -45
  465. package/src/components/TagInput/TagInput.module.css +0 -141
  466. package/src/components/TagInput/TagInput.stories.tsx +0 -109
  467. package/src/components/TagInput/TagInput.tsx +0 -174
  468. package/src/components/TagInput/__tests__/TagInput.test.tsx +0 -69
  469. package/src/components/Textarea/Textarea.module.css +0 -47
  470. package/src/components/Textarea/Textarea.tsx +0 -38
  471. package/src/components/Textarea/__tests__/Textarea.test.tsx +0 -51
  472. package/src/components/ThreeColumnLayout/ThreeColumnLayout.module.css +0 -35
  473. package/src/components/ThreeColumnLayout/ThreeColumnLayout.stories.tsx +0 -152
  474. package/src/components/ThreeColumnLayout/ThreeColumnLayout.tsx +0 -87
  475. package/src/components/ThreeColumnLayout/__tests__/ThreeColumnLayout.test.tsx +0 -78
  476. package/src/components/Toast/Toast.module.css +0 -191
  477. package/src/components/Toast/Toast.stories.tsx +0 -191
  478. package/src/components/Toast/Toast.tsx +0 -139
  479. package/src/components/Toggle/Toggle.module.css +0 -57
  480. package/src/components/Toggle/Toggle.stories.tsx +0 -95
  481. package/src/components/Toggle/Toggle.tsx +0 -39
  482. package/src/components/Toggle/__tests__/Toggle.test.tsx +0 -47
  483. package/src/components/Tooltip/Tooltip.module.css +0 -56
  484. package/src/components/Tooltip/Tooltip.tsx +0 -30
  485. package/src/components/Typography/Typography.module.css +0 -47
  486. package/src/components/Typography/Typography.stories.tsx +0 -62
  487. package/src/components/Typography/Typography.tsx +0 -30
  488. package/src/components/Typography/__tests__/Typography.test.tsx +0 -34
  489. package/src/components/UserMenu/UserMenu.module.css +0 -90
  490. package/src/components/UserMenu/UserMenu.stories.tsx +0 -49
  491. package/src/components/UserMenu/UserMenu.tsx +0 -132
  492. package/src/components/UserMenu/__tests__/UserMenu.test.tsx +0 -77
  493. package/src/css-modules.d.ts +0 -4
  494. package/src/hooks/__tests__/useCarouselRouteSync.test.tsx +0 -126
  495. package/src/hooks/__tests__/useDoubleTap.test.tsx +0 -117
  496. package/src/hooks/__tests__/useIsMobile.test.tsx +0 -80
  497. package/src/hooks/__tests__/useIsOffline.test.tsx +0 -53
  498. package/src/hooks/__tests__/useLongPress.test.tsx +0 -158
  499. package/src/hooks/__tests__/useOfflineTileState.test.tsx +0 -69
  500. package/src/hooks/__tests__/usePublishShellChromeHeight.test.tsx +0 -118
  501. package/src/hooks/__tests__/useReorderSensors.test.ts +0 -26
  502. package/src/hooks/__tests__/useResponsiveLayout.test.tsx +0 -87
  503. package/src/hooks/__tests__/useSnapCarousel.test.tsx +0 -175
  504. package/src/hooks/__tests__/useSwipeReveal.test.tsx +0 -110
  505. package/src/hooks/__tests__/useSwipeStack.test.tsx +0 -155
  506. package/src/hooks/index.ts +0 -33
  507. package/src/hooks/useCarouselRouteSync.ts +0 -92
  508. package/src/hooks/useCommitOnEnterOrBlur.ts +0 -39
  509. package/src/hooks/useDoubleTap.ts +0 -91
  510. package/src/hooks/useIsMobile.ts +0 -33
  511. package/src/hooks/useIsOffline.ts +0 -41
  512. package/src/hooks/useLongPress.ts +0 -185
  513. package/src/hooks/useOfflineTileState.ts +0 -45
  514. package/src/hooks/usePublishShellChromeHeight.ts +0 -96
  515. package/src/hooks/useReorderSensors.ts +0 -88
  516. package/src/hooks/useResponsiveLayout.ts +0 -36
  517. package/src/hooks/useSnapCarousel.ts +0 -284
  518. package/src/hooks/useSwipeReveal.ts +0 -107
  519. package/src/hooks/useSwipeStack.ts +0 -235
  520. package/src/index.ts +0 -311
  521. package/src/motion.ts +0 -78
  522. package/src/overlay-shell.ts +0 -159
  523. package/src/scroll-lock.ts +0 -22
  524. package/src/stories/Avatar.stories.tsx +0 -44
  525. package/src/stories/Card.stories.tsx +0 -35
  526. package/src/stories/Checkbox.stories.tsx +0 -45
  527. package/src/stories/DesignSystemOverview.stories.tsx +0 -3793
  528. package/src/stories/DeviceOnlyGate.stories.tsx +0 -35
  529. package/src/stories/DeviceStorageKeyGate.stories.tsx +0 -57
  530. package/src/stories/DragHandleRow.stories.tsx +0 -41
  531. package/src/stories/EmptyState.stories.tsx +0 -33
  532. package/src/stories/FileDropzone.stories.tsx +0 -69
  533. package/src/stories/FormField.stories.tsx +0 -47
  534. package/src/stories/GripIcon.stories.tsx +0 -29
  535. package/src/stories/InteractionHooks.stories.tsx +0 -925
  536. package/src/stories/LayoutSystem.stories.tsx +0 -639
  537. package/src/stories/MenuEntries.stories.tsx +0 -86
  538. package/src/stories/MobilePatterns.stories.tsx +0 -1536
  539. package/src/stories/NavList.stories.tsx +0 -147
  540. package/src/stories/NavTabs.stories.tsx +0 -53
  541. package/src/stories/OfflineGate.stories.tsx +0 -42
  542. package/src/stories/PageContainer.stories.tsx +0 -82
  543. package/src/stories/PageHeader.stories.tsx +0 -95
  544. package/src/stories/ResponsiveSurface.stories.tsx +0 -47
  545. package/src/stories/Spinner.stories.tsx +0 -25
  546. package/src/stories/StepStrip.stories.tsx +0 -76
  547. package/src/stories/SwipableMobileCarousel.stories.tsx +0 -362
  548. package/src/stories/SwipeStack.stories.tsx +0 -200
  549. package/src/stories/Textarea.stories.tsx +0 -63
  550. package/src/stories/TokenGallery.stories.tsx +0 -652
  551. package/src/stories/Tooltip.stories.tsx +0 -59
  552. package/src/tokens/primitives.css +0 -168
  553. package/src/tokens/semantic.css +0 -162
  554. package/src/tokens/theme-presets.css +0 -33
  555. package/src/tokens/theme-presets.ts +0 -72
  556. 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
- }