@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,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 { TagInput } from '../TagInput';
5
-
6
- afterEach(cleanup);
7
-
8
- describe('TagInput', () => {
9
- it('adds a tag with Enter', () => {
10
- const onChange = vi.fn();
11
- render(<TagInput value={[]} onChange={onChange} aria-label="Tags" />);
12
-
13
- const input = screen.getByLabelText('Tags');
14
- fireEvent.change(input, { target: { value: 'launch' } });
15
- fireEvent.keyDown(input, { key: 'Enter' });
16
-
17
- expect(onChange).toHaveBeenCalledWith(['launch']);
18
- });
19
-
20
- it('removes the last tag with Backspace when the input is empty', () => {
21
- const onChange = vi.fn();
22
- render(<TagInput value={['draft', 'publish']} onChange={onChange} aria-label="Tags" />);
23
-
24
- fireEvent.keyDown(screen.getByLabelText('Tags'), { key: 'Backspace' });
25
-
26
- expect(onChange).toHaveBeenCalledWith(['draft']);
27
- });
28
-
29
- it('splits pasted comma-separated tags', () => {
30
- const onChange = vi.fn();
31
- render(<TagInput value={['draft']} onChange={onChange} aria-label="Tags" />);
32
-
33
- fireEvent.paste(screen.getByLabelText('Tags'), {
34
- clipboardData: {
35
- getData: () => 'launch, release\nnotes',
36
- },
37
- });
38
-
39
- expect(onChange).toHaveBeenCalledWith(['draft', 'launch', 'release', 'notes']);
40
- });
41
-
42
- it('shows validation messages and does not add invalid tags', () => {
43
- const onChange = vi.fn();
44
- render(
45
- <TagInput
46
- value={[]}
47
- onChange={onChange}
48
- aria-label="Tags"
49
- validateTag={(tag) => (tag.length > 4 ? 'Tag is too long.' : undefined)}
50
- />,
51
- );
52
-
53
- const input = screen.getByLabelText('Tags');
54
- fireEvent.change(input, { target: { value: 'launch' } });
55
- fireEvent.keyDown(input, { key: 'Enter' });
56
-
57
- expect(screen.getByRole('alert').textContent).toBe('Tag is too long.');
58
- expect(onChange).not.toHaveBeenCalled();
59
- });
60
-
61
- it('renders removable chips with accessible names', () => {
62
- const onChange = vi.fn();
63
- render(<TagInput value={['draft']} onChange={onChange} aria-label="Tags" />);
64
-
65
- fireEvent.click(screen.getByRole('button', { name: 'Remove draft' }));
66
-
67
- expect(onChange).toHaveBeenCalledWith([]);
68
- });
69
- });
@@ -1,39 +0,0 @@
1
- .textarea {
2
- display: block;
3
- width: 100%;
4
- padding: var(--sv-space-2) var(--sv-space-3);
5
- font-family: var(--sv-font-family);
6
- font-size: var(--sv-font-size-sm);
7
- line-height: 1.5;
8
- color: var(--sv-color-text-primary);
9
- background-color: var(--sv-color-surface);
10
- border: 1px solid var(--sv-color-border-strong);
11
- border-radius: var(--sv-radius-md);
12
- resize: vertical;
13
- transition:
14
- border-color 0.15s ease,
15
- box-shadow 0.15s ease;
16
- }
17
-
18
- .textarea::placeholder {
19
- color: var(--sv-color-text-muted);
20
- }
21
-
22
- .textarea:focus-visible {
23
- outline: none;
24
- border-color: var(--sv-color-accent);
25
- box-shadow: 0 0 0 2px var(--sv-color-focus-ring);
26
- }
27
-
28
- .textarea:read-only {
29
- background-color: var(--sv-color-surface-sunken);
30
- color: var(--sv-color-text-muted);
31
- border-color: var(--sv-color-border);
32
- cursor: default;
33
- }
34
-
35
- .textarea:disabled {
36
- opacity: 0.5;
37
- cursor: not-allowed;
38
- resize: none;
39
- }
@@ -1,15 +0,0 @@
1
- import type { TextareaHTMLAttributes } from 'react';
2
- import styles from './Textarea.module.css';
3
-
4
- export type TextareaProps = TextareaHTMLAttributes<HTMLTextAreaElement>;
5
-
6
- /**
7
- * Textarea — the primitive multi-line text field. Presentational and
8
- * RSC-safe: it forwards all native textarea props to the underlying
9
- * `<textarea>`. Styling references `--sv-*` tokens via CSS Modules; there
10
- * are no hardcoded values.
11
- */
12
- export function Textarea({ className, rows = 4, ...rest }: TextareaProps) {
13
- const classes = [styles.textarea, className].filter(Boolean).join(' ');
14
- return <textarea rows={rows} className={classes} {...rest} />;
15
- }
@@ -1,29 +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 { Textarea } from '../Textarea';
5
-
6
- afterEach(cleanup);
7
-
8
- describe('Textarea', () => {
9
- it('renders and forwards native props', () => {
10
- render(<Textarea placeholder="Bio" defaultValue="Hello" />);
11
- const textarea = screen.getByPlaceholderText('Bio') as HTMLTextAreaElement;
12
- expect(textarea.value).toBe('Hello');
13
- });
14
-
15
- it('defaults to 4 rows', () => {
16
- render(<Textarea aria-label="field" />);
17
- expect((screen.getByLabelText('field') as HTMLTextAreaElement).rows).toBe(4);
18
- });
19
-
20
- it('honours an explicit rows value', () => {
21
- render(<Textarea aria-label="field" rows={8} />);
22
- expect((screen.getByLabelText('field') as HTMLTextAreaElement).rows).toBe(8);
23
- });
24
-
25
- it('is disabled when the disabled prop is set', () => {
26
- render(<Textarea aria-label="field" disabled />);
27
- expect((screen.getByLabelText('field') as HTMLTextAreaElement).disabled).toBe(true);
28
- });
29
- });
@@ -1,132 +0,0 @@
1
- /* Toast — transient notification snackbar.
2
- *
3
- * Fixed top-right, 320px. Slides in from above. Each toast auto-dismisses
4
- * after `duration` ms. Leading status icon reinforces category at a glance.
5
- *
6
- * Category variants map to the semantic status tokens (info/success/warning/
7
- * error) so the visual language is consistent with banners and badges.
8
- * The announcement category uses the accent colour (neutral brand highlight).
9
- * `security` matches the error palette — draws maximum attention. */
10
-
11
- .region {
12
- position: fixed;
13
- top: var(--sv-space-4);
14
- right: var(--sv-space-4);
15
- z-index: 200;
16
- display: flex;
17
- flex-direction: column;
18
- gap: var(--sv-space-2);
19
- width: 320px;
20
- max-width: calc(100vw - var(--sv-space-8));
21
- pointer-events: none;
22
- }
23
-
24
- .toast {
25
- display: flex;
26
- align-items: flex-start;
27
- gap: var(--sv-space-3);
28
- padding: var(--sv-space-3) var(--sv-space-4);
29
- background: var(--sv-color-surface-raised);
30
- color: var(--sv-color-text-primary);
31
- border: 1px solid var(--sv-color-border);
32
- border-radius: var(--sv-radius-md);
33
- box-shadow: var(--sv-shadow-overlay);
34
- pointer-events: all;
35
- animation: toastIn 200ms ease-out;
36
- }
37
-
38
- .toast.exiting {
39
- animation: toastOut 200ms ease-in forwards;
40
- }
41
-
42
- /* Leading status icon */
43
- .icon {
44
- flex: 0 0 auto;
45
- display: flex;
46
- align-items: center;
47
- padding-top: 1px;
48
- color: var(--sv-color-border-strong);
49
- }
50
-
51
- .toast.info .icon,
52
- .toast.announcement .icon {
53
- color: var(--sv-color-accent);
54
- }
55
-
56
- .toast.success .icon {
57
- color: var(--sv-color-success-text);
58
- }
59
-
60
- .toast.warning .icon {
61
- color: var(--sv-color-warning-text);
62
- }
63
-
64
- .toast.error .icon,
65
- .toast.security .icon {
66
- color: var(--sv-color-error-text);
67
- }
68
-
69
- .body {
70
- flex: 1 1 auto;
71
- min-width: 0;
72
- }
73
-
74
- .title {
75
- font-size: var(--sv-font-size-sm);
76
- font-weight: 600;
77
- line-height: 1.4;
78
- color: var(--sv-color-text-primary);
79
- }
80
-
81
- .message {
82
- font-size: var(--sv-font-size-sm);
83
- color: var(--sv-color-text-muted);
84
- margin-top: var(--sv-space-1);
85
- line-height: 1.4;
86
- }
87
-
88
- .close {
89
- flex: 0 0 auto;
90
- background: none;
91
- border: none;
92
- padding: 0;
93
- cursor: pointer;
94
- color: var(--sv-color-text-subtle);
95
- line-height: 1;
96
- font-size: var(--sv-font-size-md);
97
- }
98
-
99
- @media (hover: hover) {
100
- .close:hover {
101
- color: var(--sv-color-text-primary);
102
- }
103
- }
104
-
105
- @keyframes toastIn {
106
- from {
107
- opacity: 0;
108
- transform: translateY(-8px);
109
- }
110
- to {
111
- opacity: 1;
112
- transform: translateY(0);
113
- }
114
- }
115
-
116
- @keyframes toastOut {
117
- from {
118
- opacity: 1;
119
- transform: translateY(0);
120
- }
121
- to {
122
- opacity: 0;
123
- transform: translateY(-8px);
124
- }
125
- }
126
-
127
- @media (prefers-reduced-motion: reduce) {
128
- .toast,
129
- .toast.exiting {
130
- animation: none;
131
- }
132
- }
@@ -1,191 +0,0 @@
1
- import { useState } from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { ToastProvider, useToast } from './Toast';
4
-
5
- const meta = {
6
- title: 'Components/Toast',
7
- component: ToastProvider,
8
- parameters: {
9
- layout: 'centered',
10
- docs: {
11
- description: {
12
- component:
13
- 'Fixed top-right notification stack. Use `<ToastProvider>` at the app root and `useToast()` to imperatively show toasts. Each toast has a leading status icon matched to its category.',
14
- },
15
- },
16
- },
17
- args: {
18
- children: null,
19
- },
20
- } satisfies Meta<typeof ToastProvider>;
21
-
22
- export default meta;
23
- type Story = StoryObj<typeof meta>;
24
-
25
- // ---------------------------------------------------------------------------
26
-
27
- function ToastTrigger({ category, label }: { category: string; label: string }) {
28
- const { show } = useToast();
29
- return (
30
- <button
31
- type="button"
32
- onClick={() =>
33
- show({
34
- title: label,
35
- message: `This is a ${category} toast notification.`,
36
- category,
37
- })
38
- }
39
- style={{
40
- padding: '8px 16px',
41
- borderRadius: 'var(--sv-radius-md)',
42
- border: '1px solid var(--sv-color-border)',
43
- background: 'var(--sv-color-surface)',
44
- color: 'var(--sv-color-text-primary)',
45
- fontFamily: 'var(--sv-font-family)',
46
- fontSize: 'var(--sv-font-size-sm)',
47
- cursor: 'pointer',
48
- }}
49
- >
50
- {label}
51
- </button>
52
- );
53
- }
54
-
55
- /** All toast categories — each button fires a toast with the matching leading icon. */
56
- export const AllCategories: Story = {
57
- render: (_args) => (
58
- <ToastProvider>
59
- <div
60
- style={{
61
- display: 'flex',
62
- flexDirection: 'column',
63
- gap: 8,
64
- alignItems: 'flex-start',
65
- }}
66
- >
67
- <ToastTrigger category="info" label="Info toast" />
68
- <ToastTrigger category="success" label="Success toast" />
69
- <ToastTrigger category="warning" label="Warning toast" />
70
- <ToastTrigger category="error" label="Error toast" />
71
- <ToastTrigger category="security" label="Security toast" />
72
- <ToastTrigger category="announcement" label="Announcement toast" />
73
- </div>
74
- </ToastProvider>
75
- ),
76
- };
77
-
78
- /** Toast with no body — title only. */
79
- export const TitleOnly: Story = {
80
- render: (_args) => {
81
- function Trigger() {
82
- const { show } = useToast();
83
- return (
84
- <button
85
- type="button"
86
- onClick={() => show({ title: 'Session expires in 5 minutes', category: 'warning' })}
87
- style={{
88
- padding: '8px 16px',
89
- borderRadius: 'var(--sv-radius-md)',
90
- border: '1px solid var(--sv-color-border)',
91
- background: 'var(--sv-color-surface)',
92
- color: 'var(--sv-color-text-primary)',
93
- fontFamily: 'var(--sv-font-family)',
94
- fontSize: 'var(--sv-font-size-sm)',
95
- cursor: 'pointer',
96
- }}
97
- >
98
- Show title-only toast
99
- </button>
100
- );
101
- }
102
- return (
103
- <ToastProvider>
104
- <Trigger />
105
- </ToastProvider>
106
- );
107
- },
108
- };
109
-
110
- /** Persistent toast — pass `duration: 0` to disable auto-dismiss. */
111
- export const Persistent: Story = {
112
- render: (_args) => {
113
- function Trigger() {
114
- const { show } = useToast();
115
- return (
116
- <button
117
- type="button"
118
- onClick={() =>
119
- show({
120
- title: 'Maintenance mode active',
121
- message: 'Platform is in read-only mode. Dismiss when resolved.',
122
- category: 'error',
123
- duration: 0,
124
- })
125
- }
126
- style={{
127
- padding: '8px 16px',
128
- borderRadius: 'var(--sv-radius-md)',
129
- border: '1px solid var(--sv-color-border)',
130
- background: 'var(--sv-color-surface)',
131
- color: 'var(--sv-color-text-primary)',
132
- fontFamily: 'var(--sv-font-family)',
133
- fontSize: 'var(--sv-font-size-sm)',
134
- cursor: 'pointer',
135
- }}
136
- >
137
- Show persistent toast
138
- </button>
139
- );
140
- }
141
- return (
142
- <ToastProvider>
143
- <Trigger />
144
- </ToastProvider>
145
- );
146
- },
147
- };
148
-
149
- /** Multiple toasts stack vertically below the first. */
150
- export const Stacked: Story = {
151
- render: (_args) => {
152
- function Trigger() {
153
- const { show } = useToast();
154
- const [fired, setFired] = useState(false);
155
- return (
156
- <button
157
- type="button"
158
- disabled={fired}
159
- onClick={() => {
160
- show({ title: 'Plugin installed', category: 'success' });
161
- show({
162
- title: 'License warning',
163
- message: 'Expires in 3 days.',
164
- category: 'warning',
165
- });
166
- show({ title: 'Backup failed', message: 'Check storage quota.', category: 'error' });
167
- setFired(true);
168
- }}
169
- style={{
170
- padding: '8px 16px',
171
- borderRadius: 'var(--sv-radius-md)',
172
- border: '1px solid var(--sv-color-border)',
173
- background: 'var(--sv-color-surface)',
174
- color: 'var(--sv-color-text-primary)',
175
- fontFamily: 'var(--sv-font-family)',
176
- fontSize: 'var(--sv-font-size-sm)',
177
- cursor: fired ? 'default' : 'pointer',
178
- opacity: fired ? 0.5 : 1,
179
- }}
180
- >
181
- Fire 3 toasts
182
- </button>
183
- );
184
- }
185
- return (
186
- <ToastProvider>
187
- <Trigger />
188
- </ToastProvider>
189
- );
190
- },
191
- };
@@ -1,139 +0,0 @@
1
- 'use client';
2
-
3
- import {
4
- createContext,
5
- useCallback,
6
- useContext,
7
- useEffect,
8
- useId,
9
- useMemo,
10
- useRef,
11
- useState,
12
- } from 'react';
13
- import { Icon, type IconName } from '../Icon/Icon';
14
- import styles from './Toast.module.css';
15
-
16
- export interface ToastItem {
17
- id: string;
18
- title: string;
19
- message?: string;
20
- /** `'info'` | `'success'` | `'warning'` | `'error'` | `'security'` | `'announcement'` */
21
- category?: string;
22
- /** Auto-dismiss delay in ms. Default 5000. Pass `0` to disable auto-dismiss. */
23
- duration?: number;
24
- exiting?: boolean;
25
- }
26
-
27
- export interface ToastContextValue {
28
- /** Show a toast notification. Returns the generated toast id. */
29
- show(item: Omit<ToastItem, 'id'>): string;
30
- /** Dismiss a toast by id. */
31
- dismiss(id: string): void;
32
- }
33
-
34
- const ToastContext = createContext<ToastContextValue | null>(null);
35
-
36
- /** Consume the toast context to imperatively show toasts from any client component. */
37
- export function useToast(): ToastContextValue {
38
- const ctx = useContext(ToastContext);
39
- if (!ctx) throw new Error('useToast() must be used inside <ToastProvider>');
40
- return ctx;
41
- }
42
-
43
- export function ToastProvider({ children }: { children: React.ReactNode }) {
44
- const [toasts, setToasts] = useState<ToastItem[]>([]);
45
- const timers = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());
46
- const seedId = useId();
47
- const counter = useRef(0);
48
-
49
- const dismiss = useCallback((id: string) => {
50
- setToasts((prev) => prev.map((t) => (t.id === id ? { ...t, exiting: true } : t)));
51
- setTimeout(() => {
52
- setToasts((prev) => prev.filter((t) => t.id !== id));
53
- }, 220);
54
- }, []);
55
-
56
- const show = useCallback(
57
- (item: Omit<ToastItem, 'id'>): string => {
58
- const id = `${seedId}-${++counter.current}`;
59
- const duration = item.duration ?? 5000;
60
- setToasts((prev) => [...prev, { ...item, id }]);
61
- if (duration > 0) {
62
- const timer = setTimeout(() => dismiss(id), duration);
63
- timers.current.set(id, timer);
64
- }
65
- return id;
66
- },
67
- [seedId, dismiss],
68
- );
69
-
70
- useEffect(() => {
71
- const currentTimers = timers.current;
72
- return () => {
73
- currentTimers.forEach((t) => clearTimeout(t));
74
- };
75
- }, []);
76
-
77
- const value = useMemo(() => ({ show, dismiss }), [show, dismiss]);
78
-
79
- return (
80
- <ToastContext.Provider value={value}>
81
- {children}
82
- <ol
83
- className={styles.region}
84
- aria-label="Notifications"
85
- aria-live="polite"
86
- aria-atomic="false"
87
- >
88
- {toasts.map((toast) => (
89
- <Toast key={toast.id} {...toast} onDismiss={dismiss} />
90
- ))}
91
- </ol>
92
- </ToastContext.Provider>
93
- );
94
- }
95
-
96
- /** Maps toast category to a leading Icon name. */
97
- const CATEGORY_ICON: Record<string, IconName> = {
98
- info: 'info',
99
- announcement: 'info',
100
- success: 'check',
101
- warning: 'alert-triangle',
102
- error: 'alert-triangle',
103
- security: 'alert-triangle',
104
- };
105
-
106
- function Toast({
107
- id,
108
- title,
109
- message,
110
- category = 'info',
111
- exiting,
112
- onDismiss,
113
- }: ToastItem & { onDismiss(id: string): void }) {
114
- const categoryClass = styles[category as keyof typeof styles] ?? styles.info;
115
- const iconName = CATEGORY_ICON[category] ?? 'info';
116
-
117
- return (
118
- <li
119
- role="status"
120
- className={`${styles.toast} ${String(categoryClass)} ${exiting ? styles.exiting : ''}`}
121
- >
122
- <span className={styles.icon} aria-hidden="true">
123
- <Icon name={iconName} size="sm" aria-hidden />
124
- </span>
125
- <div className={styles.body}>
126
- <div className={styles.title}>{title}</div>
127
- {message && <div className={styles.message}>{message}</div>}
128
- </div>
129
- <button
130
- type="button"
131
- className={styles.close}
132
- aria-label="Dismiss notification"
133
- onClick={() => onDismiss(id)}
134
- >
135
- ✕
136
- </button>
137
- </li>
138
- );
139
- }
@@ -1,57 +0,0 @@
1
- .track {
2
- /* 38×22px pill — spec dimensions. Sizing audit: despite the component
3
- name, this renders as a binary pill switch (role="switch"), not a
4
- pressable toggle button — reviewed against this scale's other compact
5
- controls with that in mind. Kept dimensions unchanged, generously
6
- sized for touch-friendliness. (The name vs. actual behavior mismatch
7
- is a separate, pre-existing naming note, not addressed here.) */
8
- display: inline-flex;
9
- align-items: center;
10
- width: 38px;
11
- height: 22px;
12
- border-radius: var(--sv-radius-full);
13
- border: none;
14
- padding: 0;
15
- cursor: pointer;
16
- flex-shrink: 0;
17
- transition: background-color 0.15s ease;
18
- position: relative;
19
- }
20
-
21
- .track:focus-visible {
22
- outline: 2px solid var(--sv-color-focus-ring);
23
- outline-offset: 2px;
24
- }
25
-
26
- .track:disabled {
27
- opacity: 0.5;
28
- cursor: not-allowed;
29
- }
30
-
31
- .on {
32
- background-color: var(--sv-color-accent);
33
- }
34
-
35
- .off {
36
- background-color: var(--sv-color-border-strong);
37
- }
38
-
39
- /* 18px thumb, 2px inset on each side */
40
- .thumb {
41
- position: absolute;
42
- width: 18px;
43
- height: 18px;
44
- border-radius: var(--sv-radius-full);
45
- background: var(--sv-white);
46
- transition: transform 0.15s ease;
47
- left: 2px;
48
- box-shadow: var(--sv-shadow-control);
49
- }
50
-
51
- .on .thumb {
52
- transform: translateX(16px); /* 38 - 18 - 2 - 2 = 16 */
53
- }
54
-
55
- .off .thumb {
56
- transform: translateX(0);
57
- }