@sovereignfs/ui 0.54.0 → 0.89.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (473) hide show
  1. package/LICENSE +373 -661
  2. package/NOTICE +8 -0
  3. package/README.md +4 -6
  4. package/dist/Accordion.module.css +1 -1
  5. package/dist/Alert.module.css +1 -1
  6. package/dist/AppsLauncher.module.css +102 -0
  7. package/dist/Avatar.module.css +1 -1
  8. package/dist/Badge.module.css +30 -7
  9. package/dist/BalanceChip.module.css +1 -1
  10. package/dist/Button.module.css +23 -2
  11. package/dist/Card.module.css +7 -1
  12. package/dist/CardTile.module.css +187 -0
  13. package/dist/CheckableListRow.module.css +8 -0
  14. package/dist/Checkbox.module.css +8 -0
  15. package/dist/CodeTextarea.module.css +7 -1
  16. package/dist/Collapsible.module.css +1 -1
  17. package/dist/ColorPicker.module.css +138 -0
  18. package/dist/Combobox.module.css +8 -2
  19. package/dist/Command.module.css +7 -1
  20. package/dist/ConfirmDialog.module.css +8 -2
  21. package/dist/ConsentPrompt.module.css +21 -0
  22. package/dist/DatePicker.module.css +7 -1
  23. package/dist/Dialog.module.css +130 -21
  24. package/dist/DragHandleRow.module.css +6 -0
  25. package/dist/Drawer.module.css +36 -7
  26. package/dist/FileDropzone.module.css +25 -1
  27. package/dist/Header.module.css +68 -0
  28. package/dist/HeaderFooterLayout.module.css +21 -0
  29. package/dist/IconPicker.module.css +15 -5
  30. package/dist/Input.module.css +7 -1
  31. package/dist/Kbd.module.css +1 -1
  32. package/dist/LegalLinks.module.css +9 -2
  33. package/dist/Markdown.module.css +29 -0
  34. package/dist/Menu.module.css +1 -0
  35. package/dist/Message.module.css +10 -1
  36. package/dist/MessageScroller.module.css +12 -1
  37. package/dist/MobileAppsDrawer.module.css +19 -14
  38. package/dist/MobileFooter.module.css +7 -1
  39. package/dist/MobileHeader.module.css +14 -1
  40. package/dist/NavList.module.css +139 -0
  41. package/dist/NavTabs.module.css +8 -2
  42. package/dist/NotificationsPanel.module.css +268 -0
  43. package/dist/OverlayHeader.module.css +1 -1
  44. package/dist/PageContainer.module.css +62 -0
  45. package/dist/PageHeader.module.css +54 -0
  46. package/dist/PageLayout.module.css +51 -0
  47. package/dist/Popover.module.css +1 -1
  48. package/dist/QrCode.module.css +17 -0
  49. package/dist/QuantityStepper.module.css +5 -3
  50. package/dist/RadioGroup.module.css +6 -0
  51. package/dist/Resizable.module.css +3 -3
  52. package/dist/RootLayout.module.css +12 -0
  53. package/dist/SegmentedControl.module.css +7 -1
  54. package/dist/Select.module.css +7 -1
  55. package/dist/Sheet.module.css +20 -2
  56. package/dist/SplitPane.module.css +5 -5
  57. package/dist/StatusBadge.module.css +1 -1
  58. package/dist/StepStrip.module.css +55 -0
  59. package/dist/SuggestionInput.module.css +14 -3
  60. package/dist/SwipableMobileCarousel.module.css +12 -3
  61. package/dist/SwipableMobileCarouselDots.module.css +21 -0
  62. package/dist/SwipeStack.module.css +101 -0
  63. package/dist/SystemBanner.module.css +16 -0
  64. package/dist/Table.module.css +2 -2
  65. package/dist/Tabs.module.css +7 -1
  66. package/dist/TagInput.module.css +8 -2
  67. package/dist/Textarea.module.css +15 -1
  68. package/dist/ThreeColumnLayout.module.css +35 -0
  69. package/dist/Toast.module.css +67 -3
  70. package/dist/Toggle.module.css +7 -0
  71. package/dist/Tooltip.module.css +7 -1
  72. package/dist/UserMenu.module.css +95 -0
  73. package/dist/fonts/OFL.txt +93 -0
  74. package/dist/fonts/hanken-grotesk-cyrillic-ext-wght-normal.woff2 +0 -0
  75. package/dist/fonts/hanken-grotesk-latin-ext-wght-normal.woff2 +0 -0
  76. package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
  77. package/dist/fonts/hanken-grotesk-vietnamese-wght-normal.woff2 +0 -0
  78. package/dist/index.d.ts +1156 -76
  79. package/dist/index.js +4223 -1513
  80. package/dist/tokens/fonts.css +53 -0
  81. package/dist/tokens/primitives.css +23 -12
  82. package/dist/tokens/semantic.css +32 -0
  83. package/dist/tokens/theme-presets.css +33 -0
  84. package/dist/tokens.css +2 -1
  85. package/package.json +46 -19
  86. package/src/__tests__/motion.test.tsx +0 -105
  87. package/src/components/Accordion/Accordion.module.css +0 -3
  88. package/src/components/Accordion/Accordion.stories.tsx +0 -110
  89. package/src/components/Accordion/Accordion.tsx +0 -53
  90. package/src/components/Accordion/__tests__/Accordion.test.tsx +0 -61
  91. package/src/components/Alert/Alert.module.css +0 -62
  92. package/src/components/Alert/Alert.stories.tsx +0 -96
  93. package/src/components/Alert/Alert.tsx +0 -58
  94. package/src/components/Alert/__tests__/Alert.test.tsx +0 -75
  95. package/src/components/AspectRatio/AspectRatio.module.css +0 -15
  96. package/src/components/AspectRatio/AspectRatio.stories.tsx +0 -78
  97. package/src/components/AspectRatio/AspectRatio.tsx +0 -21
  98. package/src/components/AspectRatio/__tests__/AspectRatio.test.tsx +0 -27
  99. package/src/components/Avatar/Avatar.module.css +0 -38
  100. package/src/components/Avatar/Avatar.tsx +0 -42
  101. package/src/components/Badge/Badge.module.css +0 -154
  102. package/src/components/Badge/Badge.stories.tsx +0 -226
  103. package/src/components/Badge/Badge.tsx +0 -81
  104. package/src/components/Badge/__tests__/Badge.test.tsx +0 -88
  105. package/src/components/BalanceChip/BalanceChip.module.css +0 -32
  106. package/src/components/BalanceChip/BalanceChip.stories.tsx +0 -45
  107. package/src/components/BalanceChip/BalanceChip.tsx +0 -33
  108. package/src/components/Breadcrumb/Breadcrumb.module.css +0 -49
  109. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -47
  110. package/src/components/Breadcrumb/Breadcrumb.tsx +0 -57
  111. package/src/components/Breadcrumb/__tests__/Breadcrumb.test.tsx +0 -52
  112. package/src/components/Button/Button.module.css +0 -153
  113. package/src/components/Button/Button.stories.tsx +0 -83
  114. package/src/components/Button/Button.tsx +0 -52
  115. package/src/components/Button/__tests__/Button.test.tsx +0 -66
  116. package/src/components/ButtonGroup/ButtonGroup.module.css +0 -29
  117. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -57
  118. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -27
  119. package/src/components/ButtonGroup/__tests__/ButtonGroup.test.tsx +0 -29
  120. package/src/components/Calendar/Calendar.module.css +0 -126
  121. package/src/components/Calendar/Calendar.tsx +0 -213
  122. package/src/components/Calendar/__tests__/Calendar.test.tsx +0 -98
  123. package/src/components/Calendar/dateUtils.ts +0 -97
  124. package/src/components/Card/Card.module.css +0 -42
  125. package/src/components/Card/Card.tsx +0 -34
  126. package/src/components/CheckableListRow/CheckableListRow.module.css +0 -95
  127. package/src/components/CheckableListRow/CheckableListRow.stories.tsx +0 -99
  128. package/src/components/CheckableListRow/CheckableListRow.tsx +0 -89
  129. package/src/components/Checkbox/Checkbox.module.css +0 -111
  130. package/src/components/Checkbox/Checkbox.tsx +0 -78
  131. package/src/components/CodeTextarea/CodeTextarea.module.css +0 -53
  132. package/src/components/CodeTextarea/CodeTextarea.stories.tsx +0 -77
  133. package/src/components/CodeTextarea/CodeTextarea.tsx +0 -36
  134. package/src/components/Collapsible/Collapsible.module.css +0 -70
  135. package/src/components/Collapsible/Collapsible.stories.tsx +0 -62
  136. package/src/components/Collapsible/Collapsible.tsx +0 -66
  137. package/src/components/Collapsible/__tests__/Collapsible.test.tsx +0 -71
  138. package/src/components/Combobox/Combobox.module.css +0 -122
  139. package/src/components/Combobox/Combobox.stories.tsx +0 -79
  140. package/src/components/Combobox/Combobox.tsx +0 -186
  141. package/src/components/Combobox/__tests__/Combobox.test.tsx +0 -158
  142. package/src/components/Command/Command.module.css +0 -80
  143. package/src/components/Command/Command.stories.tsx +0 -104
  144. package/src/components/Command/Command.tsx +0 -168
  145. package/src/components/Command/__tests__/Command.test.tsx +0 -162
  146. package/src/components/ConfirmDialog/ConfirmDialog.module.css +0 -113
  147. package/src/components/ConfirmDialog/ConfirmDialog.tsx +0 -124
  148. package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +0 -146
  149. package/src/components/ContextMenu/ContextMenu.stories.tsx +0 -81
  150. package/src/components/ContextMenu/ContextMenu.tsx +0 -100
  151. package/src/components/ContextMenu/__tests__/ContextMenu.test.tsx +0 -87
  152. package/src/components/CurrencyInput/CurrencyInput.stories.tsx +0 -50
  153. package/src/components/CurrencyInput/CurrencyInput.tsx +0 -60
  154. package/src/components/DataTable/DataTable.module.css +0 -28
  155. package/src/components/DataTable/DataTable.stories.tsx +0 -74
  156. package/src/components/DataTable/DataTable.tsx +0 -154
  157. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -123
  158. package/src/components/DatePicker/DatePicker.module.css +0 -61
  159. package/src/components/DatePicker/DatePicker.tsx +0 -103
  160. package/src/components/DatePicker/__tests__/DatePicker.test.tsx +0 -89
  161. package/src/components/DeviceOnlyGate/DeviceOnlyGate.tsx +0 -58
  162. package/src/components/DeviceOnlyGate/__tests__/DeviceOnlyGate.test.tsx +0 -45
  163. package/src/components/DeviceStorageKeyGate/DeviceStorageKeyGate.tsx +0 -100
  164. package/src/components/DeviceStorageKeyGate/__tests__/DeviceStorageKeyGate.test.tsx +0 -119
  165. package/src/components/Dialog/Dialog.module.css +0 -226
  166. package/src/components/Dialog/Dialog.stories.tsx +0 -147
  167. package/src/components/Dialog/Dialog.tsx +0 -160
  168. package/src/components/Dialog/__tests__/Dialog.test.tsx +0 -137
  169. package/src/components/DragHandleRow/DragHandleRow.module.css +0 -57
  170. package/src/components/DragHandleRow/DragHandleRow.tsx +0 -61
  171. package/src/components/Drawer/Drawer.module.css +0 -92
  172. package/src/components/Drawer/Drawer.stories.tsx +0 -132
  173. package/src/components/Drawer/Drawer.tsx +0 -176
  174. package/src/components/Drawer/__tests__/Drawer.test.tsx +0 -199
  175. package/src/components/EmptyState/EmptyState.module.css +0 -27
  176. package/src/components/EmptyState/EmptyState.tsx +0 -27
  177. package/src/components/FileDropzone/FileDropzone.module.css +0 -63
  178. package/src/components/FileDropzone/FileDropzone.tsx +0 -109
  179. package/src/components/FileDropzone/__tests__/FileDropzone.test.tsx +0 -67
  180. package/src/components/FormField/FormField.module.css +0 -33
  181. package/src/components/FormField/FormField.tsx +0 -78
  182. package/src/components/FormField/__tests__/FormField.test.tsx +0 -83
  183. package/src/components/HoverCard/HoverCard.module.css +0 -3
  184. package/src/components/HoverCard/HoverCard.stories.tsx +0 -66
  185. package/src/components/HoverCard/HoverCard.tsx +0 -111
  186. package/src/components/HoverCard/__tests__/HoverCard.test.tsx +0 -99
  187. package/src/components/Icon/Icon.module.css +0 -27
  188. package/src/components/Icon/Icon.stories.tsx +0 -95
  189. package/src/components/Icon/Icon.tsx +0 -43
  190. package/src/components/Icon/__tests__/Icon.test.tsx +0 -40
  191. package/src/components/Icon/icons/activity.tsx +0 -20
  192. package/src/components/Icon/icons/alert-triangle.tsx +0 -22
  193. package/src/components/Icon/icons/apple.tsx +0 -21
  194. package/src/components/Icon/icons/banana.tsx +0 -21
  195. package/src/components/Icon/icons/beef.tsx +0 -22
  196. package/src/components/Icon/icons/beer.tsx +0 -24
  197. package/src/components/Icon/icons/bell.tsx +0 -21
  198. package/src/components/Icon/icons/calendar.tsx +0 -23
  199. package/src/components/Icon/icons/candy.tsx +0 -24
  200. package/src/components/Icon/icons/carrot.tsx +0 -22
  201. package/src/components/Icon/icons/check.tsx +0 -20
  202. package/src/components/Icon/icons/chevron-down.tsx +0 -20
  203. package/src/components/Icon/icons/chevron-left.tsx +0 -20
  204. package/src/components/Icon/icons/chevron-right.tsx +0 -20
  205. package/src/components/Icon/icons/chevron-up.tsx +0 -20
  206. package/src/components/Icon/icons/circle-check.tsx +0 -21
  207. package/src/components/Icon/icons/circle-x.tsx +0 -22
  208. package/src/components/Icon/icons/coffee.tsx +0 -23
  209. package/src/components/Icon/icons/cookie.tsx +0 -25
  210. package/src/components/Icon/icons/croissant.tsx +0 -24
  211. package/src/components/Icon/icons/cup-soda.tsx +0 -23
  212. package/src/components/Icon/icons/drumstick.tsx +0 -21
  213. package/src/components/Icon/icons/egg.tsx +0 -20
  214. package/src/components/Icon/icons/ellipsis-vertical.tsx +0 -22
  215. package/src/components/Icon/icons/external-link.tsx +0 -22
  216. package/src/components/Icon/icons/eye-off.tsx +0 -23
  217. package/src/components/Icon/icons/eye.tsx +0 -21
  218. package/src/components/Icon/icons/file.tsx +0 -21
  219. package/src/components/Icon/icons/fish.tsx +0 -25
  220. package/src/components/Icon/icons/grid-2x2.tsx +0 -22
  221. package/src/components/Icon/icons/house.tsx +0 -21
  222. package/src/components/Icon/icons/index.ts +0 -234
  223. package/src/components/Icon/icons/info.tsx +0 -22
  224. package/src/components/Icon/icons/lock.tsx +0 -21
  225. package/src/components/Icon/icons/log-out.tsx +0 -22
  226. package/src/components/Icon/icons/mail.tsx +0 -21
  227. package/src/components/Icon/icons/menu.tsx +0 -22
  228. package/src/components/Icon/icons/milk.tsx +0 -22
  229. package/src/components/Icon/icons/package.tsx +0 -23
  230. package/src/components/Icon/icons/pencil.tsx +0 -21
  231. package/src/components/Icon/icons/pizza.tsx +0 -24
  232. package/src/components/Icon/icons/plus.tsx +0 -21
  233. package/src/components/Icon/icons/rotate-ccw.tsx +0 -21
  234. package/src/components/Icon/icons/salad.tsx +0 -24
  235. package/src/components/Icon/icons/search.tsx +0 -21
  236. package/src/components/Icon/icons/settings.tsx +0 -21
  237. package/src/components/Icon/icons/shield.tsx +0 -20
  238. package/src/components/Icon/icons/shopping-basket.tsx +0 -26
  239. package/src/components/Icon/icons/sliders-horizontal.tsx +0 -28
  240. package/src/components/Icon/icons/smartphone.tsx +0 -21
  241. package/src/components/Icon/icons/snowflake.tsx +0 -31
  242. package/src/components/Icon/icons/spray-can.tsx +0 -29
  243. package/src/components/Icon/icons/trash-2.tsx +0 -24
  244. package/src/components/Icon/icons/upload.tsx +0 -22
  245. package/src/components/Icon/icons/user.tsx +0 -21
  246. package/src/components/Icon/icons/wine.tsx +0 -23
  247. package/src/components/Icon/icons/x.tsx +0 -21
  248. package/src/components/IconPicker/IconPicker.module.css +0 -63
  249. package/src/components/IconPicker/IconPicker.stories.tsx +0 -84
  250. package/src/components/IconPicker/IconPicker.tsx +0 -90
  251. package/src/components/Input/Input.module.css +0 -52
  252. package/src/components/Input/Input.stories.tsx +0 -86
  253. package/src/components/Input/Input.tsx +0 -14
  254. package/src/components/Input/__tests__/Input.test.tsx +0 -22
  255. package/src/components/Item/Item.module.css +0 -70
  256. package/src/components/Item/Item.stories.tsx +0 -62
  257. package/src/components/Item/Item.tsx +0 -54
  258. package/src/components/Item/__tests__/Item.test.tsx +0 -39
  259. package/src/components/Kbd/Kbd.module.css +0 -14
  260. package/src/components/Kbd/Kbd.stories.tsx +0 -32
  261. package/src/components/Kbd/Kbd.tsx +0 -12
  262. package/src/components/Kbd/__tests__/Kbd.test.tsx +0 -14
  263. package/src/components/Label/Label.module.css +0 -11
  264. package/src/components/Label/Label.stories.tsx +0 -40
  265. package/src/components/Label/Label.tsx +0 -24
  266. package/src/components/Label/__tests__/Label.test.tsx +0 -32
  267. package/src/components/LegalLinks/LegalLinks.module.css +0 -24
  268. package/src/components/LegalLinks/LegalLinks.stories.tsx +0 -22
  269. package/src/components/LegalLinks/LegalLinks.tsx +0 -40
  270. package/src/components/Markdown/Markdown.module.css +0 -49
  271. package/src/components/Markdown/Markdown.stories.tsx +0 -30
  272. package/src/components/Markdown/Markdown.tsx +0 -168
  273. package/src/components/Marker/Marker.module.css +0 -33
  274. package/src/components/Marker/Marker.stories.tsx +0 -39
  275. package/src/components/Marker/Marker.tsx +0 -34
  276. package/src/components/Marker/__tests__/Marker.test.tsx +0 -23
  277. package/src/components/MemberMultiSelect/MemberMultiSelect.module.css +0 -27
  278. package/src/components/MemberMultiSelect/MemberMultiSelect.stories.tsx +0 -74
  279. package/src/components/MemberMultiSelect/MemberMultiSelect.tsx +0 -67
  280. package/src/components/Menu/Menu.module.css +0 -89
  281. package/src/components/Menu/Menu.tsx +0 -159
  282. package/src/components/Menu/__tests__/Menu.test.tsx +0 -197
  283. package/src/components/Menubar/Menubar.stories.tsx +0 -52
  284. package/src/components/Menubar/Menubar.tsx +0 -42
  285. package/src/components/Menubar/__tests__/Menubar.test.tsx +0 -45
  286. package/src/components/Message/Message.module.css +0 -99
  287. package/src/components/Message/Message.stories.tsx +0 -79
  288. package/src/components/Message/Message.tsx +0 -41
  289. package/src/components/Message/__tests__/Message.test.tsx +0 -46
  290. package/src/components/MessageScroller/MessageScroller.module.css +0 -54
  291. package/src/components/MessageScroller/MessageScroller.stories.tsx +0 -84
  292. package/src/components/MessageScroller/MessageScroller.tsx +0 -72
  293. package/src/components/MessageScroller/__tests__/MessageScroller.test.tsx +0 -105
  294. package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +0 -81
  295. package/src/components/MobileAppsDrawer/MobileAppsDrawer.tsx +0 -78
  296. package/src/components/MobileAppsDrawer/__tests__/MobileAppsDrawer.test.tsx +0 -80
  297. package/src/components/MobileFooter/MobileFooter.module.css +0 -73
  298. package/src/components/MobileFooter/MobileFooter.stories.tsx +0 -47
  299. package/src/components/MobileFooter/MobileFooter.tsx +0 -109
  300. package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +0 -71
  301. package/src/components/MobileHeader/MobileHeader.module.css +0 -63
  302. package/src/components/MobileHeader/MobileHeader.stories.tsx +0 -57
  303. package/src/components/MobileHeader/MobileHeader.tsx +0 -77
  304. package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +0 -58
  305. package/src/components/NavTabs/NavTabs.module.css +0 -50
  306. package/src/components/NavTabs/NavTabs.tsx +0 -61
  307. package/src/components/NavigationMenu/NavigationMenu.module.css +0 -53
  308. package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -58
  309. package/src/components/NavigationMenu/NavigationMenu.tsx +0 -125
  310. package/src/components/NavigationMenu/__tests__/NavigationMenu.test.tsx +0 -93
  311. package/src/components/OfflineGate/OfflineGate.tsx +0 -44
  312. package/src/components/OfflineGate/__tests__/OfflineGate.test.tsx +0 -66
  313. package/src/components/OverlayHeader/OverlayHeader.module.css +0 -98
  314. package/src/components/OverlayHeader/OverlayHeader.tsx +0 -62
  315. package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +0 -51
  316. package/src/components/PageContainer/PageContainer.module.css +0 -20
  317. package/src/components/PageContainer/PageContainer.tsx +0 -31
  318. package/src/components/PageContainer/__tests__/PageContainer.test.tsx +0 -37
  319. package/src/components/PageHeader/PageHeader.module.css +0 -32
  320. package/src/components/PageHeader/PageHeader.tsx +0 -35
  321. package/src/components/Pagination/Pagination.module.css +0 -98
  322. package/src/components/Pagination/Pagination.stories.tsx +0 -49
  323. package/src/components/Pagination/Pagination.tsx +0 -87
  324. package/src/components/Pagination/__tests__/Pagination.test.tsx +0 -56
  325. package/src/components/Popover/Popover.module.css +0 -74
  326. package/src/components/Popover/Popover.stories.tsx +0 -357
  327. package/src/components/Popover/Popover.tsx +0 -208
  328. package/src/components/Popover/__tests__/Popover.test.tsx +0 -98
  329. package/src/components/Progress/Progress.module.css +0 -20
  330. package/src/components/Progress/Progress.stories.tsx +0 -40
  331. package/src/components/Progress/Progress.tsx +0 -35
  332. package/src/components/Progress/__tests__/Progress.test.tsx +0 -31
  333. package/src/components/QuantityStepper/QuantityStepper.module.css +0 -67
  334. package/src/components/QuantityStepper/QuantityStepper.stories.tsx +0 -79
  335. package/src/components/QuantityStepper/QuantityStepper.tsx +0 -107
  336. package/src/components/RadioGroup/RadioGroup.module.css +0 -88
  337. package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -69
  338. package/src/components/RadioGroup/RadioGroup.tsx +0 -99
  339. package/src/components/RadioGroup/__tests__/RadioGroup.test.tsx +0 -59
  340. package/src/components/Resizable/Resizable.module.css +0 -70
  341. package/src/components/Resizable/Resizable.stories.tsx +0 -82
  342. package/src/components/Resizable/Resizable.tsx +0 -313
  343. package/src/components/Resizable/__tests__/Resizable.test.tsx +0 -128
  344. package/src/components/ResponsiveSurface/ResponsiveSurface.tsx +0 -24
  345. package/src/components/ResponsiveSurface/__tests__/ResponsiveSurface.test.tsx +0 -73
  346. package/src/components/ScrollArea/ScrollArea.module.css +0 -20
  347. package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -57
  348. package/src/components/ScrollArea/ScrollArea.tsx +0 -27
  349. package/src/components/ScrollArea/__tests__/ScrollArea.test.tsx +0 -39
  350. package/src/components/SegmentedControl/SegmentedControl.module.css +0 -55
  351. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -118
  352. package/src/components/SegmentedControl/SegmentedControl.tsx +0 -56
  353. package/src/components/SegmentedControl/__tests__/SegmentedControl.test.tsx +0 -63
  354. package/src/components/Select/Select.module.css +0 -82
  355. package/src/components/Select/Select.stories.tsx +0 -115
  356. package/src/components/Select/Select.tsx +0 -48
  357. package/src/components/Select/__tests__/Select.test.tsx +0 -59
  358. package/src/components/Sheet/Sheet.module.css +0 -55
  359. package/src/components/Sheet/Sheet.tsx +0 -109
  360. package/src/components/Sheet/__tests__/Sheet.test.tsx +0 -99
  361. package/src/components/Slider/Slider.module.css +0 -95
  362. package/src/components/Slider/Slider.stories.tsx +0 -64
  363. package/src/components/Slider/Slider.tsx +0 -77
  364. package/src/components/Slider/__tests__/Slider.test.tsx +0 -45
  365. package/src/components/Spinner/Spinner.module.css +0 -39
  366. package/src/components/Spinner/Spinner.tsx +0 -23
  367. package/src/components/SplitMethodSelector/SplitMethodSelector.stories.tsx +0 -33
  368. package/src/components/SplitMethodSelector/SplitMethodSelector.tsx +0 -43
  369. package/src/components/SplitPane/SplitPane.module.css +0 -85
  370. package/src/components/SplitPane/SplitPane.stories.tsx +0 -160
  371. package/src/components/SplitPane/SplitPane.tsx +0 -149
  372. package/src/components/SplitPane/__tests__/SplitPane.test.tsx +0 -51
  373. package/src/components/StatusBadge/StatusBadge.module.css +0 -59
  374. package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -74
  375. package/src/components/StatusBadge/StatusBadge.tsx +0 -65
  376. package/src/components/SuggestionInput/SuggestionInput.module.css +0 -103
  377. package/src/components/SuggestionInput/SuggestionInput.stories.tsx +0 -144
  378. package/src/components/SuggestionInput/SuggestionInput.tsx +0 -207
  379. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +0 -55
  380. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +0 -227
  381. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlide.tsx +0 -35
  382. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody.tsx +0 -42
  383. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideFooter.tsx +0 -18
  384. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader.tsx +0 -21
  385. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideParts.module.css +0 -29
  386. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +0 -133
  387. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarouselDevGuard.test.tsx +0 -61
  388. package/src/components/SwipableMobileCarousel/context.ts +0 -13
  389. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +0 -49
  390. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +0 -62
  391. package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +0 -63
  392. package/src/components/SystemBanner/SystemBanner.module.css +0 -69
  393. package/src/components/SystemBanner/SystemBanner.stories.tsx +0 -86
  394. package/src/components/SystemBanner/SystemBanner.tsx +0 -50
  395. package/src/components/SystemBanner/__tests__/SystemBanner.test.tsx +0 -50
  396. package/src/components/Table/Table.module.css +0 -45
  397. package/src/components/Table/Table.stories.tsx +0 -125
  398. package/src/components/Table/Table.tsx +0 -51
  399. package/src/components/Table/__tests__/Table.test.tsx +0 -50
  400. package/src/components/Tabs/Tabs.module.css +0 -56
  401. package/src/components/Tabs/Tabs.stories.tsx +0 -100
  402. package/src/components/Tabs/Tabs.tsx +0 -46
  403. package/src/components/Tabs/__tests__/Tabs.test.tsx +0 -45
  404. package/src/components/TagInput/TagInput.module.css +0 -141
  405. package/src/components/TagInput/TagInput.stories.tsx +0 -109
  406. package/src/components/TagInput/TagInput.tsx +0 -174
  407. package/src/components/TagInput/__tests__/TagInput.test.tsx +0 -69
  408. package/src/components/Textarea/Textarea.module.css +0 -39
  409. package/src/components/Textarea/Textarea.tsx +0 -15
  410. package/src/components/Textarea/__tests__/Textarea.test.tsx +0 -29
  411. package/src/components/Toast/Toast.module.css +0 -132
  412. package/src/components/Toast/Toast.stories.tsx +0 -191
  413. package/src/components/Toast/Toast.tsx +0 -139
  414. package/src/components/Toggle/Toggle.module.css +0 -57
  415. package/src/components/Toggle/Toggle.stories.tsx +0 -95
  416. package/src/components/Toggle/Toggle.tsx +0 -39
  417. package/src/components/Toggle/__tests__/Toggle.test.tsx +0 -47
  418. package/src/components/Tooltip/Tooltip.module.css +0 -56
  419. package/src/components/Tooltip/Tooltip.tsx +0 -30
  420. package/src/components/Typography/Typography.module.css +0 -47
  421. package/src/components/Typography/Typography.stories.tsx +0 -62
  422. package/src/components/Typography/Typography.tsx +0 -30
  423. package/src/components/Typography/__tests__/Typography.test.tsx +0 -34
  424. package/src/css-modules.d.ts +0 -4
  425. package/src/hooks/__tests__/useCarouselRouteSync.test.tsx +0 -126
  426. package/src/hooks/__tests__/useDoubleTap.test.tsx +0 -117
  427. package/src/hooks/__tests__/useIsMobile.test.tsx +0 -80
  428. package/src/hooks/__tests__/useIsOffline.test.tsx +0 -53
  429. package/src/hooks/__tests__/useLongPress.test.tsx +0 -158
  430. package/src/hooks/__tests__/useOfflineTileState.test.tsx +0 -69
  431. package/src/hooks/__tests__/useResponsiveLayout.test.tsx +0 -87
  432. package/src/hooks/__tests__/useSnapCarousel.test.tsx +0 -93
  433. package/src/hooks/__tests__/useSwipeReveal.test.tsx +0 -110
  434. package/src/hooks/index.ts +0 -24
  435. package/src/hooks/useCarouselRouteSync.ts +0 -92
  436. package/src/hooks/useCommitOnEnterOrBlur.ts +0 -39
  437. package/src/hooks/useDoubleTap.ts +0 -91
  438. package/src/hooks/useIsMobile.ts +0 -33
  439. package/src/hooks/useIsOffline.ts +0 -41
  440. package/src/hooks/useLongPress.ts +0 -185
  441. package/src/hooks/useOfflineTileState.ts +0 -45
  442. package/src/hooks/useResponsiveLayout.ts +0 -36
  443. package/src/hooks/useSnapCarousel.ts +0 -79
  444. package/src/hooks/useSwipeReveal.ts +0 -107
  445. package/src/index.ts +0 -251
  446. package/src/motion.ts +0 -78
  447. package/src/overlay-shell.ts +0 -94
  448. package/src/scroll-lock.ts +0 -22
  449. package/src/stories/Avatar.stories.tsx +0 -44
  450. package/src/stories/Card.stories.tsx +0 -35
  451. package/src/stories/Checkbox.stories.tsx +0 -45
  452. package/src/stories/DesignSystemOverview.stories.tsx +0 -3187
  453. package/src/stories/DeviceOnlyGate.stories.tsx +0 -35
  454. package/src/stories/DeviceStorageKeyGate.stories.tsx +0 -57
  455. package/src/stories/DragHandleRow.stories.tsx +0 -41
  456. package/src/stories/EmptyState.stories.tsx +0 -33
  457. package/src/stories/FileDropzone.stories.tsx +0 -69
  458. package/src/stories/FormField.stories.tsx +0 -47
  459. package/src/stories/InteractionHooks.stories.tsx +0 -925
  460. package/src/stories/MobilePatterns.stories.tsx +0 -1536
  461. package/src/stories/NavTabs.stories.tsx +0 -53
  462. package/src/stories/OfflineGate.stories.tsx +0 -42
  463. package/src/stories/PageContainer.stories.tsx +0 -37
  464. package/src/stories/PageHeader.stories.tsx +0 -42
  465. package/src/stories/ResponsiveSurface.stories.tsx +0 -47
  466. package/src/stories/Spinner.stories.tsx +0 -25
  467. package/src/stories/SwipableMobileCarousel.stories.tsx +0 -304
  468. package/src/stories/Textarea.stories.tsx +0 -51
  469. package/src/stories/TokenGallery.stories.tsx +0 -602
  470. package/src/stories/Tooltip.stories.tsx +0 -59
  471. package/src/tokens/primitives.css +0 -157
  472. package/src/tokens/semantic.css +0 -130
  473. package/src/tokens.css +0 -5
@@ -1,73 +0,0 @@
1
- .footer {
2
- display: flex;
3
- align-items: center;
4
- width: 100%;
5
- /* Mobile-only component — never render wider than the platform's own
6
- mobile breakpoint, even if a consumer accidentally mounts it in a wider
7
- container (e.g. an un-gated preview). At real mobile widths this is a
8
- no-op since the viewport itself is already narrower. */
9
- max-width: 768px;
10
- margin-inline: auto;
11
- min-height: var(--sv-shell-footer-height, 60px);
12
- padding: 0 var(--sv-space-4);
13
- padding-bottom: max(var(--sv-space-2), env(safe-area-inset-bottom));
14
- background-color: var(--sv-color-surface);
15
- border-top: 1px solid var(--sv-color-border);
16
- position: relative;
17
- z-index: 101;
18
- }
19
-
20
- .navItem {
21
- display: flex;
22
- align-items: center;
23
- justify-content: center;
24
- flex: 1;
25
- min-height: 52px;
26
- border: none;
27
- background: transparent;
28
- color: var(--sv-color-text-muted);
29
- font: inherit;
30
- cursor: pointer;
31
- text-decoration: none;
32
- border-radius: var(--sv-radius-md);
33
- transition: color 0.1s;
34
- outline: none;
35
- }
36
-
37
- @media (hover: hover) {
38
- .navItem:hover {
39
- color: var(--sv-color-text-primary);
40
- }
41
- }
42
-
43
- .navItem:focus-visible {
44
- outline: 2px solid var(--sv-color-focus-ring);
45
- outline-offset: -2px;
46
- }
47
-
48
- .navItemActive {
49
- color: var(--sv-color-text-primary);
50
- }
51
-
52
- .navItemApps {
53
- position: relative;
54
- }
55
-
56
- .navItemAppsOpen {
57
- color: var(--sv-color-text-primary);
58
- }
59
-
60
- .navItemAppsOpen::before {
61
- content: '';
62
- position: absolute;
63
- width: 48px;
64
- height: 48px;
65
- border-radius: var(--sv-radius-full);
66
- background: var(--sv-color-surface-sunken);
67
- }
68
-
69
- .navItemAppsOpen svg,
70
- .navItemAppsOpen img {
71
- position: relative;
72
- z-index: 1;
73
- }
@@ -1,47 +0,0 @@
1
- import { useState } from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { MobileFooter } from './MobileFooter';
4
- import { Icon } from '../Icon/Icon';
5
-
6
- const homeIcon = { icon: <Icon name="house" size="md" aria-hidden />, label: 'Home', active: true };
7
- const searchIcon = { icon: <Icon name="search" size="md" aria-hidden />, label: 'Search' };
8
- const calendarIcon = { icon: <Icon name="calendar" size="md" aria-hidden />, label: 'Calendar' };
9
- const activityIcon = { icon: <Icon name="activity" size="md" aria-hidden />, label: 'Activity' };
10
-
11
- const meta = {
12
- title: 'Components/MobileFooter',
13
- component: MobileFooter,
14
- parameters: {
15
- layout: 'padded',
16
- docs: {
17
- description: {
18
- component:
19
- 'Mobile shell footer nav row (RFC 0088). The centered launcher (onOpenApps) is always rendered; leftIcons/rightIcons take 1 or 2 items each, symmetric so the launcher stays centered. Presentational only, no data fetching.',
20
- },
21
- },
22
- },
23
- args: {
24
- onOpenApps: () => {},
25
- leftIcons: [homeIcon],
26
- rightIcons: [searchIcon],
27
- },
28
- } satisfies Meta<typeof MobileFooter>;
29
-
30
- export default meta;
31
- type Story = StoryObj<typeof meta>;
32
-
33
- export const Default: Story = {};
34
-
35
- export const FiveIcons: Story = {
36
- args: {
37
- leftIcons: [homeIcon, calendarIcon],
38
- rightIcons: [searchIcon, activityIcon],
39
- },
40
- };
41
-
42
- export const LauncherOpen: Story = {
43
- render: function Render(args) {
44
- const [open, setOpen] = useState(true);
45
- return <MobileFooter {...args} launcherOpen={open} onOpenApps={() => setOpen((v) => !v)} />;
46
- },
47
- };
@@ -1,109 +0,0 @@
1
- import type { HTMLAttributes, ReactNode } from 'react';
2
- import { Icon } from '../Icon/Icon';
3
- import styles from './MobileFooter.module.css';
4
-
5
- export interface FooterIcon {
6
- icon: ReactNode;
7
- label: string;
8
- href?: string;
9
- onClick?: () => void;
10
- active?: boolean;
11
- }
12
-
13
- export interface MobileFooterProps extends HTMLAttributes<HTMLElement> {
14
- /** Opens the app drawer/launcher. Always rendered as the centered slot;
15
- * not overridable. */
16
- onOpenApps: () => void;
17
- /** Custom launcher icon (e.g. a plugin-supplied image). Defaults to a
18
- * generic grid icon. */
19
- launcherIcon?: ReactNode;
20
- /** Whether the launcher's own drawer is currently open (applies the
21
- * pressed/active visual state). */
22
- launcherOpen?: boolean;
23
- /** 1 or 2 icons rendered to the left of the centered launcher. */
24
- leftIcons: FooterIcon[];
25
- /** 1 or 2 icons rendered to the right of the centered launcher. Must match
26
- * `leftIcons.length` — the launcher stays visually centered, so a mismatch
27
- * is flagged (dev-mode only, never thrown) rather than silently allowed. */
28
- rightIcons: FooterIcon[];
29
- }
30
-
31
- function FooterNavItem({ icon, label, href, onClick, active }: FooterIcon) {
32
- const className = [styles.navItem, active ? styles.navItemActive : ''].filter(Boolean).join(' ');
33
- if (href) {
34
- return (
35
- <a
36
- href={href}
37
- className={className}
38
- aria-label={label}
39
- aria-current={active ? 'page' : undefined}
40
- >
41
- {icon}
42
- </a>
43
- );
44
- }
45
- return (
46
- <button type="button" className={className} aria-label={label} onClick={onClick}>
47
- {icon}
48
- </button>
49
- );
50
- }
51
-
52
- /**
53
- * The mobile footer bar: a centered, fixed "Apps" launcher flanked by 1 or 2
54
- * overridable icons on each side (3 or 5 total, matching standard
55
- * iOS/Android bottom-nav conventions). Owns its own chrome — background,
56
- * border-top, safe-area-aware bottom padding, and a 768px max-width (so it
57
- * never stretches full-bleed if mounted outside an actual mobile viewport)
58
- * — matching the runtime shell's own mobile footer (MobileNav) exactly,
59
- * since this component is meant to replace that hand-rolled markup.
60
- * Presentational only — no data fetching; the consumer owns the
61
- * drawer/overlay `onOpenApps` opens. See RFC 0088 for the
62
- * immutable/overridable boundary this enforces.
63
- */
64
- export function MobileFooter({
65
- onOpenApps,
66
- launcherIcon,
67
- launcherOpen,
68
- leftIcons,
69
- rightIcons,
70
- className,
71
- ...rest
72
- }: MobileFooterProps) {
73
- if (process.env.NODE_ENV !== 'production' && leftIcons.length !== rightIcons.length) {
74
- console.error(
75
- `MobileFooter: leftIcons (${leftIcons.length}) and rightIcons (${rightIcons.length}) ` +
76
- 'must have the same length so the launcher stays visually centered.',
77
- );
78
- }
79
-
80
- const cls = [styles.footer, className].filter(Boolean).join(' ');
81
- const launcherClassName = [
82
- styles.navItem,
83
- styles.navItemApps,
84
- launcherOpen ? styles.navItemAppsOpen : '',
85
- ]
86
- .filter(Boolean)
87
- .join(' ');
88
-
89
- return (
90
- <nav {...rest} className={cls} aria-label="App navigation">
91
- {leftIcons.map((item) => (
92
- <FooterNavItem key={item.label} {...item} />
93
- ))}
94
- <button
95
- type="button"
96
- className={launcherClassName}
97
- aria-label="Apps"
98
- aria-expanded={launcherOpen}
99
- aria-haspopup="dialog"
100
- onClick={onOpenApps}
101
- >
102
- {launcherIcon ?? <Icon name="grid-2x2" size="md" aria-hidden />}
103
- </button>
104
- {rightIcons.map((item) => (
105
- <FooterNavItem key={item.label} {...item} />
106
- ))}
107
- </nav>
108
- );
109
- }
@@ -1,71 +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 { MobileFooter } from '../MobileFooter';
5
-
6
- afterEach(() => {
7
- cleanup();
8
- vi.unstubAllEnvs();
9
- vi.restoreAllMocks();
10
- });
11
-
12
- const oneIcon = [{ icon: <span>icon</span>, label: 'Home' }];
13
- const twoIcons = [
14
- { icon: <span>icon</span>, label: 'Home' },
15
- { icon: <span>icon</span>, label: 'Calendar' },
16
- ];
17
- const leftTwo = [
18
- { icon: <span>icon</span>, label: 'Home' },
19
- { icon: <span>icon</span>, label: 'Calendar' },
20
- ];
21
- const rightTwo = [
22
- { icon: <span>icon</span>, label: 'Search' },
23
- { icon: <span>icon</span>, label: 'Activity' },
24
- ];
25
-
26
- describe('MobileFooter', () => {
27
- it('always renders the centered launcher button', () => {
28
- render(<MobileFooter onOpenApps={() => {}} leftIcons={oneIcon} rightIcons={oneIcon} />);
29
-
30
- expect(screen.getByRole('button', { name: 'Apps' })).toBeDefined();
31
- });
32
-
33
- it('calls onOpenApps when the launcher is pressed', () => {
34
- const onOpenApps = vi.fn();
35
- render(<MobileFooter onOpenApps={onOpenApps} leftIcons={oneIcon} rightIcons={oneIcon} />);
36
-
37
- fireEvent.click(screen.getByRole('button', { name: 'Apps' }));
38
- expect(onOpenApps).toHaveBeenCalledTimes(1);
39
- });
40
-
41
- it('renders 1+1 and 2+2 icon layouts', () => {
42
- const { rerender } = render(
43
- <MobileFooter onOpenApps={() => {}} leftIcons={oneIcon} rightIcons={oneIcon} />,
44
- );
45
- expect(screen.getAllByRole('button').length).toBe(3);
46
-
47
- rerender(<MobileFooter onOpenApps={() => {}} leftIcons={leftTwo} rightIcons={rightTwo} />);
48
- expect(screen.getByLabelText('Calendar')).toBeDefined();
49
- expect(screen.getByLabelText('Activity')).toBeDefined();
50
- });
51
-
52
- it('logs a dev-mode console.error when left/right icon counts mismatch, but never throws', () => {
53
- vi.stubEnv('NODE_ENV', 'development');
54
- const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
55
-
56
- expect(() =>
57
- render(<MobileFooter onOpenApps={() => {}} leftIcons={oneIcon} rightIcons={twoIcons} />),
58
- ).not.toThrow();
59
-
60
- expect(errorSpy).toHaveBeenCalledWith(expect.stringContaining('leftIcons'));
61
- });
62
-
63
- it('does not call console.error in production even with mismatched counts', () => {
64
- vi.stubEnv('NODE_ENV', 'production');
65
- const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
66
-
67
- render(<MobileFooter onOpenApps={() => {}} leftIcons={oneIcon} rightIcons={twoIcons} />);
68
-
69
- expect(errorSpy).not.toHaveBeenCalled();
70
- });
71
- });
@@ -1,63 +0,0 @@
1
- .header {
2
- display: flex;
3
- align-items: center;
4
- justify-content: space-between;
5
- gap: var(--sv-space-3);
6
- width: 100%;
7
- /* Mobile-only component — never render wider than the platform's own
8
- mobile breakpoint, even if a consumer accidentally mounts it in a wider
9
- container (e.g. an un-gated preview). At real mobile widths this is a
10
- no-op since the viewport itself is already narrower. */
11
- max-width: 768px;
12
- margin-inline: auto;
13
- min-height: var(--sv-shell-header-height, 60px);
14
- padding: var(--sv-space-3) var(--sv-space-4);
15
- padding-top: max(var(--sv-space-3), env(safe-area-inset-top));
16
- padding-right: max(var(--sv-space-4), env(safe-area-inset-right));
17
- padding-left: max(var(--sv-space-4), env(safe-area-inset-left));
18
- background-color: var(--sv-color-surface);
19
- border-bottom: 1px solid var(--sv-color-border);
20
- position: sticky;
21
- top: 0;
22
- z-index: 101;
23
- }
24
-
25
- .brandGroup {
26
- display: flex;
27
- align-items: center;
28
- gap: var(--sv-space-3);
29
- min-width: 0;
30
- }
31
-
32
- /* Matches the runtime shell's own .mobileBrandIcon (shell.module.css) — the
33
- default logo shown when the consumer doesn't supply one. */
34
- .defaultLogo {
35
- display: flex;
36
- align-items: center;
37
- justify-content: center;
38
- flex-shrink: 0;
39
- width: 36px;
40
- height: 36px;
41
- border-radius: var(--sv-radius-md);
42
- background-color: var(--sv-color-accent);
43
- color: var(--sv-color-text-on-accent);
44
- font-weight: var(--sv-font-weight-semibold);
45
- overflow: hidden;
46
- }
47
-
48
- .title {
49
- font-size: var(--sv-font-size-md);
50
- font-weight: var(--sv-font-weight-semibold);
51
- color: var(--sv-color-text-primary);
52
- overflow: hidden;
53
- text-overflow: ellipsis;
54
- white-space: nowrap;
55
- }
56
-
57
- .right {
58
- display: flex;
59
- align-items: center;
60
- gap: var(--sv-space-2);
61
- margin-left: auto;
62
- flex-shrink: 0;
63
- }
@@ -1,57 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { MobileHeader } from './MobileHeader';
3
- import { Avatar } from '../Avatar/Avatar';
4
- import { Icon } from '../Icon/Icon';
5
-
6
- function Logo() {
7
- return (
8
- <span
9
- aria-label="Home"
10
- style={{
11
- display: 'flex',
12
- alignItems: 'center',
13
- justifyContent: 'center',
14
- width: 28,
15
- height: 28,
16
- borderRadius: 'var(--sv-radius-sm)',
17
- background: 'var(--sv-color-accent)',
18
- color: 'var(--sv-color-text-on-accent)',
19
- fontWeight: 700,
20
- fontSize: 13,
21
- flexShrink: 0,
22
- }}
23
- >
24
- S
25
- </span>
26
- );
27
- }
28
-
29
- const meta = {
30
- title: 'Components/MobileHeader',
31
- component: MobileHeader,
32
- parameters: {
33
- layout: 'padded',
34
- docs: {
35
- description: {
36
- component:
37
- 'Mobile shell header content row (RFC 0088). Logo, bell, and avatarMenu are always rendered by the consumer — the optional title is the only overridable part. Presentational only, no data fetching. See Overview/Mobile Patterns for the full immutable/overridable boundary.',
38
- },
39
- },
40
- },
41
- args: {
42
- logo: <Logo />,
43
- bell: <Icon name="bell" size="md" aria-label="Notifications" />,
44
- avatarMenu: <Avatar name="Jamie Doe" size="sm" />,
45
- },
46
- } satisfies Meta<typeof MobileHeader>;
47
-
48
- export default meta;
49
- type Story = StoryObj<typeof meta>;
50
-
51
- export const Default: Story = {};
52
-
53
- export const WithTitle: Story = {
54
- args: {
55
- title: 'Tasks',
56
- },
57
- };
@@ -1,77 +0,0 @@
1
- import type { HTMLAttributes, ReactNode } from 'react';
2
- import styles from './MobileHeader.module.css';
3
-
4
- export interface MobileHeaderProps extends HTMLAttributes<HTMLDivElement> {
5
- /** The brand/logo element — already a complete, clickable link home (e.g. an
6
- * instance logo wrapped in the consumer's own router `Link`). Always
7
- * rendered. `MobileHeader` stays router-agnostic, so this is provided
8
- * fully built rather than as a bare icon + href. Optional — omit it to get
9
- * a default "S" badge (matching the runtime shell's own fallback brand
10
- * icon when no instance logo is configured), sized and styled to the same
11
- * 36px/radius-md convention a custom logo is expected to follow. */
12
- logo?: ReactNode;
13
- /** Optional contextual title rendered beside the logo (e.g. the active
14
- * plugin's name). Absent by default — this is the one overridable part of
15
- * the header. See RFC 0088. */
16
- title?: string;
17
- /** Notification bell — always rendered; not overridable.
18
- * TODO: this is just an icon slot today (the consumer wires up its own
19
- * click handler/content) — it doesn't yet accommodate a full notification
20
- * feature (unread badge, dropdown panel, etc. — see the runtime shell's
21
- * own NotificationBell). Deferred; revisit once a plugin actually needs
22
- * more than a bare bell icon here. */
23
- bell: ReactNode;
24
- /** Avatar / account menu trigger — always rendered; not overridable. */
25
- avatarMenu: ReactNode;
26
- }
27
-
28
- /** Default fallback logo — matches the runtime shell's own .mobileBrandIcon
29
- * exactly (36px, radius-md, accent background) for the "no instance logo
30
- * configured" case, just with a fixed "S" instead of the instance name's
31
- * first letter (this component can't know the instance name — no data
32
- * fetching, see the component's own doc comment). */
33
- function DefaultLogo() {
34
- return (
35
- <span className={styles.defaultLogo} aria-hidden="true">
36
- S
37
- </span>
38
- );
39
- }
40
-
41
- /**
42
- * The mobile header bar: brand/logo (always shown), an optional contextual
43
- * title, and a fixed bell + avatar-menu cluster. Owns its own chrome —
44
- * background, border-bottom, sticky positioning, safe-area-aware padding,
45
- * and a 768px max-width (so it never stretches full-bleed if mounted outside
46
- * an actual mobile viewport) — matching the runtime shell's own mobile
47
- * header exactly, since this component is meant to replace that hand-rolled
48
- * markup. Presentational only — no data fetching; the consumer supplies
49
- * `bell`/`avatarMenu` (and, optionally, `logo`) as already-wired components
50
- * (their own sizing — 36px logo/avatar, 44px bell tap target — is the
51
- * consumer's responsibility, matching the reference implementation in the
52
- * runtime shell). See RFC 0088 for the immutable/overridable boundary this
53
- * enforces.
54
- */
55
- export function MobileHeader({
56
- logo,
57
- title,
58
- bell,
59
- avatarMenu,
60
- className,
61
- ...rest
62
- }: MobileHeaderProps) {
63
- const cls = [styles.header, className].filter(Boolean).join(' ');
64
-
65
- return (
66
- <div className={cls} {...rest}>
67
- <div className={styles.brandGroup}>
68
- {logo ?? <DefaultLogo />}
69
- {title && <span className={styles.title}>{title}</span>}
70
- </div>
71
- <div className={styles.right}>
72
- {bell}
73
- {avatarMenu}
74
- </div>
75
- </div>
76
- );
77
- }
@@ -1,58 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it } from 'vitest';
3
- import { cleanup, render, screen } from '@testing-library/react';
4
- import { MobileHeader } from '../MobileHeader';
5
-
6
- afterEach(() => {
7
- cleanup();
8
- });
9
-
10
- describe('MobileHeader', () => {
11
- it('always renders the logo, bell, and avatar menu slots', () => {
12
- render(
13
- <MobileHeader
14
- logo={<a href="/">logo</a>}
15
- bell={<span data-testid="bell">bell</span>}
16
- avatarMenu={<span data-testid="avatar">avatar</span>}
17
- />,
18
- );
19
-
20
- expect(screen.getByText('logo')).toBeDefined();
21
- expect(screen.getByTestId('bell')).toBeDefined();
22
- expect(screen.getByTestId('avatar')).toBeDefined();
23
- });
24
-
25
- it('renders no title by default', () => {
26
- render(<MobileHeader logo={<a href="/">logo</a>} bell={<span />} avatarMenu={<span />} />);
27
-
28
- expect(screen.queryByText(/tasks/i)).toBeNull();
29
- });
30
-
31
- it('renders the optional title when provided', () => {
32
- render(
33
- <MobileHeader
34
- logo={<a href="/">logo</a>}
35
- title="Tasks"
36
- bell={<span />}
37
- avatarMenu={<span />}
38
- />,
39
- );
40
-
41
- expect(screen.getByText('Tasks')).toBeDefined();
42
- });
43
-
44
- it('renders a default "S" badge when logo is omitted', () => {
45
- render(<MobileHeader bell={<span />} avatarMenu={<span />} />);
46
-
47
- expect(screen.getByText('S')).toBeDefined();
48
- });
49
-
50
- it('renders the supplied logo instead of the default badge when provided', () => {
51
- render(
52
- <MobileHeader logo={<a href="/">custom logo</a>} bell={<span />} avatarMenu={<span />} />,
53
- );
54
-
55
- expect(screen.getByText('custom logo')).toBeDefined();
56
- expect(screen.queryByText('S')).toBeNull();
57
- });
58
- });
@@ -1,50 +0,0 @@
1
- .nav {
2
- display: flex;
3
- flex-wrap: wrap;
4
- gap: 0;
5
- border-bottom: 1px solid var(--sv-color-border);
6
- }
7
-
8
- .link {
9
- padding: var(--sv-space-2) var(--sv-space-3);
10
- padding-bottom: calc(var(--sv-space-2) + 2px);
11
- border-bottom: 2px solid transparent;
12
- font-size: var(--sv-font-size-sm);
13
- font-weight: var(--sv-font-weight-medium);
14
- color: var(--sv-color-text-muted);
15
- text-decoration: none;
16
- white-space: nowrap;
17
- transition: color 0.1s ease;
18
- }
19
-
20
- @media (hover: hover) {
21
- .link:hover {
22
- color: var(--sv-color-text-primary);
23
- }
24
- }
25
-
26
- .link:focus-visible {
27
- outline: 2px solid var(--sv-color-focus-ring);
28
- outline-offset: -2px;
29
- border-radius: var(--sv-radius-sm);
30
- }
31
-
32
- .active {
33
- color: var(--sv-color-text-primary);
34
- font-weight: var(--sv-font-weight-semibold);
35
- border-bottom-color: var(--sv-color-text-primary);
36
- }
37
-
38
- @media (max-width: 640px) {
39
- .nav {
40
- flex-wrap: nowrap;
41
- overflow-x: auto;
42
- scrollbar-width: none;
43
- -webkit-overflow-scrolling: touch;
44
- mask-image: linear-gradient(to right, black calc(100% - 32px), transparent 100%);
45
- }
46
-
47
- .nav::-webkit-scrollbar {
48
- display: none;
49
- }
50
- }
@@ -1,61 +0,0 @@
1
- import { Fragment, type ReactNode } from 'react';
2
- import styles from './NavTabs.module.css';
3
-
4
- export interface NavTabItem {
5
- label: string;
6
- href: string;
7
- active?: boolean;
8
- }
9
-
10
- /** Props to spread onto a consumer-supplied link element — keeps NavTabs' own
11
- * class names and a11y attributes in sync with whatever the consumer renders. */
12
- export interface NavTabLinkProps {
13
- href: string;
14
- className: string;
15
- 'aria-current': 'page' | undefined;
16
- children: ReactNode;
17
- }
18
-
19
- export interface NavTabsProps {
20
- items: NavTabItem[];
21
- className?: string;
22
- 'aria-label'?: string;
23
- /** Render a tab as something other than a plain `<a href>` — e.g. Next's
24
- * `<Link replace>` inside an overlay-shell plugin, where a full page
25
- * navigation would break the dialog's history contract. Receives the item
26
- * plus the class name/aria attributes NavTabs would otherwise apply. */
27
- renderLink?: (item: NavTabItem, linkProps: NavTabLinkProps) => ReactNode;
28
- }
29
-
30
- export function NavTabs({ items, className, 'aria-label': ariaLabel, renderLink }: NavTabsProps) {
31
- return (
32
- <nav
33
- className={[styles.nav, className].filter(Boolean).join(' ')}
34
- aria-label={ariaLabel ?? 'Page navigation'}
35
- >
36
- {items.map((item) => {
37
- const linkProps: NavTabLinkProps = {
38
- href: item.href,
39
- className: [styles.link, item.active && styles.active].filter(Boolean).join(' '),
40
- 'aria-current': item.active ? 'page' : undefined,
41
- children: item.label,
42
- };
43
- return (
44
- <Fragment key={item.href}>
45
- {renderLink ? (
46
- renderLink(item, linkProps)
47
- ) : (
48
- <a
49
- href={linkProps.href}
50
- className={linkProps.className}
51
- aria-current={linkProps['aria-current']}
52
- >
53
- {linkProps.children}
54
- </a>
55
- )}
56
- </Fragment>
57
- );
58
- })}
59
- </nav>
60
- );
61
- }