@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,61 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { NotificationsPanel } from './NotificationsPanel';
3
- import { Icon } from '../Icon/Icon';
4
-
5
- const items = [
6
- {
7
- id: '1',
8
- icon: <Icon name="layers" size="sm" aria-hidden />,
9
- title: 'Added to a project',
10
- timeLabel: '2d ago',
11
- read: false,
12
- onDismiss: () => {},
13
- },
14
- {
15
- id: '2',
16
- icon: <Icon name="user-round-plus" size="sm" aria-hidden />,
17
- title: 'Jamie invited you to Notes',
18
- timeLabel: '3d ago',
19
- read: true,
20
- href: '/notes',
21
- onDismiss: () => {},
22
- },
23
- ];
24
-
25
- const meta = {
26
- title: 'Components/NotificationsPanel',
27
- component: NotificationsPanel,
28
- parameters: {
29
- layout: 'centered',
30
- docs: {
31
- description: {
32
- component:
33
- "The bell trigger + dropdown, generalized from the runtime shell's own NotificationBell. Pure presentation — no fetch/SSE/mark-read logic; the consumer supplies already-resolved items and wires onOpen/onDismiss/onMarkAllRead/onClearAll.",
34
- },
35
- },
36
- },
37
- args: {
38
- items,
39
- unreadCount: 1,
40
- onMarkAllRead: () => {},
41
- onClearAll: () => {},
42
- },
43
- } satisfies Meta<typeof NotificationsPanel>;
44
-
45
- export default meta;
46
- type Story = StoryObj<typeof meta>;
47
-
48
- export const Default: Story = {};
49
-
50
- export const Empty: Story = {
51
- args: {
52
- items: [],
53
- unreadCount: 0,
54
- },
55
- };
56
-
57
- export const WithViewAll: Story = {
58
- args: {
59
- viewAllHref: '/inbox',
60
- },
61
- };
@@ -1,187 +0,0 @@
1
- 'use client';
2
-
3
- import { useState, type ReactNode } from 'react';
4
- import { Icon } from '../Icon/Icon';
5
- import { Popover } from '../Popover/Popover';
6
- import styles from './NotificationsPanel.module.css';
7
-
8
- export interface NotificationsPanelItem {
9
- id: string;
10
- /** Category icon, already resolved (sized + colored) by the consumer —
11
- * this component doesn't own category → color mapping. */
12
- icon: ReactNode;
13
- title: string;
14
- /** Pre-formatted relative time (e.g. "2d ago") — formatting stays
15
- * consumer-side so this component needs no Date/clock dependency. */
16
- timeLabel: string;
17
- read: boolean;
18
- /** Renders the title as a link when set. */
19
- href?: string;
20
- /** Called when the title is clicked/tapped — typically "mark as read". */
21
- onOpen?: () => void;
22
- onDismiss: () => void;
23
- }
24
-
25
- export interface NotificationsPanelProps {
26
- items: NotificationsPanelItem[];
27
- unreadCount: number;
28
- onMarkAllRead?: () => void;
29
- onClearAll?: () => void;
30
- emptyMessage?: string;
31
- /** Trigger button's accessible label base — the unread count is appended
32
- * automatically, matching the real NotificationBell. Defaults to
33
- * "Notifications". */
34
- 'aria-label'?: string;
35
- align?: 'left' | 'right';
36
- /** Optional footer link (e.g. to the consumer's own full notification
37
- * list/detail view — RFC 0048) — mirrors the real `NotificationBell`'s
38
- * "View all" link. Omit to render no footer, matching this component's
39
- * behavior before this prop existed. */
40
- viewAllHref?: string;
41
- }
42
-
43
- function NotificationRow({ item }: { item: NotificationsPanelItem }) {
44
- const titleContent = item.href ? (
45
- <a href={item.href} className={styles.itemTitle} onClick={item.onOpen}>
46
- {item.title}
47
- </a>
48
- ) : !item.read ? (
49
- <button
50
- type="button"
51
- className={styles.itemTitle}
52
- aria-label={`Mark as read: ${item.title}`}
53
- onClick={item.onOpen}
54
- >
55
- {item.title}
56
- </button>
57
- ) : (
58
- <span className={styles.itemTitle}>{item.title}</span>
59
- );
60
-
61
- return (
62
- <li className={[styles.item, item.read ? styles.itemRead : ''].filter(Boolean).join(' ')}>
63
- <div className={styles.categoryIcon}>{item.icon}</div>
64
- <div className={styles.itemBody}>
65
- {titleContent}
66
- <span className={styles.itemTime}>{item.timeLabel}</span>
67
- </div>
68
- <div className={styles.itemEnd}>
69
- {!item.read && <span className={styles.unreadDot} aria-label="Unread" />}
70
- <button
71
- type="button"
72
- className={styles.dismissBtn}
73
- aria-label={`Dismiss: ${item.title}`}
74
- onClick={item.onDismiss}
75
- >
76
- <Icon name="x" size="sm" aria-hidden />
77
- </button>
78
- </div>
79
- </li>
80
- );
81
- }
82
-
83
- /**
84
- * NotificationsPanel — the bell trigger + dropdown, generalized from the
85
- * runtime shell's own `NotificationBell.tsx` visual structure and copy
86
- * (title / Mark all read / Clear all / close, then a list of category-icon +
87
- * title + time + unread-dot + dismiss rows, or an empty state).
88
- *
89
- * Deliberately **presentational only** — no fetch/SSE/polling, no
90
- * category → color mapping, no mark-read/dismiss networking. The real
91
- * `NotificationBell` owns real platform data (`/api/account/notifications`,
92
- * a shared cross-instance store); this component can't and shouldn't know
93
- * about that (SDK boundary). The consumer supplies `items` already resolved
94
- * and wires `onOpen`/`onDismiss`/`onMarkAllRead`/`onClearAll` to whatever
95
- * its own data layer needs, against a shared panel instead of a
96
- * `shell: minimal` plugin hand-rebuilding one locally. Built on the shared
97
- * `Popover` primitive (self-contained open state) rather than the
98
- * original's hand-rolled outside-click/Escape listener.
99
- */
100
- export function NotificationsPanel({
101
- items,
102
- unreadCount,
103
- onMarkAllRead,
104
- onClearAll,
105
- emptyMessage = 'No notifications.',
106
- 'aria-label': ariaLabel = 'Notifications',
107
- align = 'right',
108
- viewAllHref,
109
- }: NotificationsPanelProps) {
110
- const [open, setOpen] = useState(false);
111
-
112
- return (
113
- <Popover
114
- align={align}
115
- width={340}
116
- aria-label={ariaLabel}
117
- open={open}
118
- onClose={() => setOpen(false)}
119
- trigger={
120
- <button
121
- type="button"
122
- aria-label={unreadCount > 0 ? `${ariaLabel} (${unreadCount} unread)` : ariaLabel}
123
- aria-haspopup="true"
124
- aria-expanded={open}
125
- onClick={() => setOpen((v) => !v)}
126
- className={styles.trigger}
127
- >
128
- {/* size="lg" (24px), not "md" (20px) — matches the real
129
- NotificationBell's own inline SVG, which is literally
130
- width="24" height="24", not the DS Icon scale's "md" step. */}
131
- <Icon name="bell" size="lg" aria-hidden />
132
- {unreadCount > 0 && (
133
- <span className={styles.badge} aria-hidden="true">
134
- {unreadCount > 99 ? '99+' : unreadCount}
135
- </span>
136
- )}
137
- </button>
138
- }
139
- >
140
- <div className={styles.header}>
141
- <span className={styles.headerTitle}>{ariaLabel}</span>
142
- <div className={styles.headerActions}>
143
- {items.length > 0 && (
144
- <>
145
- {unreadCount > 0 && onMarkAllRead && (
146
- <button type="button" className={styles.actionBtn} onClick={onMarkAllRead}>
147
- Mark all read
148
- </button>
149
- )}
150
- {onClearAll && (
151
- <button type="button" className={styles.actionBtn} onClick={onClearAll}>
152
- Clear all
153
- </button>
154
- )}
155
- </>
156
- )}
157
- <button
158
- type="button"
159
- className={styles.closeBtn}
160
- aria-label={`Close ${ariaLabel.toLowerCase()}`}
161
- onClick={() => setOpen(false)}
162
- >
163
- <Icon name="x" size="sm" aria-hidden />
164
- </button>
165
- </div>
166
- </div>
167
-
168
- <ul className={styles.list} aria-label={`${ariaLabel} list`}>
169
- {items.length === 0 ? (
170
- <li className={styles.empty}>
171
- <span className={styles.emptyIcon} aria-hidden="true">
172
- <Icon name="bell" size="lg" aria-hidden />
173
- </span>
174
- <span className={styles.emptyText}>{emptyMessage}</span>
175
- </li>
176
- ) : (
177
- items.map((item) => <NotificationRow key={item.id} item={item} />)
178
- )}
179
- </ul>
180
- {viewAllHref && (
181
- <a href={viewAllHref} className={styles.viewAll} onClick={() => setOpen(false)}>
182
- View all
183
- </a>
184
- )}
185
- </Popover>
186
- );
187
- }
@@ -1,78 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it, vi } from 'vitest';
3
- import { cleanup, fireEvent, render, screen } from '@testing-library/react';
4
- import { NotificationsPanel } from '../NotificationsPanel';
5
-
6
- afterEach(() => {
7
- cleanup();
8
- });
9
-
10
- const items = [
11
- {
12
- id: '1',
13
- icon: <span>icon</span>,
14
- title: 'Added to a project',
15
- timeLabel: '2d ago',
16
- read: false,
17
- onOpen: vi.fn(),
18
- onDismiss: vi.fn(),
19
- },
20
- ];
21
-
22
- describe('NotificationsPanel', () => {
23
- it('renders a closed trigger with an unread badge', () => {
24
- render(<NotificationsPanel items={items} unreadCount={1} />);
25
- expect(screen.getByRole('button', { name: /1 unread/ })).toBeTruthy();
26
- expect(screen.queryByText('Added to a project')).toBeNull();
27
- });
28
-
29
- it('renders no badge when there are no unread notifications', () => {
30
- render(<NotificationsPanel items={[]} unreadCount={0} />);
31
- expect(screen.getByRole('button', { name: 'Notifications' })).toBeTruthy();
32
- });
33
-
34
- it('opens the panel on trigger click, showing items', () => {
35
- render(<NotificationsPanel items={items} unreadCount={1} />);
36
- fireEvent.click(screen.getByRole('button', { name: /unread/ }));
37
- expect(screen.getByText('Added to a project')).toBeTruthy();
38
- expect(screen.getByText('2d ago')).toBeTruthy();
39
- });
40
-
41
- it('shows an empty state when there are no items', () => {
42
- render(<NotificationsPanel items={[]} unreadCount={0} />);
43
- fireEvent.click(screen.getByRole('button', { name: 'Notifications' }));
44
- expect(screen.getByText('No notifications.')).toBeTruthy();
45
- });
46
-
47
- it('calls onOpen when an unread title is clicked', () => {
48
- render(<NotificationsPanel items={items} unreadCount={1} />);
49
- fireEvent.click(screen.getByRole('button', { name: /unread/ }));
50
- fireEvent.click(screen.getByRole('button', { name: 'Mark as read: Added to a project' }));
51
- expect(items[0]?.onOpen).toHaveBeenCalledOnce();
52
- });
53
-
54
- it('calls onDismiss when the dismiss button is clicked', () => {
55
- render(<NotificationsPanel items={items} unreadCount={1} />);
56
- fireEvent.click(screen.getByRole('button', { name: /unread/ }));
57
- fireEvent.click(screen.getByRole('button', { name: 'Dismiss: Added to a project' }));
58
- expect(items[0]?.onDismiss).toHaveBeenCalledOnce();
59
- });
60
-
61
- it('calls onMarkAllRead and onClearAll from the header actions', () => {
62
- const onMarkAllRead = vi.fn();
63
- const onClearAll = vi.fn();
64
- render(
65
- <NotificationsPanel
66
- items={items}
67
- unreadCount={1}
68
- onMarkAllRead={onMarkAllRead}
69
- onClearAll={onClearAll}
70
- />,
71
- );
72
- fireEvent.click(screen.getByRole('button', { name: /unread/ }));
73
- fireEvent.click(screen.getByRole('button', { name: 'Mark all read' }));
74
- fireEvent.click(screen.getByRole('button', { name: 'Clear all' }));
75
- expect(onMarkAllRead).toHaveBeenCalledOnce();
76
- expect(onClearAll).toHaveBeenCalledOnce();
77
- });
78
- });
@@ -1,44 +0,0 @@
1
- 'use client';
2
-
3
- import type { ReactNode } from 'react';
4
- import { useIsOffline } from '../../hooks/useIsOffline';
5
- import { EmptyState } from '../EmptyState/EmptyState';
6
-
7
- export interface OfflineGateProps {
8
- children: ReactNode;
9
- /** Defaults to a generic "this section" phrasing — pass the surface's own name. */
10
- surfaceName?: string;
11
- className?: string;
12
- }
13
-
14
- /**
15
- * OfflineGate — blocks administrative/settings surfaces from rendering
16
- * (possibly stale) cached content while the device has no network, showing an
17
- * explanatory empty state instead (research 0012, epic task 2.32).
18
- *
19
- * Distinct from `OfflineBanner`: the banner is an informational overlay that
20
- * coexists with normal content everywhere in the shell. This is a hard block
21
- * for surfaces where operating against stale data is actively wrong — e.g. a
22
- * Console user list or an Account billing page reflects a point-in-time
23
- * snapshot the moment it's server-rendered, and any cached copy replayed
24
- * later has no way to signal that it may already be stale. `OfflineGate`
25
- * doesn't try to tell staleness apart from freshness; it removes the
26
- * question by not rendering the content at all while offline.
27
- *
28
- * `children` is rendered unconditionally while online, so this adds no cost
29
- * to the common case — it only decides what to show, never how the wrapped
30
- * content itself is fetched or cached.
31
- */
32
- export function OfflineGate({ children, surfaceName, className }: OfflineGateProps) {
33
- const isOffline = useIsOffline();
34
- if (!isOffline) return <>{children}</>;
35
-
36
- return (
37
- <EmptyState
38
- icon="alert-triangle"
39
- heading="You're offline"
40
- description={`${surfaceName ?? 'This section'} needs a connection — reconnect to continue.`}
41
- className={className}
42
- />
43
- );
44
- }
@@ -1,66 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
- import { act, cleanup, render, screen } from '@testing-library/react';
4
- import { OfflineGate } from '../OfflineGate';
5
-
6
- describe('OfflineGate', () => {
7
- beforeEach(() => {
8
- vi.stubGlobal('navigator', { ...window.navigator, onLine: true });
9
- });
10
- afterEach(() => {
11
- vi.unstubAllGlobals();
12
- cleanup();
13
- });
14
-
15
- it('renders children unchanged while online', () => {
16
- render(
17
- <OfflineGate>
18
- <p>Live content</p>
19
- </OfflineGate>,
20
- );
21
- expect(screen.getByText('Live content')).toBeDefined();
22
- });
23
-
24
- it('replaces children with an explanatory empty state while offline', () => {
25
- vi.stubGlobal('navigator', { ...window.navigator, onLine: false });
26
- render(
27
- <OfflineGate>
28
- <p>Live content</p>
29
- </OfflineGate>,
30
- );
31
- expect(screen.queryByText('Live content')).toBeNull();
32
- expect(screen.getByText("You're offline")).toBeDefined();
33
- });
34
-
35
- it('names the surface in the offline message when provided', () => {
36
- vi.stubGlobal('navigator', { ...window.navigator, onLine: false });
37
- render(
38
- <OfflineGate surfaceName="Console">
39
- <p>Live content</p>
40
- </OfflineGate>,
41
- );
42
- expect(screen.getByText(/Console needs a connection/)).toBeDefined();
43
- });
44
-
45
- it('falls back to generic phrasing with no surface name', () => {
46
- vi.stubGlobal('navigator', { ...window.navigator, onLine: false });
47
- render(
48
- <OfflineGate>
49
- <p>Live content</p>
50
- </OfflineGate>,
51
- );
52
- expect(screen.getByText(/This section needs a connection/)).toBeDefined();
53
- });
54
-
55
- it('swaps back to children on reconnect', () => {
56
- vi.stubGlobal('navigator', { ...window.navigator, onLine: false });
57
- render(
58
- <OfflineGate>
59
- <p>Live content</p>
60
- </OfflineGate>,
61
- );
62
- expect(screen.getByText("You're offline")).toBeDefined();
63
- act(() => window.dispatchEvent(new Event('online')));
64
- expect(screen.getByText('Live content')).toBeDefined();
65
- });
66
- });
@@ -1,98 +0,0 @@
1
- /* OverlayHeader — shared fixed secondary header for Dialog's mobile mode,
2
- * Sheet, and Drawer. Not itself pinned via position — the consumer renders it
3
- * as a flex-shrink: 0 sibling before its own scrolling content region (see
4
- * the component's own doc comment). */
5
-
6
- .header {
7
- flex-shrink: 0;
8
- background: var(--sv-color-surface);
9
- border-bottom: var(--sv-border-width-hairline) solid var(--sv-color-border);
10
- }
11
-
12
- .row {
13
- display: flex;
14
- align-items: center;
15
- gap: var(--sv-space-2);
16
- padding: var(--sv-space-3) var(--sv-space-4);
17
- }
18
-
19
- .backButton {
20
- display: inline-flex;
21
- align-items: center;
22
- justify-content: center;
23
- width: var(--sv-touch-target-min, 44px);
24
- height: var(--sv-touch-target-min, 44px);
25
- flex-shrink: 0;
26
- /* Pull the touch-target padding back so the chevron glyph still sits close
27
- to the title, matching the visual (not hit-area) spacing of .row's own
28
- gap — otherwise a 44px box reads as a large empty gap before the title. */
29
- margin-left: calc(-1 * (var(--sv-touch-target-min, 44px) - var(--sv-icon-size-md)) / 2);
30
- margin-right: calc(
31
- -1 * (var(--sv-touch-target-min, 44px) - var(--sv-icon-size-md)) / 2 + var(--sv-space-1)
32
- );
33
- border: none;
34
- border-radius: var(--sv-radius-md);
35
- background: transparent;
36
- color: var(--sv-color-text-muted);
37
- cursor: pointer;
38
- }
39
-
40
- @media (hover: hover) {
41
- .backButton:hover {
42
- background: var(--sv-color-surface-sunken);
43
- color: var(--sv-color-text-primary);
44
- }
45
- }
46
-
47
- .backButton:focus-visible {
48
- outline: 2px solid var(--sv-color-focus-ring);
49
- outline-offset: -2px;
50
- }
51
-
52
- .title {
53
- flex: 1;
54
- min-width: 0;
55
- overflow: hidden;
56
- text-overflow: ellipsis;
57
- white-space: nowrap;
58
- font-size: var(--sv-font-size-xl);
59
- font-weight: var(--sv-font-weight-semibold);
60
- color: var(--sv-color-text-primary);
61
- }
62
-
63
- .action {
64
- flex-shrink: 0;
65
- }
66
-
67
- .closeButton {
68
- display: inline-flex;
69
- align-items: center;
70
- justify-content: center;
71
- width: var(--sv-touch-target-min, 44px);
72
- height: var(--sv-touch-target-min, 44px);
73
- flex-shrink: 0;
74
- /* Pull the touch-target padding back so the × sits flush with the row's own
75
- edge padding, same reasoning as .backButton above. */
76
- margin-right: calc(-1 * (var(--sv-touch-target-min, 44px) - var(--sv-icon-size-sm)) / 2);
77
- border: none;
78
- border-radius: var(--sv-radius-md);
79
- background: transparent;
80
- color: var(--sv-color-text-muted);
81
- cursor: pointer;
82
- }
83
-
84
- @media (hover: hover) {
85
- .closeButton:hover {
86
- background: var(--sv-color-surface-sunken);
87
- color: var(--sv-color-text-primary);
88
- }
89
- }
90
-
91
- .closeButton:focus-visible {
92
- outline: 2px solid var(--sv-color-focus-ring);
93
- outline-offset: -2px;
94
- }
95
-
96
- .secondRow {
97
- padding: 0 var(--sv-space-2) var(--sv-space-2);
98
- }
@@ -1,77 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- import { Icon } from '../Icon/Icon';
3
- import styles from './OverlayHeader.module.css';
4
-
5
- export interface OverlayHeaderProps {
6
- /** Overlay title, shown between the optional back button and the trailing
7
- * slots. Optional — some consumers (e.g. `Dialog`'s mobile bar) need the
8
- * row's close button present even when no title applies. Accepts any
9
- * `ReactNode`, not just a string — e.g. `Dialog`'s `header` prop passes
10
- * arbitrary content through here (an icon next to text, etc.); the
11
- * row's title slot still assumes single-line content sized like text
12
- * (see the component's own doc comment for the line this doesn't cross). */
13
- title?: ReactNode;
14
- /** Always renders a close button; called on click. */
15
- onClose: () => void;
16
- /** When provided, renders a back-chevron button before the title (for
17
- * hierarchical navigation within a single overlay — going back without
18
- * fully closing it). Omit for a flat overlay that only ever closes. */
19
- onBack?: () => void;
20
- /** Trailing slot next to the close button — e.g. a "Save" action. */
21
- action?: ReactNode;
22
- /** A second row below the title row — e.g. a tab strip. */
23
- secondRow?: ReactNode;
24
- className?: string;
25
- /** Override the title row's own className (e.g. tighter padding to match
26
- * a consumer's own compact header elsewhere in the same surface) — the
27
- * row keeps its standard title/back/action/close layout, just restyled.
28
- * For a genuinely different shape, don't use `OverlayHeader` at all (see
29
- * this component's own doc comment). */
30
- rowClassName?: string;
31
- /** Override the title text's own className (e.g. a smaller font size to
32
- * match a consumer's own compact header elsewhere in the same surface). */
33
- titleClassName?: string;
34
- }
35
-
36
- /**
37
- * OverlayHeader — the shared fixed secondary header for `Dialog`'s mobile
38
- * mode, `Sheet`, and `Drawer`: title + close (+ optional back button /
39
- * trailing action / tab-strip row). Not itself `position: sticky` or
40
- * `position: fixed` — it stays visually pinned because the consuming overlay
41
- * renders it as a non-scrolling flex sibling before its own scrollable
42
- * content region, the same technique `Dialog`'s `.mobileBar` already used
43
- * before this component existed to generalize it.
44
- *
45
- * Content that needs a fully custom header (e.g. an editable title, or
46
- * controls that aren't a simple title/back/action shape) should not use this
47
- * component — render its own header row instead; `Sheet`'s `title` prop is
48
- * optional specifically to leave that escape hatch open.
49
- */
50
- export function OverlayHeader({
51
- title,
52
- onClose,
53
- onBack,
54
- action,
55
- secondRow,
56
- className,
57
- rowClassName,
58
- titleClassName,
59
- }: OverlayHeaderProps) {
60
- return (
61
- <div className={[styles.header, className].filter(Boolean).join(' ')}>
62
- <div className={[styles.row, rowClassName].filter(Boolean).join(' ')}>
63
- {onBack && (
64
- <button type="button" className={styles.backButton} aria-label="Back" onClick={onBack}>
65
- <Icon name="chevron-left" size="md" aria-hidden />
66
- </button>
67
- )}
68
- <span className={[styles.title, titleClassName].filter(Boolean).join(' ')}>{title}</span>
69
- {action && <div className={styles.action}>{action}</div>}
70
- <button type="button" className={styles.closeButton} aria-label="Close" onClick={onClose}>
71
- <Icon name="x" size="sm" aria-hidden />
72
- </button>
73
- </div>
74
- {secondRow && <div className={styles.secondRow}>{secondRow}</div>}
75
- </div>
76
- );
77
- }
@@ -1,69 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it, vi } from 'vitest';
3
- import { cleanup, fireEvent, render, screen } from '@testing-library/react';
4
- import { OverlayHeader } from '../OverlayHeader';
5
-
6
- describe('OverlayHeader', () => {
7
- afterEach(cleanup);
8
-
9
- it('renders the title and calls onClose on the close button', () => {
10
- const onClose = vi.fn();
11
- render(<OverlayHeader title="Account" onClose={onClose} />);
12
- expect(screen.getByText('Account')).toBeTruthy();
13
- fireEvent.click(screen.getByRole('button', { name: 'Close' }));
14
- expect(onClose).toHaveBeenCalledOnce();
15
- });
16
-
17
- it('does not render a back button when onBack is omitted', () => {
18
- render(<OverlayHeader title="Account" onClose={() => {}} />);
19
- expect(screen.queryByRole('button', { name: 'Back' })).toBeNull();
20
- });
21
-
22
- it('renders and wires a back button when onBack is provided', () => {
23
- const onBack = vi.fn();
24
- render(<OverlayHeader title="Account" onClose={() => {}} onBack={onBack} />);
25
- fireEvent.click(screen.getByRole('button', { name: 'Back' }));
26
- expect(onBack).toHaveBeenCalledOnce();
27
- });
28
-
29
- it('renders the trailing action slot', () => {
30
- render(
31
- <OverlayHeader
32
- title="Edit list"
33
- onClose={() => {}}
34
- action={<button type="button">Save</button>}
35
- />,
36
- );
37
- expect(screen.getByRole('button', { name: 'Save' })).toBeTruthy();
38
- });
39
-
40
- it('renders just the close button when title is omitted', () => {
41
- const onClose = vi.fn();
42
- render(<OverlayHeader onClose={onClose} />);
43
- fireEvent.click(screen.getByRole('button', { name: 'Close' }));
44
- expect(onClose).toHaveBeenCalledOnce();
45
- });
46
-
47
- it('renders the second row', () => {
48
- render(<OverlayHeader title="Account" onClose={() => {}} secondRow={<nav>Tab strip</nav>} />);
49
- expect(screen.getByText('Tab strip')).toBeTruthy();
50
- });
51
-
52
- it('accepts arbitrary ReactNode content for title, not just a string', () => {
53
- // Locks in the type widening (title?: string -> title?: ReactNode) that
54
- // Dialog's `header` prop relies on (Dialog.tsx passes header through
55
- // here as `title`) — a plain string title must keep working unchanged.
56
- render(
57
- <OverlayHeader
58
- title={
59
- <>
60
- <strong>Card</strong> detail
61
- </>
62
- }
63
- onClose={() => {}}
64
- />,
65
- );
66
- expect(screen.getByText('Card').tagName).toBe('STRONG');
67
- expect(screen.getByText('detail')).toBeTruthy();
68
- });
69
- });