@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,357 +0,0 @@
1
- import { useState } from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { Popover } from './Popover';
4
- import { Button } from '../Button/Button';
5
-
6
- const meta = {
7
- title: 'Components/Popover',
8
- component: Popover,
9
- parameters: {
10
- layout: 'centered',
11
- docs: {
12
- description: {
13
- component:
14
- 'Floating panel anchored to a trigger, below it by default. Non-modal: closes on outside click or Escape. `align` controls which trigger edge the panel aligns to; `width` accepts a fixed px number or `"trigger"` to match the trigger\'s own rendered width. Automatically flips to open upward instead of downward if the panel wouldn\'t fit below the trigger within the viewport.',
15
- },
16
- },
17
- },
18
- args: {
19
- open: false,
20
- onClose: () => {},
21
- trigger: <button type="button">Trigger</button>,
22
- 'aria-label': 'Popover',
23
- children: null,
24
- },
25
- } satisfies Meta<typeof Popover>;
26
-
27
- export default meta;
28
- type Story = StoryObj<typeof meta>;
29
-
30
- // ---------------------------------------------------------------------------
31
-
32
- const rowStyle: React.CSSProperties = {
33
- display: 'flex',
34
- alignItems: 'center',
35
- gap: 12,
36
- padding: '10px 16px',
37
- fontFamily: 'var(--sv-font-family)',
38
- fontSize: 'var(--sv-font-size-sm)',
39
- color: 'var(--sv-color-text-primary)',
40
- borderBottom: '1px solid var(--sv-color-border)',
41
- cursor: 'pointer',
42
- };
43
-
44
- /** Notification bell popover — right-aligned, 288px. */
45
- export const Notifications: Story = {
46
- render: (_args) => {
47
- const [open, setOpen] = useState(false);
48
-
49
- return (
50
- <div style={{ padding: 40 }}>
51
- <Popover
52
- open={open}
53
- onClose={() => setOpen(false)}
54
- align="right"
55
- aria-label="Notifications"
56
- trigger={
57
- <Button variant="ghost" onClick={() => setOpen((o) => !o)} aria-label="Notifications">
58
- 🔔
59
- </Button>
60
- }
61
- >
62
- <div
63
- style={{
64
- display: 'flex',
65
- alignItems: 'center',
66
- justifyContent: 'space-between',
67
- padding: '12px 16px',
68
- borderBottom: '1px solid var(--sv-color-border)',
69
- fontFamily: 'var(--sv-font-family)',
70
- }}
71
- >
72
- <span
73
- style={{
74
- fontWeight: 'var(--sv-font-weight-semibold)',
75
- fontSize: 'var(--sv-font-size-sm)',
76
- color: 'var(--sv-color-text-primary)',
77
- }}
78
- >
79
- Notifications
80
- </span>
81
- <button
82
- type="button"
83
- style={{
84
- background: 'none',
85
- border: 'none',
86
- fontSize: 'var(--sv-font-size-caption)',
87
- color: 'var(--sv-color-text-muted)',
88
- cursor: 'pointer',
89
- fontFamily: 'var(--sv-font-family)',
90
- }}
91
- >
92
- Mark all read
93
- </button>
94
- </div>
95
- <div style={rowStyle}>
96
- <span style={{ fontSize: 20 }}>📦</span>
97
- <div style={{ flex: 1 }}>
98
- <div style={{ fontWeight: 'var(--sv-font-weight-medium)' }}>Plugin updated</div>
99
- <div
100
- style={{
101
- fontSize: 'var(--sv-font-size-caption)',
102
- color: 'var(--sv-color-text-muted)',
103
- }}
104
- >
105
- 1 hour ago
106
- </div>
107
- </div>
108
- </div>
109
- <div style={rowStyle}>
110
- <span style={{ fontSize: 20 }}>✉️</span>
111
- <div style={{ flex: 1 }}>
112
- <div style={{ fontWeight: 'var(--sv-font-weight-medium)' }}>Invite accepted</div>
113
- <div
114
- style={{
115
- fontSize: 'var(--sv-font-size-caption)',
116
- color: 'var(--sv-color-text-muted)',
117
- }}
118
- >
119
- 2 min ago
120
- </div>
121
- </div>
122
- </div>
123
- </Popover>
124
- </div>
125
- );
126
- },
127
- };
128
-
129
- /** User menu — right-aligned with identity header and nav rows. */
130
- export const UserMenu: Story = {
131
- render: (_args) => {
132
- const [open, setOpen] = useState(false);
133
-
134
- const menuRowStyle: React.CSSProperties = {
135
- ...rowStyle,
136
- gap: 10,
137
- cursor: 'default',
138
- };
139
-
140
- return (
141
- <div style={{ padding: 40 }}>
142
- <Popover
143
- open={open}
144
- onClose={() => setOpen(false)}
145
- align="right"
146
- aria-label="User menu"
147
- trigger={
148
- <button
149
- type="button"
150
- onClick={() => setOpen((o) => !o)}
151
- style={{
152
- width: 32,
153
- height: 32,
154
- borderRadius: '50%',
155
- background: 'var(--sv-color-accent)',
156
- color: 'var(--sv-color-text-on-accent)',
157
- border: 'none',
158
- cursor: 'pointer',
159
- fontFamily: 'var(--sv-font-family)',
160
- fontWeight: 600,
161
- fontSize: 13,
162
- }}
163
- aria-label="Open user menu"
164
- >
165
- KB
166
- </button>
167
- }
168
- >
169
- <div
170
- style={{
171
- padding: '12px 16px',
172
- borderBottom: '1px solid var(--sv-color-border)',
173
- fontFamily: 'var(--sv-font-family)',
174
- }}
175
- >
176
- <div
177
- style={{
178
- fontWeight: 'var(--sv-font-weight-semibold)',
179
- fontSize: 'var(--sv-font-size-sm)',
180
- color: 'var(--sv-color-text-primary)',
181
- }}
182
- >
183
- Kasun Benthara
184
- </div>
185
- <div
186
- style={{
187
- fontSize: 'var(--sv-font-size-caption)',
188
- color: 'var(--sv-color-text-muted)',
189
- }}
190
- >
191
- kasun@openfs.io
192
- </div>
193
- </div>
194
- {['Account', 'Console', 'Sign out'].map((item) => (
195
- <div key={item} style={menuRowStyle}>
196
- {item}
197
- </div>
198
- ))}
199
- </Popover>
200
- </div>
201
- );
202
- },
203
- };
204
-
205
- /** Left-aligned variant. */
206
- export const LeftAligned: Story = {
207
- render: (_args) => {
208
- const [open, setOpen] = useState(false);
209
- return (
210
- <div style={{ padding: 40 }}>
211
- <Popover
212
- open={open}
213
- onClose={() => setOpen(false)}
214
- align="left"
215
- aria-label="Options"
216
- trigger={<Button onClick={() => setOpen((o) => !o)}>Open (left-aligned)</Button>}
217
- >
218
- <div
219
- style={{
220
- padding: 16,
221
- fontFamily: 'var(--sv-font-family)',
222
- fontSize: 'var(--sv-font-size-sm)',
223
- color: 'var(--sv-color-text-muted)',
224
- }}
225
- >
226
- Panel aligns to the left edge of the trigger.
227
- </div>
228
- </Popover>
229
- </div>
230
- );
231
- },
232
- };
233
-
234
- /** `panelStyle` overrides the panel's own chrome (square corners here) —
235
- * an escape hatch for compact pickers where the default rounded panel
236
- * doesn't fit the content (e.g. a small colour-swatch grid). */
237
- export const SquareCorners: Story = {
238
- render: (_args) => {
239
- const [open, setOpen] = useState(false);
240
- return (
241
- <div style={{ padding: 40 }}>
242
- <Popover
243
- open={open}
244
- onClose={() => setOpen(false)}
245
- align="left"
246
- width={160}
247
- panelStyle={{ borderRadius: 0 }}
248
- aria-label="Colour"
249
- trigger={<Button onClick={() => setOpen((o) => !o)}>Open (square panel)</Button>}
250
- >
251
- <div
252
- style={{
253
- padding: 16,
254
- fontFamily: 'var(--sv-font-family)',
255
- fontSize: 'var(--sv-font-size-sm)',
256
- color: 'var(--sv-color-text-muted)',
257
- }}
258
- >
259
- No rounded corners.
260
- </div>
261
- </Popover>
262
- </div>
263
- );
264
- },
265
- };
266
-
267
- /** `width="trigger"` matches the panel's width to the trigger's own rendered
268
- * width — for a dropdown under a full-width form field, a fixed px value
269
- * would either overflow or leave a gap depending on the field's own width. */
270
- export const MatchesTriggerWidth: Story = {
271
- render: (_args) => {
272
- const [open, setOpen] = useState(false);
273
- return (
274
- <div style={{ padding: 40, width: 360 }}>
275
- <Popover
276
- open={open}
277
- onClose={() => setOpen(false)}
278
- align="left"
279
- width="trigger"
280
- aria-label="Set due date"
281
- trigger={
282
- <button
283
- type="button"
284
- onClick={() => setOpen((o) => !o)}
285
- style={{
286
- width: '100%',
287
- boxSizing: 'border-box',
288
- textAlign: 'left',
289
- padding: '10px 14px',
290
- border: '1px solid var(--sv-color-border)',
291
- borderRadius: 'var(--sv-radius-md)',
292
- background: 'var(--sv-color-surface-raised)',
293
- fontFamily: 'var(--sv-font-family)',
294
- fontSize: 'var(--sv-font-size-sm)',
295
- color: 'var(--sv-color-text-primary)',
296
- cursor: 'pointer',
297
- }}
298
- >
299
- No due date
300
- </button>
301
- }
302
- >
303
- <div
304
- style={{
305
- padding: 16,
306
- fontFamily: 'var(--sv-font-family)',
307
- fontSize: 'var(--sv-font-size-sm)',
308
- color: 'var(--sv-color-text-muted)',
309
- }}
310
- >
311
- Panel width matches the 360px trigger above exactly, instead of a fixed pixel value that
312
- would overflow or leave a gap at other trigger widths.
313
- </div>
314
- </Popover>
315
- </div>
316
- );
317
- },
318
- };
319
-
320
- /** Flips to open upward automatically when the panel wouldn't fit below the
321
- * trigger within the viewport — no prop needed, this is always on. */
322
- export const OpensUpward: Story = {
323
- render: (_args) => {
324
- const [open, setOpen] = useState(false);
325
- return (
326
- <div
327
- style={{
328
- height: '70vh',
329
- display: 'flex',
330
- alignItems: 'flex-end',
331
- justifyContent: 'center',
332
- paddingBottom: 24,
333
- }}
334
- >
335
- <Popover
336
- open={open}
337
- onClose={() => setOpen(false)}
338
- align="left"
339
- aria-label="Options"
340
- trigger={<Button onClick={() => setOpen((o) => !o)}>Open (near viewport bottom)</Button>}
341
- >
342
- <div
343
- style={{
344
- padding: 16,
345
- fontFamily: 'var(--sv-font-family)',
346
- fontSize: 'var(--sv-font-size-sm)',
347
- color: 'var(--sv-color-text-muted)',
348
- }}
349
- >
350
- This trigger sits near the bottom of the viewport, so the panel opens upward instead of
351
- getting clipped below.
352
- </div>
353
- </Popover>
354
- </div>
355
- );
356
- },
357
- };
@@ -1,290 +0,0 @@
1
- 'use client';
2
-
3
- import {
4
- useEffect,
5
- useLayoutEffect,
6
- useRef,
7
- useState,
8
- type CSSProperties,
9
- type ReactElement,
10
- type ReactNode,
11
- } from 'react';
12
- import {
13
- isTopmostOpenOverlay,
14
- registerOpenOverlay,
15
- unregisterOpenOverlay,
16
- } from '../../overlay-shell';
17
- import styles from './Popover.module.css';
18
-
19
- export interface PopoverProps {
20
- /** The element that opens the popover — rendered as-is; caller wires its onClick. */
21
- trigger: ReactElement;
22
- open: boolean;
23
- onClose: () => void;
24
- /** Which edge of the trigger the panel aligns to. Default: 'right'. */
25
- align?: 'left' | 'right';
26
- /** Panel width in px, or `'trigger'` to match the trigger element's own
27
- * rendered width exactly (e.g. a dropdown under a full-width form field,
28
- * where a fixed pixel width would either overflow or leave a gap
29
- * depending on viewport size). Default: 288. */
30
- width?: number | 'trigger';
31
- /**
32
- * Inline style overrides for the panel, merged after `width`. Escape hatch
33
- * for callers that need to override the panel's own chrome (e.g. no
34
- * rounded corners for a compact swatch picker) — inline styles always win
35
- * regardless of CSS module load order, unlike passing an extra className.
36
- */
37
- panelStyle?: CSSProperties;
38
- /**
39
- * Class applied to the popover's own wrapper around `trigger` — the
40
- * element that participates in the caller's layout.
41
- *
42
- * Mostly needed for flex sizing: the wrapper is an `inline-flex` box with
43
- * the default `min-width: auto`, which pins it to the trigger's content
44
- * width. Inside a flex row that has to shrink, that stops a truncatable
45
- * trigger from ever giving up space, and pushes its siblings out of the
46
- * container instead. Pass a class setting `min-width: 0` there.
47
- */
48
- className?: string;
49
- 'aria-label': string;
50
- children: ReactNode;
51
- }
52
-
53
- // Matches the gap already applied via .panel's `calc(100% + var(--sv-space-2))`
54
- // offset — used here in plain px since layout math needs a number, not a
55
- // CSS custom property.
56
- const TRIGGER_GAP = 8;
57
- // Breathing room kept between the panel and the viewport edge it's closest
58
- // to — without this, a panel that just barely fits ends up flush against
59
- // the edge (e.g. touching a mobile footer nav bar with no gap at all). Kept
60
- // small deliberately: this subtracts directly from the space available
61
- // before the internal-scroll cap kicks in (see the layout effect below), so
62
- // a larger value here trades "more edge clearance" for "more panels that
63
- // would otherwise fit exactly get an unwanted scrollbar instead" — a bad
64
- // trade for a purely cosmetic gap.
65
- const VIEWPORT_MARGIN = 4;
66
-
67
- /**
68
- * Popover — floating panel anchored to a trigger element, below it by
69
- * default.
70
- *
71
- * Positioning is `position: absolute` inside a `position: relative` wrapper —
72
- * no floating-ui dependency. Supports left/right alignment against the trigger
73
- * edge, and automatically opens on whichever side (above or below the
74
- * trigger) has more room within the viewport.
75
- *
76
- * If the panel doesn't fit on *either* side as the trigger currently sits —
77
- * common for a tall panel (e.g. a full calendar month) nested partway down a
78
- * long scrollable mobile sheet — the trigger's scrollable ancestor is
79
- * scrolled so the trigger sits at the top of it first, maximizing the room
80
- * available below, then the panel opens downward against that. This mirrors
81
- * how most mobile date pickers behave (scroll the page, not the picker) and
82
- * avoids the panel needing its own internal scroll in the vast majority of
83
- * cases. If it's still too tall even after that (a genuinely tiny viewport,
84
- * or an unusually tall panel), it's capped to whatever room actually exists
85
- * and scrolls internally as a last resort, rather than rendering past the
86
- * edge of the viewport with no way to reach the rest of it.
87
- *
88
- * Closes on outside click or Escape. Does not trap focus (it is non-modal).
89
- */
90
- export function Popover({
91
- trigger,
92
- open,
93
- onClose,
94
- align = 'right',
95
- width = 288,
96
- panelStyle,
97
- className,
98
- 'aria-label': ariaLabel,
99
- children,
100
- }: PopoverProps) {
101
- const containerRef = useRef<HTMLDivElement>(null);
102
- const panelRef = useRef<HTMLDivElement>(null);
103
- const [triggerWidth, setTriggerWidth] = useState<number | null>(null);
104
- // Whether the panel opens upward instead of downward. Defaults to false
105
- // (today's only behavior) so nothing shifts before this can actually be
106
- // measured.
107
- const [openUpward, setOpenUpward] = useState(false);
108
- // Caps the panel to whatever room actually exists on its chosen side, only
109
- // when the panel is taller than that — null leaves it at its natural
110
- // height, unconstrained, for the common case where it already fits.
111
- const [maxHeight, setMaxHeight] = useState<number | null>(null);
112
- // Horizontal viewport clamp, as a `left` override (container-relative px)
113
- // that replaces the `align`-driven `left: 0` / `right: 0` class rule —
114
- // null leaves alignment at its natural, class-driven position, for the
115
- // common case where the panel already fits. Needed because a fixed-width
116
- // panel anchored to one edge of a trigger near the *opposite* edge of a
117
- // narrow viewport (e.g. a 340px panel under a bell sitting near the right
118
- // edge of a 375px mobile screen) has nowhere to go but off-screen — the
119
- // existing vertical flip only ever solves the above/below axis, never
120
- // this one.
121
- const [horizontalOffset, setHorizontalOffset] = useState<number | null>(null);
122
- const overlayIdRef = useRef<string | null>(null);
123
-
124
- // Registers into the same open-overlay stack Dialog/Drawer/Sheet/
125
- // ConfirmDialog use (overlay-shell.ts) purely so a Dialog this Popover was
126
- // opened from inside of (e.g. a DatePicker/Combobox field in a modal form —
127
- // Popover is what Menu/Combobox/DatePicker/ContextMenu/HoverCard/UserMenu
128
- // are all built on) knows it is no longer the topmost overlay, and defers
129
- // Escape to this one instead of closing itself too. A separate effect keyed
130
- // only on `open`, matching useOverlayKeyboardTrap's own pattern — identity
131
- // churn on `onClose` shouldn't re-register and bump this popover back to
132
- // the top of the stack.
133
- useEffect(() => {
134
- if (!open) return;
135
- const id = registerOpenOverlay();
136
- overlayIdRef.current = id;
137
- return () => {
138
- unregisterOpenOverlay(id);
139
- overlayIdRef.current = null;
140
- };
141
- }, [open]);
142
-
143
- // width="trigger": measure the trigger's own rendered width and keep the
144
- // panel matching it, including live resizes (e.g. rotating the device, or
145
- // the trigger's own width changing for any other reason).
146
- useEffect(() => {
147
- if (width !== 'trigger') return;
148
- const el = containerRef.current?.firstElementChild as HTMLElement | null;
149
- if (!el) return;
150
- function recompute() {
151
- if (el) setTriggerWidth(el.getBoundingClientRect().width);
152
- }
153
- recompute();
154
- const ro = new ResizeObserver(recompute);
155
- ro.observe(el);
156
- return () => ro.disconnect();
157
- }, [width]);
158
-
159
- // Collision detection: once open, measure the room available above and
160
- // below the trigger within the viewport. If neither side has enough for
161
- // the panel as things currently sit, scroll the trigger's scrollable
162
- // ancestor so the trigger sits at the top of it (scrollIntoView with
163
- // behavior: 'instant' applies synchronously, so re-measuring right after
164
- // reflects the new position with no extra frame to wait for) — this is
165
- // usually enough on its own to make the panel fit below. Whatever's left
166
- // after that: open on whichever side has more room, and only if it still
167
- // doesn't fit, cap the panel's height to that room (.panel's overflow-y:
168
- // auto then lets it scroll internally as a last resort, rather than
169
- // extending past the viewport edge with no way to reach the clipped part).
170
- // Runs in a layout effect (before paint) so there's no visible flash of
171
- // "opens one way, then snaps to the other" — measured and corrected within
172
- // the same commit the browser paints.
173
- useLayoutEffect(() => {
174
- if (!open) {
175
- setOpenUpward(false);
176
- setMaxHeight(null);
177
- setHorizontalOffset(null);
178
- return;
179
- }
180
- const container = containerRef.current;
181
- const panel = panelRef.current;
182
- if (!container || !panel) return;
183
-
184
- // Arrow function expression, not a hoisted declaration — TypeScript only
185
- // preserves the non-null narrowing above for a closure defined after it.
186
- const measure = () => {
187
- const triggerRect = container.getBoundingClientRect();
188
- const panelHeight = panel.getBoundingClientRect().height;
189
- return {
190
- panelHeight,
191
- spaceBelow: window.innerHeight - triggerRect.bottom - TRIGGER_GAP - VIEWPORT_MARGIN,
192
- spaceAbove: triggerRect.top - TRIGGER_GAP - VIEWPORT_MARGIN,
193
- };
194
- };
195
-
196
- let { panelHeight, spaceBelow, spaceAbove } = measure();
197
- if (panelHeight > spaceBelow && panelHeight > spaceAbove) {
198
- container.scrollIntoView({ block: 'start', behavior: 'instant' });
199
- ({ panelHeight, spaceBelow, spaceAbove } = measure());
200
- }
201
-
202
- const upward = panelHeight > spaceBelow && spaceAbove > spaceBelow;
203
- setOpenUpward(upward);
204
- const available = upward ? spaceAbove : spaceBelow;
205
- setMaxHeight(panelHeight > available ? Math.max(available, 0) : null);
206
-
207
- // Horizontal clamp. Deliberately computed from `containerRect` (the
208
- // trigger's own position, never affected by anything this effect does)
209
- // and the panel's rendered *width* (also offset-independent) rather than
210
- // reading the panel's current `left`/`right` off the DOM — those reflect
211
- // whatever `horizontalOffset` a *previous* run of this same effect may
212
- // already have applied. Measuring the rendered position directly is not
213
- // idempotent: re-running this effect after it already nudged the panel
214
- // on-screen would see an already-corrected rect that looks like it never
215
- // needed correcting, and clear the very offset it just set (confirmed
216
- // live — React StrictMode's dev-only double-invoke of layout effects hit
217
- // exactly this: the second pass measured the first pass's fix as "fits
218
- // fine" and reset `horizontalOffset` back to null before first paint).
219
- // Rebuilding the *natural*, un-offset position analytically from the
220
- // same `align`-driven rule the CSS class itself encodes (`right: 0` /
221
- // `left: 0` relative to the container) sidesteps that entirely — the
222
- // same inputs always produce the same output, however many times this
223
- // runs.
224
- const containerRect = container.getBoundingClientRect();
225
- const panelWidth = panel.getBoundingClientRect().width;
226
- const naturalLeft = align === 'right' ? containerRect.right - panelWidth : containerRect.left;
227
- const clampedLeft = Math.min(
228
- Math.max(naturalLeft, VIEWPORT_MARGIN),
229
- window.innerWidth - VIEWPORT_MARGIN - panelWidth,
230
- );
231
- setHorizontalOffset(clampedLeft !== naturalLeft ? clampedLeft - containerRect.left : null);
232
- // children included: content that changes the panel's height (e.g. a
233
- // calendar switching months to a row with fewer/more weeks) should
234
- // re-run this measurement, not just the open/close transition itself.
235
- // align included: the horizontal clamp above reads it directly.
236
- }, [open, children, align]);
237
-
238
- // Outside-click dismissal
239
- useEffect(() => {
240
- if (!open) return;
241
- function handleMouseDown(e: MouseEvent) {
242
- if (!containerRef.current?.contains(e.target as Node)) {
243
- onClose();
244
- }
245
- }
246
- document.addEventListener('mousedown', handleMouseDown);
247
- return () => document.removeEventListener('mousedown', handleMouseDown);
248
- }, [open, onClose]);
249
-
250
- // Escape key dismissal — deferred to a nested overlay (if any) via the same
251
- // topmost-overlay check useOverlayKeyboardTrap uses, so e.g. opening a
252
- // ConfirmDialog from inside this panel's content doesn't also close the
253
- // popover out from under it on the same Escape press.
254
- useEffect(() => {
255
- if (!open) return;
256
- function handleKeyDown(e: KeyboardEvent) {
257
- if (e.key !== 'Escape') return;
258
- const id = overlayIdRef.current;
259
- if (id !== null && !isTopmostOpenOverlay(id)) return;
260
- onClose();
261
- }
262
- document.addEventListener('keydown', handleKeyDown);
263
- return () => document.removeEventListener('keydown', handleKeyDown);
264
- }, [open, onClose]);
265
-
266
- return (
267
- <div ref={containerRef} className={[styles.container, className].filter(Boolean).join(' ')}>
268
- {trigger}
269
- {open && (
270
- <div
271
- ref={panelRef}
272
- role="dialog"
273
- aria-label={ariaLabel}
274
- aria-modal={false}
275
- className={[styles.panel, styles[align], openUpward ? styles.upward : '']
276
- .filter(Boolean)
277
- .join(' ')}
278
- style={{
279
- width: width === 'trigger' ? (triggerWidth ?? undefined) : width,
280
- maxHeight: maxHeight ?? undefined,
281
- ...(horizontalOffset != null ? { left: horizontalOffset, right: 'auto' } : {}),
282
- ...panelStyle,
283
- }}
284
- >
285
- {children}
286
- </div>
287
- )}
288
- </div>
289
- );
290
- }