@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,67 +0,0 @@
1
- 'use client';
2
-
3
- import type { ReactNode } from 'react';
4
- import { Checkbox } from '../Checkbox/Checkbox';
5
- import styles from './MemberMultiSelect.module.css';
6
-
7
- export interface MemberMultiSelectOption {
8
- id: string;
9
- label: string;
10
- }
11
-
12
- export interface MemberMultiSelectProps {
13
- options: MemberMultiSelectOption[];
14
- selectedIds: Set<string>;
15
- onToggle: (id: string, checked: boolean) => void;
16
- /** Rendered to the right of a selected row only — e.g. a per-person `CurrencyInput` or share count. */
17
- renderTrailing?: (id: string) => ReactNode;
18
- /** Section label above the list, e.g. "Paid by" or "Split between". */
19
- label?: string;
20
- /** Helper/validation text below the list, e.g. a running total. */
21
- hint?: ReactNode;
22
- className?: string;
23
- }
24
-
25
- /**
26
- * MemberMultiSelect — checkbox list for picking any number of people from an
27
- * already-resolved set of options (group/project members, collaborators,
28
- * etc.). Deliberately domain-agnostic about *who* an option represents —
29
- * instance users and guest members are both just `{id, label}` here, so
30
- * nothing special is needed to include guests alongside instance users; the
31
- * caller's `options` array is the only place that distinction exists.
32
- *
33
- * Not a directory search or an "add a new guest" flow — pair with
34
- * `SuggestionInput` (search + add) for that; this component only selects
35
- * among options already passed in.
36
- */
37
- export function MemberMultiSelect({
38
- options,
39
- selectedIds,
40
- onToggle,
41
- renderTrailing,
42
- label,
43
- hint,
44
- className,
45
- }: MemberMultiSelectProps) {
46
- return (
47
- <div className={[styles.group, className].filter(Boolean).join(' ')}>
48
- {label && <span className={styles.label}>{label}</span>}
49
- {options.map((option) => {
50
- const checked = selectedIds.has(option.id);
51
- return (
52
- <div key={option.id} className={styles.row}>
53
- <Checkbox
54
- checked={checked}
55
- onChange={(next) => onToggle(option.id, next)}
56
- label={option.label}
57
- />
58
- {checked && renderTrailing && (
59
- <span className={styles.trailing}>{renderTrailing(option.id)}</span>
60
- )}
61
- </div>
62
- );
63
- })}
64
- {hint && <span className={styles.hint}>{hint}</span>}
65
- </div>
66
- );
67
- }
@@ -1,90 +0,0 @@
1
- /* Menu — the item list shared by both presentations (Popover panel on
2
- * desktop, Drawer panel on mobile); the presentational chrome around it is
3
- * entirely owned by those two components, not duplicated here.
4
- *
5
- * Sizing audit: reviewed against this scale's other compact controls —
6
- * --sv-radius-sm (6px) and --sv-font-size-sm (14px) already fit. The 44px
7
- * min-height is a deliberate design choice, kept unconditional (not gated
8
- * to pointer:coarse like Button/Checkbox) because this menu doubles as a
9
- * full Drawer sheet on mobile, where every item must stay comfortably
10
- * tappable. */
11
-
12
- .list {
13
- list-style: none;
14
- margin: 0;
15
- padding: var(--sv-space-1);
16
- display: flex;
17
- flex-direction: column;
18
- }
19
-
20
- .item {
21
- display: flex;
22
- align-items: center;
23
- gap: var(--sv-space-2);
24
- width: 100%;
25
- /* Min touch target (WCAG 2.5.5 / Apple HIG) — this menu renders as a
26
- Drawer sheet on mobile, so every item must be comfortably tappable. */
27
- min-height: var(--sv-touch-target-min, 44px);
28
- padding: var(--sv-space-2) var(--sv-space-3);
29
- border: none;
30
- border-radius: var(--sv-radius-sm);
31
- background: transparent;
32
- color: var(--sv-color-text-primary);
33
- font: inherit;
34
- font-size: var(--sv-font-size-sm);
35
- text-align: left;
36
- text-decoration: none;
37
- cursor: pointer;
38
- }
39
-
40
- @media (hover: hover) {
41
- .item:hover:not(:disabled) {
42
- background: var(--sv-color-surface-sunken);
43
- }
44
- }
45
-
46
- .item:focus-visible {
47
- outline: 2px solid var(--sv-color-focus-ring);
48
- outline-offset: -2px;
49
- }
50
-
51
- .item:disabled {
52
- opacity: 0.5;
53
- cursor: not-allowed;
54
- }
55
-
56
- .itemDestructive {
57
- color: var(--sv-color-error-text);
58
- }
59
-
60
- @media (hover: hover) {
61
- .itemDestructive:hover:not(:disabled) {
62
- background: var(--sv-color-error-surface);
63
- }
64
- }
65
-
66
- /* Reserved checkmark gutter for a checkable item — sized so unchecked
67
- siblings in the same group still align with the checked one's icon. */
68
- .check {
69
- display: inline-flex;
70
- flex-shrink: 0;
71
- width: var(--sv-icon-size-sm);
72
- height: var(--sv-icon-size-sm);
73
- align-items: center;
74
- justify-content: center;
75
- }
76
-
77
- .label {
78
- padding: var(--sv-space-2) var(--sv-space-3) var(--sv-space-1);
79
- font-size: var(--sv-font-size-label);
80
- font-weight: var(--sv-font-weight-semibold);
81
- color: var(--sv-color-text-muted);
82
- text-transform: uppercase;
83
- letter-spacing: 0.04em;
84
- }
85
-
86
- .separator {
87
- height: 1px;
88
- margin: var(--sv-space-1) var(--sv-space-2);
89
- background: var(--sv-color-border);
90
- }
@@ -1,209 +0,0 @@
1
- 'use client';
2
-
3
- import type { ReactElement } from 'react';
4
- import { useIsMobile } from '../../hooks';
5
- import { Drawer } from '../Drawer/Drawer';
6
- import { Icon, type IconName } from '../Icon/Icon';
7
- import { Popover } from '../Popover/Popover';
8
- import styles from './Menu.module.css';
9
-
10
- export interface MenuItem {
11
- type?: 'item';
12
- label: string;
13
- /** Optional when `href` is provided (a pure navigation entry needs no
14
- * extra callback) — required otherwise. Called before the surface closes
15
- * is the caller's job to avoid; `Menu`'s own wiring always closes first,
16
- * then calls this. */
17
- onSelect?: () => void;
18
- /** Renders the entry as a link (`<a href>`, `role="menuitem"`) instead of
19
- * a `<button>` — same href-vs-onClick convention as `MobileAppsDrawer`'s
20
- * items. Framework-agnostic (a plain anchor, not `next/link`), matching
21
- * every other `packages/ui` href slot. */
22
- href?: string;
23
- icon?: IconName;
24
- /** Styles the item as a destructive action (e.g. "Delete list"). */
25
- destructive?: boolean;
26
- disabled?: boolean;
27
- /**
28
- * Marks the item as one of a mutually-exclusive set (e.g. the active sort
29
- * order) — renders a leading checkmark and `role="menuitemradio"` instead
30
- * of `role="menuitem"`. Pass this on every item in the group, including
31
- * the unchecked ones, so their labels stay aligned with the checked one's
32
- * reserved checkmark gutter. Omit entirely for plain action items (e.g.
33
- * "Delete list") — they render with no reserved leading space at all.
34
- */
35
- checked?: boolean;
36
- }
37
-
38
- /** A non-interactive section heading above a run of items (e.g. "Sort by"). */
39
- export interface MenuLabel {
40
- type: 'label';
41
- label: string;
42
- }
43
-
44
- /** A visual divider between sections. */
45
- export interface MenuSeparator {
46
- type: 'separator';
47
- }
48
-
49
- export type MenuEntry = MenuItem | MenuLabel | MenuSeparator;
50
-
51
- export interface MenuProps {
52
- /** The element that opens the menu — rendered as-is; the caller wires its
53
- * onClick to flip `open` (same controlled pattern as `Popover`). */
54
- trigger: ReactElement;
55
- open: boolean;
56
- onClose: () => void;
57
- items: MenuEntry[];
58
- 'aria-label': string;
59
- /** Forwarded to `Popover` on desktop. Has no effect on mobile, where the
60
- * menu is always a full-width `Drawer`. */
61
- align?: 'left' | 'right';
62
- /** Forwarded to `Popover` on desktop (same default: 288). Has no effect
63
- * on mobile. Narrow this when the trigger lives inside a column
64
- * narrower than the default width — e.g. a per-row "⋯" menu in a
65
- * sidebar list — so the panel fits within that column's own bounds
66
- * instead of overflowing past its edge, where a scrollable ancestor's
67
- * `overflow-y: auto` (which the CSS Overflow spec computes the paired
68
- * `overflow-x` to `auto` as well, not `visible`, once either axis is
69
- * set) would clip it. */
70
- width?: number | 'trigger';
71
- }
72
-
73
- /**
74
- * Menu — an adaptive action menu: `Popover` on desktop, a bottom-sheet
75
- * `Drawer` on mobile. Replaces the desktop-Popover/mobile-Drawer fork that
76
- * `⋯` action menus (list options, row actions) otherwise re-derive per
77
- * plugin. Same list of `items` renders in both presentations — only the
78
- * surrounding chrome (floating panel vs. bottom sheet) differs, matching the
79
- * platform's `useIsMobile` breakpoint.
80
- *
81
- * `items` accepts three entry shapes: a plain action (`MenuItem`, `type`
82
- * omitted or `'item'`), a non-interactive section heading (`MenuLabel`,
83
- * `type: 'label'`), and a `MenuSeparator` (`type: 'separator'`) — enough to
84
- * express grouped sections like "Filter" / "Sort by" above a run of
85
- * destructive actions, matching how native OS menus lay out mixed
86
- * action/selection groups.
87
- *
88
- * Selecting an item both closes the menu and calls its `onSelect` — a
89
- * consumer's `onSelect` never needs to call `onClose` itself.
90
- */
91
- /**
92
- * MenuEntries — the `<ul role="menu">` item list itself, factored out of
93
- * `Menu` so other adaptive-surface components (e.g. `ContextMenu`) can
94
- * render the exact same items/destructive/checked/icon markup inside their
95
- * own positioning shell, instead of re-deriving it and risking drift.
96
- */
97
- export function MenuEntries({
98
- items,
99
- onSelect,
100
- }: {
101
- items: MenuEntry[];
102
- /** Called after an item's own onSelect — typically the surface's onClose. */
103
- onSelect: (entry: MenuItem) => void;
104
- }) {
105
- return (
106
- <ul className={styles.list} role="menu">
107
- {items.map((entry, index) => {
108
- // Entries are a static, order-stable list per render — nothing
109
- // reorders — so an index key is safe here.
110
- if (entry.type === 'separator') {
111
- return <li key={index} role="separator" className={styles.separator} />;
112
- }
113
- if (entry.type === 'label') {
114
- return (
115
- <li key={index} role="presentation" className={styles.label}>
116
- {entry.label}
117
- </li>
118
- );
119
- }
120
- const isCheckable = entry.checked !== undefined;
121
- const className = [styles.item, entry.destructive ? styles.itemDestructive : '']
122
- .filter(Boolean)
123
- .join(' ');
124
- const content = (
125
- <>
126
- {isCheckable && (
127
- <span className={styles.check} aria-hidden>
128
- {entry.checked && <Icon name="check" size="sm" aria-hidden />}
129
- </span>
130
- )}
131
- {entry.icon && <Icon name={entry.icon} size="sm" aria-hidden />}
132
- {entry.label}
133
- </>
134
- );
135
- return (
136
- <li key={index} role="none">
137
- {entry.href ? (
138
- <a
139
- role="menuitem"
140
- href={entry.href}
141
- className={className}
142
- onClick={() => onSelect(entry)}
143
- >
144
- {content}
145
- </a>
146
- ) : (
147
- <button
148
- role={isCheckable ? 'menuitemradio' : 'menuitem'}
149
- aria-checked={isCheckable ? entry.checked : undefined}
150
- type="button"
151
- className={className}
152
- disabled={entry.disabled}
153
- onClick={() => onSelect(entry)}
154
- >
155
- {content}
156
- </button>
157
- )}
158
- </li>
159
- );
160
- })}
161
- </ul>
162
- );
163
- }
164
-
165
- export function Menu({
166
- trigger,
167
- open,
168
- onClose,
169
- items,
170
- 'aria-label': ariaLabel,
171
- align,
172
- width,
173
- }: MenuProps) {
174
- const isMobile = useIsMobile();
175
-
176
- const list = (
177
- <MenuEntries
178
- items={items}
179
- onSelect={(entry) => {
180
- onClose();
181
- entry.onSelect?.();
182
- }}
183
- />
184
- );
185
-
186
- if (isMobile) {
187
- return (
188
- <>
189
- {trigger}
190
- <Drawer open={open} onClose={onClose} aria-label={ariaLabel}>
191
- {list}
192
- </Drawer>
193
- </>
194
- );
195
- }
196
-
197
- return (
198
- <Popover
199
- trigger={trigger}
200
- open={open}
201
- onClose={onClose}
202
- aria-label={ariaLabel}
203
- align={align}
204
- width={width}
205
- >
206
- {list}
207
- </Popover>
208
- );
209
- }
@@ -1,227 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
- import { cleanup, fireEvent, render, screen } from '@testing-library/react';
4
- import { Menu, type MenuItem } from '../Menu';
5
-
6
- let mobile = false;
7
- function installMatchMedia() {
8
- vi.stubGlobal(
9
- 'matchMedia',
10
- vi.fn().mockImplementation((query: string) => ({
11
- // useIsMobile's query is '(max-width: ...)'; everything else (e.g.
12
- // Drawer's prefers-reduced-motion check) defaults to false so the
13
- // mobile-branch Drawer isn't accidentally forced into the
14
- // reduced-motion path.
15
- matches: query.includes('max-width') ? mobile : false,
16
- media: query,
17
- addEventListener: vi.fn(),
18
- removeEventListener: vi.fn(),
19
- addListener: vi.fn(),
20
- removeListener: vi.fn(),
21
- dispatchEvent: vi.fn(),
22
- })),
23
- );
24
- }
25
-
26
- function installPointerCapture() {
27
- if (!Element.prototype.setPointerCapture) {
28
- Element.prototype.setPointerCapture = () => {};
29
- }
30
- }
31
-
32
- const items: MenuItem[] = [
33
- { label: 'Rename', onSelect: vi.fn() },
34
- { label: 'Delete', onSelect: vi.fn(), destructive: true },
35
- ];
36
-
37
- describe('Menu', () => {
38
- beforeEach(() => {
39
- mobile = false;
40
- installMatchMedia();
41
- installPointerCapture();
42
- });
43
- afterEach(() => {
44
- vi.unstubAllGlobals();
45
- cleanup();
46
- });
47
-
48
- it('renders the trigger regardless of open state', () => {
49
- render(
50
- <Menu
51
- trigger={<button type="button">Open menu</button>}
52
- open={false}
53
- onClose={() => {}}
54
- items={items}
55
- aria-label="List actions"
56
- />,
57
- );
58
- expect(screen.getByRole('button', { name: 'Open menu' })).toBeTruthy();
59
- });
60
-
61
- it('renders as a Popover on desktop', () => {
62
- render(
63
- <Menu
64
- trigger={<button type="button">Open menu</button>}
65
- open
66
- onClose={() => {}}
67
- items={items}
68
- aria-label="List actions"
69
- />,
70
- );
71
- const menu = screen.getByRole('dialog', { name: 'List actions' });
72
- // Popover's own aria-modal is explicitly false (non-modal floating panel).
73
- expect(menu.getAttribute('aria-modal')).toBe('false');
74
- expect(screen.getByRole('menuitem', { name: 'Rename' })).toBeTruthy();
75
- });
76
-
77
- it('renders as a Drawer on mobile', () => {
78
- mobile = true;
79
- installMatchMedia();
80
- render(
81
- <Menu
82
- trigger={<button type="button">Open menu</button>}
83
- open
84
- onClose={() => {}}
85
- items={items}
86
- aria-label="List actions"
87
- />,
88
- );
89
- const menu = screen.getByRole('dialog', { name: 'List actions' });
90
- expect(menu.getAttribute('aria-modal')).toBe('true');
91
- expect(screen.getByRole('menuitem', { name: 'Rename' })).toBeTruthy();
92
- });
93
-
94
- it('calls both onClose and the item onSelect when an item is chosen', () => {
95
- const onClose = vi.fn();
96
- const onSelect = vi.fn();
97
- render(
98
- <Menu
99
- trigger={<button type="button">Open menu</button>}
100
- open
101
- onClose={onClose}
102
- items={[{ label: 'Rename', onSelect }]}
103
- aria-label="List actions"
104
- />,
105
- );
106
- fireEvent.click(screen.getByRole('menuitem', { name: 'Rename' }));
107
- expect(onSelect).toHaveBeenCalledOnce();
108
- expect(onClose).toHaveBeenCalledOnce();
109
- });
110
-
111
- it('disables an item and does not fire onSelect when clicked', () => {
112
- const onSelect = vi.fn();
113
- render(
114
- <Menu
115
- trigger={<button type="button">Open menu</button>}
116
- open
117
- onClose={() => {}}
118
- items={[{ label: 'Archive', onSelect, disabled: true }]}
119
- aria-label="List actions"
120
- />,
121
- );
122
- fireEvent.click(screen.getByRole('menuitem', { name: 'Archive' }));
123
- expect(onSelect).not.toHaveBeenCalled();
124
- });
125
-
126
- it('marks a destructive item distinctly from a default one', () => {
127
- render(
128
- <Menu
129
- trigger={<button type="button">Open menu</button>}
130
- open
131
- onClose={() => {}}
132
- items={items}
133
- aria-label="List actions"
134
- />,
135
- );
136
- const renameClass = screen.getByRole('menuitem', { name: 'Rename' }).className;
137
- const deleteClass = screen.getByRole('menuitem', { name: 'Delete' }).className;
138
- expect(deleteClass).not.toBe(renameClass);
139
- });
140
-
141
- it('renders section labels and separators as non-interactive entries', () => {
142
- render(
143
- <Menu
144
- trigger={<button type="button">Open menu</button>}
145
- open
146
- onClose={() => {}}
147
- items={[
148
- { type: 'label', label: 'Sort by' },
149
- { label: 'Title', onSelect: vi.fn(), checked: true },
150
- { type: 'separator' },
151
- { label: 'Delete list', onSelect: vi.fn(), destructive: true },
152
- ]}
153
- aria-label="List actions"
154
- />,
155
- );
156
- expect(screen.getByText('Sort by').getAttribute('role')).toBe('presentation');
157
- expect(screen.getByRole('separator')).toBeTruthy();
158
- // Only the plain action item is a plain menuitem; the checkable one is a menuitemradio.
159
- expect(screen.getAllByRole('menuitem')).toHaveLength(1);
160
- });
161
-
162
- it('renders a checkable item as menuitemradio with aria-checked', () => {
163
- render(
164
- <Menu
165
- trigger={<button type="button">Open menu</button>}
166
- open
167
- onClose={() => {}}
168
- items={[
169
- { label: 'Manual', onSelect: vi.fn(), checked: false },
170
- { label: 'Title', onSelect: vi.fn(), checked: true },
171
- ]}
172
- aria-label="List actions"
173
- />,
174
- );
175
- const unchecked = screen.getByRole('menuitemradio', { name: 'Manual' });
176
- const checked = screen.getByRole('menuitemradio', { name: 'Title' });
177
- expect(unchecked.getAttribute('aria-checked')).toBe('false');
178
- expect(checked.getAttribute('aria-checked')).toBe('true');
179
- });
180
-
181
- it('closes and selects when a checkable item is clicked', () => {
182
- const onClose = vi.fn();
183
- const onSelect = vi.fn();
184
- render(
185
- <Menu
186
- trigger={<button type="button">Open menu</button>}
187
- open
188
- onClose={onClose}
189
- items={[{ label: 'Title', onSelect, checked: false }]}
190
- aria-label="List actions"
191
- />,
192
- );
193
- fireEvent.click(screen.getByRole('menuitemradio', { name: 'Title' }));
194
- expect(onSelect).toHaveBeenCalledOnce();
195
- expect(onClose).toHaveBeenCalledOnce();
196
- });
197
-
198
- it('renders an item with href as a link, not a button', () => {
199
- render(
200
- <Menu
201
- trigger={<button type="button">Open menu</button>}
202
- open
203
- onClose={() => {}}
204
- items={[{ label: 'Account', href: '/account' }]}
205
- aria-label="List actions"
206
- />,
207
- );
208
- const link = screen.getByRole('menuitem', { name: 'Account' });
209
- expect(link.tagName).toBe('A');
210
- expect(link.getAttribute('href')).toBe('/account');
211
- });
212
-
213
- it('closes on click of an href item even with no onSelect', () => {
214
- const onClose = vi.fn();
215
- render(
216
- <Menu
217
- trigger={<button type="button">Open menu</button>}
218
- open
219
- onClose={onClose}
220
- items={[{ label: 'Account', href: '/account' }]}
221
- aria-label="List actions"
222
- />,
223
- );
224
- fireEvent.click(screen.getByRole('menuitem', { name: 'Account' }));
225
- expect(onClose).toHaveBeenCalledOnce();
226
- });
227
- });
@@ -1,52 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Menubar } from './Menubar';
3
-
4
- const meta = {
5
- title: 'Components/Menubar',
6
- component: Menubar,
7
- parameters: {
8
- layout: 'padded',
9
- docs: {
10
- description: {
11
- component:
12
- "Desktop app-style menu bar (File/Edit/View...). A thin composition of NavigationMenu with MenuEntries as each item's flyout content — no positioning or list-rendering logic duplicated.",
13
- },
14
- },
15
- },
16
- } satisfies Meta<typeof Menubar>;
17
-
18
- export default meta;
19
- type Story = StoryObj<typeof meta>;
20
-
21
- // ---------------------------------------------------------------------------
22
-
23
- export const Default: Story = {
24
- args: {
25
- menus: [
26
- {
27
- label: 'File',
28
- items: [
29
- { label: 'New conversation', onSelect: () => {} },
30
- { label: 'Export', onSelect: () => {} },
31
- { type: 'separator' },
32
- { label: 'Close', onSelect: () => {} },
33
- ],
34
- },
35
- {
36
- label: 'Edit',
37
- items: [
38
- { label: 'Undo', onSelect: () => {} },
39
- { label: 'Redo', onSelect: () => {} },
40
- ],
41
- },
42
- {
43
- label: 'View',
44
- items: [
45
- { type: 'label', label: 'Layout' },
46
- { label: 'Compact', checked: false, onSelect: () => {} },
47
- { label: 'Comfortable', checked: true, onSelect: () => {} },
48
- ],
49
- },
50
- ],
51
- },
52
- };
@@ -1,42 +0,0 @@
1
- 'use client';
2
-
3
- import { NavigationMenu } from '../NavigationMenu/NavigationMenu';
4
- import { MenuEntries, type MenuEntry } from '../Menu/Menu';
5
-
6
- export interface MenubarMenu {
7
- label: string;
8
- items: MenuEntry[];
9
- }
10
-
11
- export interface MenubarProps {
12
- menus: MenubarMenu[];
13
- 'aria-label'?: string;
14
- }
15
-
16
- /**
17
- * Menubar — desktop app-style menu bar (File / Edit / View...). A thin
18
- * composition of `NavigationMenu` (top-level triggers, per-item flyout
19
- * positioning, hover-switches-when-one-is-open, arrow-key navigation) with
20
- * `MenuEntries` (the same item list markup `Menu`'s dropdowns use) as each
21
- * item's flyout content — no positioning or list-rendering logic
22
- * duplicated from either.
23
- */
24
- export function Menubar({ menus, 'aria-label': ariaLabel = 'Menu bar' }: MenubarProps) {
25
- return (
26
- <NavigationMenu
27
- aria-label={ariaLabel}
28
- items={menus.map((menu) => ({
29
- label: menu.label,
30
- content: (close: () => void) => (
31
- <MenuEntries
32
- items={menu.items}
33
- onSelect={(entry) => {
34
- close();
35
- entry.onSelect?.();
36
- }}
37
- />
38
- ),
39
- }))}
40
- />
41
- );
42
- }