@sovereignfs/ui 0.83.1 → 0.89.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (556) hide show
  1. package/LICENSE +373 -661
  2. package/NOTICE +8 -0
  3. package/README.md +4 -6
  4. package/dist/AppsLauncher.module.css +6 -0
  5. package/dist/Button.module.css +5 -0
  6. package/dist/Card.module.css +6 -0
  7. package/dist/CardTile.module.css +6 -0
  8. package/dist/CheckableListRow.module.css +8 -0
  9. package/dist/Checkbox.module.css +8 -0
  10. package/dist/CodeTextarea.module.css +6 -0
  11. package/dist/ColorPicker.module.css +6 -0
  12. package/dist/Combobox.module.css +6 -0
  13. package/dist/Command.module.css +6 -0
  14. package/dist/ConfirmDialog.module.css +6 -0
  15. package/dist/DatePicker.module.css +6 -0
  16. package/dist/Dialog.module.css +1 -1
  17. package/dist/DragHandleRow.module.css +6 -0
  18. package/dist/FileDropzone.module.css +25 -1
  19. package/dist/Header.module.css +6 -0
  20. package/dist/IconPicker.module.css +14 -4
  21. package/dist/Input.module.css +6 -0
  22. package/dist/LegalLinks.module.css +9 -2
  23. package/dist/Markdown.module.css +5 -0
  24. package/dist/Message.module.css +9 -0
  25. package/dist/MobileAppsDrawer.module.css +9 -5
  26. package/dist/MobileFooter.module.css +6 -0
  27. package/dist/NavList.module.css +11 -2
  28. package/dist/NavTabs.module.css +7 -1
  29. package/dist/NotificationsPanel.module.css +10 -0
  30. package/dist/QrCode.module.css +17 -0
  31. package/dist/QuantityStepper.module.css +4 -2
  32. package/dist/RadioGroup.module.css +6 -0
  33. package/dist/SegmentedControl.module.css +6 -0
  34. package/dist/Select.module.css +6 -0
  35. package/dist/Sheet.module.css +16 -1
  36. package/dist/SplitPane.module.css +1 -1
  37. package/dist/StepStrip.module.css +5 -3
  38. package/dist/SuggestionInput.module.css +12 -1
  39. package/dist/SwipableMobileCarouselDots.module.css +6 -0
  40. package/dist/SystemBanner.module.css +6 -0
  41. package/dist/Tabs.module.css +6 -0
  42. package/dist/TagInput.module.css +6 -0
  43. package/dist/Textarea.module.css +6 -0
  44. package/dist/Toast.module.css +5 -0
  45. package/dist/Toggle.module.css +7 -0
  46. package/dist/Tooltip.module.css +6 -0
  47. package/dist/UserMenu.module.css +5 -0
  48. package/dist/fonts/OFL.txt +93 -0
  49. package/dist/fonts/hanken-grotesk-cyrillic-ext-wght-normal.woff2 +0 -0
  50. package/dist/fonts/hanken-grotesk-latin-ext-wght-normal.woff2 +0 -0
  51. package/dist/fonts/hanken-grotesk-latin-wght-normal.woff2 +0 -0
  52. package/dist/fonts/hanken-grotesk-vietnamese-wght-normal.woff2 +0 -0
  53. package/dist/index.d.ts +121 -43
  54. package/dist/index.js +1410 -1152
  55. package/dist/tokens/fonts.css +53 -0
  56. package/dist/tokens/primitives.css +12 -12
  57. package/dist/tokens.css +2 -1
  58. package/package.json +24 -13
  59. package/src/__tests__/motion.test.tsx +0 -105
  60. package/src/__tests__/package-json.test.ts +0 -8
  61. package/src/components/Accordion/Accordion.module.css +0 -3
  62. package/src/components/Accordion/Accordion.stories.tsx +0 -110
  63. package/src/components/Accordion/Accordion.tsx +0 -53
  64. package/src/components/Accordion/__tests__/Accordion.test.tsx +0 -61
  65. package/src/components/Alert/Alert.module.css +0 -62
  66. package/src/components/Alert/Alert.stories.tsx +0 -96
  67. package/src/components/Alert/Alert.tsx +0 -58
  68. package/src/components/Alert/__tests__/Alert.test.tsx +0 -75
  69. package/src/components/AppsLauncher/AppsLauncher.module.css +0 -96
  70. package/src/components/AppsLauncher/AppsLauncher.stories.tsx +0 -58
  71. package/src/components/AppsLauncher/AppsLauncher.tsx +0 -117
  72. package/src/components/AppsLauncher/__tests__/AppsLauncher.test.tsx +0 -52
  73. package/src/components/AspectRatio/AspectRatio.module.css +0 -15
  74. package/src/components/AspectRatio/AspectRatio.stories.tsx +0 -78
  75. package/src/components/AspectRatio/AspectRatio.tsx +0 -21
  76. package/src/components/AspectRatio/__tests__/AspectRatio.test.tsx +0 -27
  77. package/src/components/Avatar/Avatar.module.css +0 -38
  78. package/src/components/Avatar/Avatar.tsx +0 -42
  79. package/src/components/Badge/Badge.module.css +0 -177
  80. package/src/components/Badge/Badge.stories.tsx +0 -238
  81. package/src/components/Badge/Badge.tsx +0 -84
  82. package/src/components/Badge/__tests__/Badge.test.tsx +0 -90
  83. package/src/components/BalanceChip/BalanceChip.module.css +0 -32
  84. package/src/components/BalanceChip/BalanceChip.stories.tsx +0 -45
  85. package/src/components/BalanceChip/BalanceChip.tsx +0 -33
  86. package/src/components/Breadcrumb/Breadcrumb.module.css +0 -49
  87. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -47
  88. package/src/components/Breadcrumb/Breadcrumb.tsx +0 -57
  89. package/src/components/Breadcrumb/__tests__/Breadcrumb.test.tsx +0 -52
  90. package/src/components/Button/Button.module.css +0 -169
  91. package/src/components/Button/Button.stories.tsx +0 -83
  92. package/src/components/Button/Button.tsx +0 -52
  93. package/src/components/Button/__tests__/Button.test.tsx +0 -66
  94. package/src/components/ButtonGroup/ButtonGroup.module.css +0 -29
  95. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -57
  96. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -27
  97. package/src/components/ButtonGroup/__tests__/ButtonGroup.test.tsx +0 -29
  98. package/src/components/Calendar/Calendar.module.css +0 -126
  99. package/src/components/Calendar/Calendar.tsx +0 -213
  100. package/src/components/Calendar/__tests__/Calendar.test.tsx +0 -98
  101. package/src/components/Calendar/dateUtils.ts +0 -97
  102. package/src/components/Card/Card.module.css +0 -42
  103. package/src/components/Card/Card.tsx +0 -34
  104. package/src/components/CardTile/CardTile.module.css +0 -181
  105. package/src/components/CardTile/CardTile.stories.tsx +0 -86
  106. package/src/components/CardTile/CardTile.tsx +0 -128
  107. package/src/components/CardTile/__tests__/CardTile.test.tsx +0 -56
  108. package/src/components/CheckableListRow/CheckableListRow.module.css +0 -95
  109. package/src/components/CheckableListRow/CheckableListRow.stories.tsx +0 -99
  110. package/src/components/CheckableListRow/CheckableListRow.tsx +0 -89
  111. package/src/components/Checkbox/Checkbox.module.css +0 -111
  112. package/src/components/Checkbox/Checkbox.tsx +0 -78
  113. package/src/components/CodeTextarea/CodeTextarea.module.css +0 -53
  114. package/src/components/CodeTextarea/CodeTextarea.stories.tsx +0 -77
  115. package/src/components/CodeTextarea/CodeTextarea.tsx +0 -36
  116. package/src/components/Collapsible/Collapsible.module.css +0 -70
  117. package/src/components/Collapsible/Collapsible.stories.tsx +0 -62
  118. package/src/components/Collapsible/Collapsible.tsx +0 -66
  119. package/src/components/Collapsible/__tests__/Collapsible.test.tsx +0 -71
  120. package/src/components/ColorPicker/ColorPicker.module.css +0 -132
  121. package/src/components/ColorPicker/ColorPicker.stories.tsx +0 -80
  122. package/src/components/ColorPicker/ColorPicker.tsx +0 -157
  123. package/src/components/ColorPicker/__tests__/ColorPicker.test.tsx +0 -117
  124. package/src/components/Combobox/Combobox.module.css +0 -122
  125. package/src/components/Combobox/Combobox.stories.tsx +0 -79
  126. package/src/components/Combobox/Combobox.tsx +0 -186
  127. package/src/components/Combobox/__tests__/Combobox.test.tsx +0 -158
  128. package/src/components/Command/Command.module.css +0 -80
  129. package/src/components/Command/Command.stories.tsx +0 -104
  130. package/src/components/Command/Command.tsx +0 -168
  131. package/src/components/Command/__tests__/Command.test.tsx +0 -162
  132. package/src/components/ConfirmDialog/ConfirmDialog.module.css +0 -113
  133. package/src/components/ConfirmDialog/ConfirmDialog.tsx +0 -150
  134. package/src/components/ConfirmDialog/__tests__/ConfirmDialog.test.tsx +0 -214
  135. package/src/components/ConsentPrompt/ConsentPrompt.module.css +0 -21
  136. package/src/components/ConsentPrompt/ConsentPrompt.stories.tsx +0 -31
  137. package/src/components/ConsentPrompt/ConsentPrompt.tsx +0 -66
  138. package/src/components/ContextMenu/ContextMenu.stories.tsx +0 -81
  139. package/src/components/ContextMenu/ContextMenu.tsx +0 -100
  140. package/src/components/ContextMenu/__tests__/ContextMenu.test.tsx +0 -87
  141. package/src/components/CurrencyInput/CurrencyInput.stories.tsx +0 -50
  142. package/src/components/CurrencyInput/CurrencyInput.tsx +0 -60
  143. package/src/components/DataTable/DataTable.module.css +0 -28
  144. package/src/components/DataTable/DataTable.stories.tsx +0 -74
  145. package/src/components/DataTable/DataTable.tsx +0 -154
  146. package/src/components/DataTable/__tests__/DataTable.test.tsx +0 -123
  147. package/src/components/DatePicker/DatePicker.module.css +0 -61
  148. package/src/components/DatePicker/DatePicker.tsx +0 -103
  149. package/src/components/DatePicker/__tests__/DatePicker.test.tsx +0 -89
  150. package/src/components/DeviceOnlyGate/DeviceOnlyGate.tsx +0 -58
  151. package/src/components/DeviceOnlyGate/__tests__/DeviceOnlyGate.test.tsx +0 -45
  152. package/src/components/DeviceStorageKeyGate/DeviceStorageKeyGate.tsx +0 -100
  153. package/src/components/DeviceStorageKeyGate/__tests__/DeviceStorageKeyGate.test.tsx +0 -119
  154. package/src/components/Dialog/Dialog.module.css +0 -335
  155. package/src/components/Dialog/Dialog.stories.tsx +0 -324
  156. package/src/components/Dialog/Dialog.tsx +0 -254
  157. package/src/components/Dialog/__tests__/Dialog.test.tsx +0 -318
  158. package/src/components/DragHandleRow/DragHandleRow.module.css +0 -57
  159. package/src/components/DragHandleRow/DragHandleRow.tsx +0 -42
  160. package/src/components/Drawer/Drawer.module.css +0 -121
  161. package/src/components/Drawer/Drawer.stories.tsx +0 -132
  162. package/src/components/Drawer/Drawer.tsx +0 -175
  163. package/src/components/Drawer/__tests__/Drawer.test.tsx +0 -226
  164. package/src/components/EmptyState/EmptyState.module.css +0 -27
  165. package/src/components/EmptyState/EmptyState.tsx +0 -27
  166. package/src/components/FileDropzone/FileDropzone.module.css +0 -63
  167. package/src/components/FileDropzone/FileDropzone.tsx +0 -109
  168. package/src/components/FileDropzone/__tests__/FileDropzone.test.tsx +0 -67
  169. package/src/components/FormField/FormField.module.css +0 -33
  170. package/src/components/FormField/FormField.tsx +0 -78
  171. package/src/components/FormField/__tests__/FormField.test.tsx +0 -83
  172. package/src/components/GripIcon/GripIcon.tsx +0 -27
  173. package/src/components/Header/Header.module.css +0 -62
  174. package/src/components/Header/Header.stories.tsx +0 -452
  175. package/src/components/Header/Header.tsx +0 -102
  176. package/src/components/Header/__tests__/Header.test.tsx +0 -104
  177. package/src/components/HeaderFooterLayout/HeaderFooterLayout.module.css +0 -21
  178. package/src/components/HeaderFooterLayout/HeaderFooterLayout.stories.tsx +0 -111
  179. package/src/components/HeaderFooterLayout/HeaderFooterLayout.tsx +0 -54
  180. package/src/components/HeaderFooterLayout/__tests__/HeaderFooterLayout.test.tsx +0 -58
  181. package/src/components/HoverCard/HoverCard.module.css +0 -3
  182. package/src/components/HoverCard/HoverCard.stories.tsx +0 -66
  183. package/src/components/HoverCard/HoverCard.tsx +0 -111
  184. package/src/components/HoverCard/__tests__/HoverCard.test.tsx +0 -99
  185. package/src/components/Icon/Icon.module.css +0 -27
  186. package/src/components/Icon/Icon.stories.tsx +0 -95
  187. package/src/components/Icon/Icon.tsx +0 -43
  188. package/src/components/Icon/__tests__/Icon.test.tsx +0 -40
  189. package/src/components/Icon/icons/activity.tsx +0 -20
  190. package/src/components/Icon/icons/alert-triangle.tsx +0 -22
  191. package/src/components/Icon/icons/apple.tsx +0 -21
  192. package/src/components/Icon/icons/arrow-left-right.tsx +0 -23
  193. package/src/components/Icon/icons/banana.tsx +0 -21
  194. package/src/components/Icon/icons/beef.tsx +0 -22
  195. package/src/components/Icon/icons/beer.tsx +0 -24
  196. package/src/components/Icon/icons/bell.tsx +0 -21
  197. package/src/components/Icon/icons/bold.tsx +0 -20
  198. package/src/components/Icon/icons/calendar.tsx +0 -23
  199. package/src/components/Icon/icons/candy.tsx +0 -24
  200. package/src/components/Icon/icons/carrot.tsx +0 -22
  201. package/src/components/Icon/icons/check.tsx +0 -20
  202. package/src/components/Icon/icons/chevron-down.tsx +0 -20
  203. package/src/components/Icon/icons/chevron-left.tsx +0 -20
  204. package/src/components/Icon/icons/chevron-right.tsx +0 -20
  205. package/src/components/Icon/icons/chevron-up.tsx +0 -20
  206. package/src/components/Icon/icons/circle-check.tsx +0 -21
  207. package/src/components/Icon/icons/circle-chevron-left.tsx +0 -21
  208. package/src/components/Icon/icons/circle-x.tsx +0 -22
  209. package/src/components/Icon/icons/code.tsx +0 -21
  210. package/src/components/Icon/icons/coffee.tsx +0 -23
  211. package/src/components/Icon/icons/cookie.tsx +0 -25
  212. package/src/components/Icon/icons/copy.tsx +0 -21
  213. package/src/components/Icon/icons/credit-card.tsx +0 -21
  214. package/src/components/Icon/icons/croissant.tsx +0 -24
  215. package/src/components/Icon/icons/cup-soda.tsx +0 -23
  216. package/src/components/Icon/icons/database.tsx +0 -22
  217. package/src/components/Icon/icons/download.tsx +0 -22
  218. package/src/components/Icon/icons/drumstick.tsx +0 -21
  219. package/src/components/Icon/icons/egg.tsx +0 -20
  220. package/src/components/Icon/icons/ellipsis-vertical.tsx +0 -22
  221. package/src/components/Icon/icons/external-link.tsx +0 -22
  222. package/src/components/Icon/icons/eye-off.tsx +0 -23
  223. package/src/components/Icon/icons/eye.tsx +0 -21
  224. package/src/components/Icon/icons/file-text.tsx +0 -24
  225. package/src/components/Icon/icons/file.tsx +0 -21
  226. package/src/components/Icon/icons/fish.tsx +0 -25
  227. package/src/components/Icon/icons/folder-closed.tsx +0 -21
  228. package/src/components/Icon/icons/folder-open.tsx +0 -20
  229. package/src/components/Icon/icons/folder.tsx +0 -20
  230. package/src/components/Icon/icons/folders.tsx +0 -21
  231. package/src/components/Icon/icons/grid-2x2.tsx +0 -22
  232. package/src/components/Icon/icons/hat-glasses.tsx +0 -24
  233. package/src/components/Icon/icons/history.tsx +0 -22
  234. package/src/components/Icon/icons/house.tsx +0 -21
  235. package/src/components/Icon/icons/inbox.tsx +0 -21
  236. package/src/components/Icon/icons/index.ts +0 -394
  237. package/src/components/Icon/icons/info.tsx +0 -22
  238. package/src/components/Icon/icons/italic.tsx +0 -22
  239. package/src/components/Icon/icons/layers.tsx +0 -22
  240. package/src/components/Icon/icons/layout-dashboard.tsx +0 -23
  241. package/src/components/Icon/icons/layout-grid.tsx +0 -23
  242. package/src/components/Icon/icons/link.tsx +0 -21
  243. package/src/components/Icon/icons/list-ordered.tsx +0 -25
  244. package/src/components/Icon/icons/list.tsx +0 -25
  245. package/src/components/Icon/icons/lock.tsx +0 -21
  246. package/src/components/Icon/icons/log-out.tsx +0 -22
  247. package/src/components/Icon/icons/luggage.tsx +0 -24
  248. package/src/components/Icon/icons/mail.tsx +0 -21
  249. package/src/components/Icon/icons/map-pin.tsx +0 -21
  250. package/src/components/Icon/icons/menu.tsx +0 -22
  251. package/src/components/Icon/icons/milk.tsx +0 -22
  252. package/src/components/Icon/icons/minus.tsx +0 -20
  253. package/src/components/Icon/icons/package.tsx +0 -23
  254. package/src/components/Icon/icons/paint-bucket.tsx +0 -23
  255. package/src/components/Icon/icons/panel-left.tsx +0 -21
  256. package/src/components/Icon/icons/pencil.tsx +0 -21
  257. package/src/components/Icon/icons/pin.tsx +0 -21
  258. package/src/components/Icon/icons/pizza.tsx +0 -24
  259. package/src/components/Icon/icons/plus.tsx +0 -21
  260. package/src/components/Icon/icons/rectangle-ellipsis.tsx +0 -23
  261. package/src/components/Icon/icons/refresh-cw.tsx +0 -23
  262. package/src/components/Icon/icons/rotate-ccw.tsx +0 -21
  263. package/src/components/Icon/icons/rotate-cw.tsx +0 -21
  264. package/src/components/Icon/icons/route.tsx +0 -22
  265. package/src/components/Icon/icons/salad.tsx +0 -24
  266. package/src/components/Icon/icons/search.tsx +0 -21
  267. package/src/components/Icon/icons/send.tsx +0 -21
  268. package/src/components/Icon/icons/settings.tsx +0 -21
  269. package/src/components/Icon/icons/share-2.tsx +0 -24
  270. package/src/components/Icon/icons/sheet.tsx +0 -24
  271. package/src/components/Icon/icons/shield.tsx +0 -20
  272. package/src/components/Icon/icons/shopping-basket.tsx +0 -26
  273. package/src/components/Icon/icons/sliders-horizontal.tsx +0 -28
  274. package/src/components/Icon/icons/smartphone.tsx +0 -21
  275. package/src/components/Icon/icons/snowflake.tsx +0 -31
  276. package/src/components/Icon/icons/spray-can.tsx +0 -29
  277. package/src/components/Icon/icons/square-kanban.tsx +0 -23
  278. package/src/components/Icon/icons/table.tsx +0 -23
  279. package/src/components/Icon/icons/trash-2.tsx +0 -24
  280. package/src/components/Icon/icons/upload.tsx +0 -22
  281. package/src/components/Icon/icons/user-round-plus.tsx +0 -23
  282. package/src/components/Icon/icons/user.tsx +0 -21
  283. package/src/components/Icon/icons/users.tsx +0 -23
  284. package/src/components/Icon/icons/wine.tsx +0 -23
  285. package/src/components/Icon/icons/x.tsx +0 -21
  286. package/src/components/IconPicker/IconPicker.module.css +0 -63
  287. package/src/components/IconPicker/IconPicker.stories.tsx +0 -84
  288. package/src/components/IconPicker/IconPicker.tsx +0 -90
  289. package/src/components/Input/Input.module.css +0 -52
  290. package/src/components/Input/Input.stories.tsx +0 -86
  291. package/src/components/Input/Input.tsx +0 -20
  292. package/src/components/Input/__tests__/Input.test.tsx +0 -22
  293. package/src/components/Item/Item.module.css +0 -70
  294. package/src/components/Item/Item.stories.tsx +0 -62
  295. package/src/components/Item/Item.tsx +0 -54
  296. package/src/components/Item/__tests__/Item.test.tsx +0 -39
  297. package/src/components/Kbd/Kbd.module.css +0 -14
  298. package/src/components/Kbd/Kbd.stories.tsx +0 -32
  299. package/src/components/Kbd/Kbd.tsx +0 -12
  300. package/src/components/Kbd/__tests__/Kbd.test.tsx +0 -14
  301. package/src/components/Label/Label.module.css +0 -11
  302. package/src/components/Label/Label.stories.tsx +0 -40
  303. package/src/components/Label/Label.tsx +0 -24
  304. package/src/components/Label/__tests__/Label.test.tsx +0 -32
  305. package/src/components/LegalLinks/LegalLinks.module.css +0 -24
  306. package/src/components/LegalLinks/LegalLinks.stories.tsx +0 -22
  307. package/src/components/LegalLinks/LegalLinks.tsx +0 -40
  308. package/src/components/Markdown/Markdown.module.css +0 -73
  309. package/src/components/Markdown/Markdown.stories.tsx +0 -40
  310. package/src/components/Markdown/Markdown.tsx +0 -305
  311. package/src/components/Markdown/__tests__/Markdown.test.tsx +0 -144
  312. package/src/components/Marker/Marker.module.css +0 -33
  313. package/src/components/Marker/Marker.stories.tsx +0 -39
  314. package/src/components/Marker/Marker.tsx +0 -34
  315. package/src/components/Marker/__tests__/Marker.test.tsx +0 -23
  316. package/src/components/MemberMultiSelect/MemberMultiSelect.module.css +0 -27
  317. package/src/components/MemberMultiSelect/MemberMultiSelect.stories.tsx +0 -74
  318. package/src/components/MemberMultiSelect/MemberMultiSelect.tsx +0 -67
  319. package/src/components/Menu/Menu.module.css +0 -90
  320. package/src/components/Menu/Menu.tsx +0 -209
  321. package/src/components/Menu/__tests__/Menu.test.tsx +0 -227
  322. package/src/components/Menubar/Menubar.stories.tsx +0 -52
  323. package/src/components/Menubar/Menubar.tsx +0 -42
  324. package/src/components/Menubar/__tests__/Menubar.test.tsx +0 -45
  325. package/src/components/Message/Message.module.css +0 -99
  326. package/src/components/Message/Message.stories.tsx +0 -79
  327. package/src/components/Message/Message.tsx +0 -41
  328. package/src/components/Message/__tests__/Message.test.tsx +0 -46
  329. package/src/components/MessageScroller/MessageScroller.module.css +0 -65
  330. package/src/components/MessageScroller/MessageScroller.stories.tsx +0 -84
  331. package/src/components/MessageScroller/MessageScroller.tsx +0 -84
  332. package/src/components/MessageScroller/__tests__/MessageScroller.test.tsx +0 -105
  333. package/src/components/MobileAppsDrawer/MobileAppsDrawer.module.css +0 -82
  334. package/src/components/MobileAppsDrawer/MobileAppsDrawer.tsx +0 -78
  335. package/src/components/MobileAppsDrawer/__tests__/MobileAppsDrawer.test.tsx +0 -80
  336. package/src/components/MobileFooter/MobileFooter.module.css +0 -73
  337. package/src/components/MobileFooter/MobileFooter.stories.tsx +0 -47
  338. package/src/components/MobileFooter/MobileFooter.tsx +0 -122
  339. package/src/components/MobileFooter/__tests__/MobileFooter.test.tsx +0 -129
  340. package/src/components/MobileHeader/MobileHeader.module.css +0 -76
  341. package/src/components/MobileHeader/MobileHeader.stories.tsx +0 -57
  342. package/src/components/MobileHeader/MobileHeader.tsx +0 -90
  343. package/src/components/MobileHeader/__tests__/MobileHeader.test.tsx +0 -113
  344. package/src/components/NavList/NavList.module.css +0 -130
  345. package/src/components/NavList/NavList.tsx +0 -136
  346. package/src/components/NavList/__tests__/NavList.test.tsx +0 -109
  347. package/src/components/NavTabs/NavTabs.module.css +0 -50
  348. package/src/components/NavTabs/NavTabs.tsx +0 -61
  349. package/src/components/NavigationMenu/NavigationMenu.module.css +0 -53
  350. package/src/components/NavigationMenu/NavigationMenu.stories.tsx +0 -58
  351. package/src/components/NavigationMenu/NavigationMenu.tsx +0 -125
  352. package/src/components/NavigationMenu/__tests__/NavigationMenu.test.tsx +0 -93
  353. package/src/components/NotificationsPanel/NotificationsPanel.module.css +0 -258
  354. package/src/components/NotificationsPanel/NotificationsPanel.stories.tsx +0 -61
  355. package/src/components/NotificationsPanel/NotificationsPanel.tsx +0 -187
  356. package/src/components/NotificationsPanel/__tests__/NotificationsPanel.test.tsx +0 -78
  357. package/src/components/OfflineGate/OfflineGate.tsx +0 -44
  358. package/src/components/OfflineGate/__tests__/OfflineGate.test.tsx +0 -66
  359. package/src/components/OverlayHeader/OverlayHeader.module.css +0 -98
  360. package/src/components/OverlayHeader/OverlayHeader.tsx +0 -77
  361. package/src/components/OverlayHeader/__tests__/OverlayHeader.test.tsx +0 -69
  362. package/src/components/PageContainer/PageContainer.module.css +0 -82
  363. package/src/components/PageContainer/PageContainer.tsx +0 -64
  364. package/src/components/PageContainer/__tests__/PageContainer.test.tsx +0 -70
  365. package/src/components/PageHeader/PageHeader.module.css +0 -86
  366. package/src/components/PageHeader/PageHeader.tsx +0 -176
  367. package/src/components/PageHeader/__tests__/PageHeader.test.tsx +0 -103
  368. package/src/components/PageLayout/PageLayout.module.css +0 -51
  369. package/src/components/PageLayout/PageLayout.stories.tsx +0 -73
  370. package/src/components/PageLayout/PageLayout.tsx +0 -51
  371. package/src/components/PageLayout/__tests__/PageLayout.test.tsx +0 -34
  372. package/src/components/Pagination/Pagination.module.css +0 -98
  373. package/src/components/Pagination/Pagination.stories.tsx +0 -49
  374. package/src/components/Pagination/Pagination.tsx +0 -87
  375. package/src/components/Pagination/__tests__/Pagination.test.tsx +0 -56
  376. package/src/components/Popover/Popover.module.css +0 -74
  377. package/src/components/Popover/Popover.stories.tsx +0 -357
  378. package/src/components/Popover/Popover.tsx +0 -290
  379. package/src/components/Popover/__tests__/Popover.test.tsx +0 -263
  380. package/src/components/Progress/Progress.module.css +0 -20
  381. package/src/components/Progress/Progress.stories.tsx +0 -40
  382. package/src/components/Progress/Progress.tsx +0 -35
  383. package/src/components/Progress/__tests__/Progress.test.tsx +0 -31
  384. package/src/components/QuantityStepper/QuantityStepper.module.css +0 -67
  385. package/src/components/QuantityStepper/QuantityStepper.stories.tsx +0 -79
  386. package/src/components/QuantityStepper/QuantityStepper.tsx +0 -107
  387. package/src/components/RadioGroup/RadioGroup.module.css +0 -88
  388. package/src/components/RadioGroup/RadioGroup.stories.tsx +0 -69
  389. package/src/components/RadioGroup/RadioGroup.tsx +0 -99
  390. package/src/components/RadioGroup/__tests__/RadioGroup.test.tsx +0 -59
  391. package/src/components/Resizable/Resizable.module.css +0 -70
  392. package/src/components/Resizable/Resizable.stories.tsx +0 -82
  393. package/src/components/Resizable/Resizable.tsx +0 -313
  394. package/src/components/Resizable/__tests__/Resizable.test.tsx +0 -128
  395. package/src/components/ResponsiveSurface/ResponsiveSurface.tsx +0 -24
  396. package/src/components/ResponsiveSurface/__tests__/ResponsiveSurface.test.tsx +0 -73
  397. package/src/components/RootLayout/RootLayout.module.css +0 -12
  398. package/src/components/RootLayout/RootLayout.stories.tsx +0 -125
  399. package/src/components/RootLayout/RootLayout.tsx +0 -185
  400. package/src/components/RootLayout/__tests__/RootLayout.test.tsx +0 -161
  401. package/src/components/ScrollArea/ScrollArea.module.css +0 -20
  402. package/src/components/ScrollArea/ScrollArea.stories.tsx +0 -57
  403. package/src/components/ScrollArea/ScrollArea.tsx +0 -27
  404. package/src/components/ScrollArea/__tests__/ScrollArea.test.tsx +0 -39
  405. package/src/components/SegmentedControl/SegmentedControl.module.css +0 -55
  406. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -118
  407. package/src/components/SegmentedControl/SegmentedControl.tsx +0 -56
  408. package/src/components/SegmentedControl/__tests__/SegmentedControl.test.tsx +0 -63
  409. package/src/components/Select/Select.module.css +0 -82
  410. package/src/components/Select/Select.stories.tsx +0 -115
  411. package/src/components/Select/Select.tsx +0 -48
  412. package/src/components/Select/__tests__/Select.test.tsx +0 -59
  413. package/src/components/Sheet/Sheet.module.css +0 -58
  414. package/src/components/Sheet/Sheet.tsx +0 -109
  415. package/src/components/Sheet/__tests__/Sheet.test.tsx +0 -99
  416. package/src/components/Slider/Slider.module.css +0 -95
  417. package/src/components/Slider/Slider.stories.tsx +0 -64
  418. package/src/components/Slider/Slider.tsx +0 -77
  419. package/src/components/Slider/__tests__/Slider.test.tsx +0 -45
  420. package/src/components/Spinner/Spinner.module.css +0 -39
  421. package/src/components/Spinner/Spinner.tsx +0 -23
  422. package/src/components/SplitMethodSelector/SplitMethodSelector.stories.tsx +0 -33
  423. package/src/components/SplitMethodSelector/SplitMethodSelector.tsx +0 -43
  424. package/src/components/SplitPane/SplitPane.module.css +0 -85
  425. package/src/components/SplitPane/SplitPane.stories.tsx +0 -160
  426. package/src/components/SplitPane/SplitPane.tsx +0 -149
  427. package/src/components/SplitPane/__tests__/SplitPane.test.tsx +0 -51
  428. package/src/components/StatusBadge/StatusBadge.module.css +0 -59
  429. package/src/components/StatusBadge/StatusBadge.stories.tsx +0 -74
  430. package/src/components/StatusBadge/StatusBadge.tsx +0 -65
  431. package/src/components/StepStrip/StepStrip.module.css +0 -53
  432. package/src/components/StepStrip/StepStrip.tsx +0 -74
  433. package/src/components/SuggestionInput/SuggestionInput.module.css +0 -103
  434. package/src/components/SuggestionInput/SuggestionInput.stories.tsx +0 -144
  435. package/src/components/SuggestionInput/SuggestionInput.tsx +0 -207
  436. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.module.css +0 -64
  437. package/src/components/SwipableMobileCarousel/SwipableMobileCarousel.tsx +0 -243
  438. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlide.tsx +0 -35
  439. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideBody.tsx +0 -42
  440. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideFooter.tsx +0 -18
  441. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideHeader.tsx +0 -21
  442. package/src/components/SwipableMobileCarousel/SwipableMobileCarouselSlideParts.module.css +0 -29
  443. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarousel.test.tsx +0 -214
  444. package/src/components/SwipableMobileCarousel/__tests__/SwipableMobileCarouselDevGuard.test.tsx +0 -61
  445. package/src/components/SwipableMobileCarousel/context.ts +0 -13
  446. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.module.css +0 -64
  447. package/src/components/SwipableMobileCarouselDots/SwipableMobileCarouselDots.tsx +0 -73
  448. package/src/components/SwipableMobileCarouselDots/__tests__/SwipableMobileCarouselDots.test.tsx +0 -63
  449. package/src/components/SwipeStack/SwipeStack.module.css +0 -101
  450. package/src/components/SwipeStack/SwipeStack.tsx +0 -199
  451. package/src/components/SwipeStack/SwipeStackCard.tsx +0 -22
  452. package/src/components/SwipeStack/__tests__/SwipeStack.test.tsx +0 -169
  453. package/src/components/SystemBanner/SystemBanner.module.css +0 -79
  454. package/src/components/SystemBanner/SystemBanner.stories.tsx +0 -86
  455. package/src/components/SystemBanner/SystemBanner.tsx +0 -50
  456. package/src/components/SystemBanner/__tests__/SystemBanner.test.tsx +0 -50
  457. package/src/components/Table/Table.module.css +0 -45
  458. package/src/components/Table/Table.stories.tsx +0 -125
  459. package/src/components/Table/Table.tsx +0 -51
  460. package/src/components/Table/__tests__/Table.test.tsx +0 -50
  461. package/src/components/Tabs/Tabs.module.css +0 -56
  462. package/src/components/Tabs/Tabs.stories.tsx +0 -100
  463. package/src/components/Tabs/Tabs.tsx +0 -46
  464. package/src/components/Tabs/__tests__/Tabs.test.tsx +0 -45
  465. package/src/components/TagInput/TagInput.module.css +0 -141
  466. package/src/components/TagInput/TagInput.stories.tsx +0 -109
  467. package/src/components/TagInput/TagInput.tsx +0 -174
  468. package/src/components/TagInput/__tests__/TagInput.test.tsx +0 -69
  469. package/src/components/Textarea/Textarea.module.css +0 -47
  470. package/src/components/Textarea/Textarea.tsx +0 -38
  471. package/src/components/Textarea/__tests__/Textarea.test.tsx +0 -51
  472. package/src/components/ThreeColumnLayout/ThreeColumnLayout.module.css +0 -35
  473. package/src/components/ThreeColumnLayout/ThreeColumnLayout.stories.tsx +0 -152
  474. package/src/components/ThreeColumnLayout/ThreeColumnLayout.tsx +0 -87
  475. package/src/components/ThreeColumnLayout/__tests__/ThreeColumnLayout.test.tsx +0 -78
  476. package/src/components/Toast/Toast.module.css +0 -191
  477. package/src/components/Toast/Toast.stories.tsx +0 -191
  478. package/src/components/Toast/Toast.tsx +0 -139
  479. package/src/components/Toggle/Toggle.module.css +0 -57
  480. package/src/components/Toggle/Toggle.stories.tsx +0 -95
  481. package/src/components/Toggle/Toggle.tsx +0 -39
  482. package/src/components/Toggle/__tests__/Toggle.test.tsx +0 -47
  483. package/src/components/Tooltip/Tooltip.module.css +0 -56
  484. package/src/components/Tooltip/Tooltip.tsx +0 -30
  485. package/src/components/Typography/Typography.module.css +0 -47
  486. package/src/components/Typography/Typography.stories.tsx +0 -62
  487. package/src/components/Typography/Typography.tsx +0 -30
  488. package/src/components/Typography/__tests__/Typography.test.tsx +0 -34
  489. package/src/components/UserMenu/UserMenu.module.css +0 -90
  490. package/src/components/UserMenu/UserMenu.stories.tsx +0 -49
  491. package/src/components/UserMenu/UserMenu.tsx +0 -132
  492. package/src/components/UserMenu/__tests__/UserMenu.test.tsx +0 -77
  493. package/src/css-modules.d.ts +0 -4
  494. package/src/hooks/__tests__/useCarouselRouteSync.test.tsx +0 -126
  495. package/src/hooks/__tests__/useDoubleTap.test.tsx +0 -117
  496. package/src/hooks/__tests__/useIsMobile.test.tsx +0 -80
  497. package/src/hooks/__tests__/useIsOffline.test.tsx +0 -53
  498. package/src/hooks/__tests__/useLongPress.test.tsx +0 -158
  499. package/src/hooks/__tests__/useOfflineTileState.test.tsx +0 -69
  500. package/src/hooks/__tests__/usePublishShellChromeHeight.test.tsx +0 -118
  501. package/src/hooks/__tests__/useReorderSensors.test.ts +0 -26
  502. package/src/hooks/__tests__/useResponsiveLayout.test.tsx +0 -87
  503. package/src/hooks/__tests__/useSnapCarousel.test.tsx +0 -175
  504. package/src/hooks/__tests__/useSwipeReveal.test.tsx +0 -110
  505. package/src/hooks/__tests__/useSwipeStack.test.tsx +0 -155
  506. package/src/hooks/index.ts +0 -33
  507. package/src/hooks/useCarouselRouteSync.ts +0 -92
  508. package/src/hooks/useCommitOnEnterOrBlur.ts +0 -39
  509. package/src/hooks/useDoubleTap.ts +0 -91
  510. package/src/hooks/useIsMobile.ts +0 -33
  511. package/src/hooks/useIsOffline.ts +0 -41
  512. package/src/hooks/useLongPress.ts +0 -185
  513. package/src/hooks/useOfflineTileState.ts +0 -45
  514. package/src/hooks/usePublishShellChromeHeight.ts +0 -96
  515. package/src/hooks/useReorderSensors.ts +0 -88
  516. package/src/hooks/useResponsiveLayout.ts +0 -36
  517. package/src/hooks/useSnapCarousel.ts +0 -284
  518. package/src/hooks/useSwipeReveal.ts +0 -107
  519. package/src/hooks/useSwipeStack.ts +0 -235
  520. package/src/index.ts +0 -311
  521. package/src/motion.ts +0 -78
  522. package/src/overlay-shell.ts +0 -159
  523. package/src/scroll-lock.ts +0 -22
  524. package/src/stories/Avatar.stories.tsx +0 -44
  525. package/src/stories/Card.stories.tsx +0 -35
  526. package/src/stories/Checkbox.stories.tsx +0 -45
  527. package/src/stories/DesignSystemOverview.stories.tsx +0 -3793
  528. package/src/stories/DeviceOnlyGate.stories.tsx +0 -35
  529. package/src/stories/DeviceStorageKeyGate.stories.tsx +0 -57
  530. package/src/stories/DragHandleRow.stories.tsx +0 -41
  531. package/src/stories/EmptyState.stories.tsx +0 -33
  532. package/src/stories/FileDropzone.stories.tsx +0 -69
  533. package/src/stories/FormField.stories.tsx +0 -47
  534. package/src/stories/GripIcon.stories.tsx +0 -29
  535. package/src/stories/InteractionHooks.stories.tsx +0 -925
  536. package/src/stories/LayoutSystem.stories.tsx +0 -639
  537. package/src/stories/MenuEntries.stories.tsx +0 -86
  538. package/src/stories/MobilePatterns.stories.tsx +0 -1536
  539. package/src/stories/NavList.stories.tsx +0 -147
  540. package/src/stories/NavTabs.stories.tsx +0 -53
  541. package/src/stories/OfflineGate.stories.tsx +0 -42
  542. package/src/stories/PageContainer.stories.tsx +0 -82
  543. package/src/stories/PageHeader.stories.tsx +0 -95
  544. package/src/stories/ResponsiveSurface.stories.tsx +0 -47
  545. package/src/stories/Spinner.stories.tsx +0 -25
  546. package/src/stories/StepStrip.stories.tsx +0 -76
  547. package/src/stories/SwipableMobileCarousel.stories.tsx +0 -362
  548. package/src/stories/SwipeStack.stories.tsx +0 -200
  549. package/src/stories/Textarea.stories.tsx +0 -63
  550. package/src/stories/TokenGallery.stories.tsx +0 -652
  551. package/src/stories/Tooltip.stories.tsx +0 -59
  552. package/src/tokens/primitives.css +0 -168
  553. package/src/tokens/semantic.css +0 -162
  554. package/src/tokens/theme-presets.css +0 -33
  555. package/src/tokens/theme-presets.ts +0 -72
  556. package/src/tokens.css +0 -5
@@ -1,66 +0,0 @@
1
- 'use client';
2
-
3
- import { useId } from 'react';
4
- import type { ReactNode } from 'react';
5
- import { Icon } from '../Icon/Icon';
6
- import styles from './Collapsible.module.css';
7
-
8
- export interface CollapsibleProps {
9
- open: boolean;
10
- onOpenChange: (open: boolean) => void;
11
- trigger: ReactNode;
12
- children: ReactNode;
13
- id?: string;
14
- className?: string;
15
- }
16
-
17
- /**
18
- * Collapsible — single expand/collapse primitive. Independently useful
19
- * (e.g. a "show more" toggle), and composed internally by `Accordion`.
20
- *
21
- * The expand/collapse animation uses `grid-template-rows: 0fr` → `1fr`
22
- * rather than animating `height`, which can't transition to/from `auto`
23
- * in CSS without JS-measuring pixel heights. Collapsed content stays in
24
- * the DOM (so no layout jump on re-open) but is marked `inert` — removed
25
- * from the tab order and the accessibility tree — so it isn't reachable
26
- * while hidden.
27
- */
28
- export function Collapsible({
29
- open,
30
- onOpenChange,
31
- trigger,
32
- children,
33
- id,
34
- className,
35
- }: CollapsibleProps) {
36
- const generatedId = useId();
37
- const contentId = `${id ?? generatedId}-content`;
38
-
39
- return (
40
- <div className={[styles.root, className].filter(Boolean).join(' ')}>
41
- <button
42
- type="button"
43
- className={styles.trigger}
44
- aria-expanded={open}
45
- aria-controls={contentId}
46
- onClick={() => onOpenChange(!open)}
47
- >
48
- <span className={styles.triggerLabel}>{trigger}</span>
49
- <Icon
50
- name="chevron-down"
51
- size="sm"
52
- aria-hidden
53
- className={[styles.chevron, open ? styles.chevronOpen : ''].filter(Boolean).join(' ')}
54
- />
55
- </button>
56
- <div
57
- id={contentId}
58
- className={styles.contentWrapper}
59
- data-open={open}
60
- inert={!open || undefined}
61
- >
62
- <div className={styles.contentInner}>{children}</div>
63
- </div>
64
- </div>
65
- );
66
- }
@@ -1,71 +0,0 @@
1
- // @vitest-environment jsdom
2
- import { afterEach, describe, expect, it, vi } from 'vitest';
3
- import { cleanup, render, screen, fireEvent } from '@testing-library/react';
4
- import { Collapsible } from '../Collapsible';
5
-
6
- afterEach(cleanup);
7
-
8
- describe('Collapsible', () => {
9
- it('exposes aria-expanded matching the open prop', () => {
10
- const { rerender } = render(
11
- <Collapsible open={false} onOpenChange={() => {}} trigger="More info">
12
- Body content
13
- </Collapsible>,
14
- );
15
- expect(screen.getByRole('button', { name: 'More info' }).getAttribute('aria-expanded')).toBe(
16
- 'false',
17
- );
18
-
19
- rerender(
20
- <Collapsible open onOpenChange={() => {}} trigger="More info">
21
- Body content
22
- </Collapsible>,
23
- );
24
- expect(screen.getByRole('button', { name: 'More info' }).getAttribute('aria-expanded')).toBe(
25
- 'true',
26
- );
27
- });
28
-
29
- it('calls onOpenChange with the toggled value when the trigger is clicked', () => {
30
- const onOpenChange = vi.fn();
31
- render(
32
- <Collapsible open={false} onOpenChange={onOpenChange} trigger="More info">
33
- Body content
34
- </Collapsible>,
35
- );
36
- fireEvent.click(screen.getByRole('button', { name: 'More info' }));
37
- expect(onOpenChange).toHaveBeenCalledWith(true);
38
- });
39
-
40
- it('marks collapsed content inert', () => {
41
- render(
42
- <Collapsible open={false} onOpenChange={() => {}} trigger="More info">
43
- Body content
44
- </Collapsible>,
45
- );
46
- const content = screen.getByText('Body content').closest('[inert]');
47
- expect(content).not.toBeNull();
48
- });
49
-
50
- it('does not mark expanded content inert', () => {
51
- render(
52
- <Collapsible open onOpenChange={() => {}} trigger="More info">
53
- Body content
54
- </Collapsible>,
55
- );
56
- const content = screen.getByText('Body content').closest('[inert]');
57
- expect(content).toBeNull();
58
- });
59
-
60
- it('associates the trigger with the content via aria-controls', () => {
61
- render(
62
- <Collapsible open onOpenChange={() => {}} trigger="More info" id="details">
63
- Body content
64
- </Collapsible>,
65
- );
66
- const button = screen.getByRole('button', { name: 'More info' });
67
- const controlsId = button.getAttribute('aria-controls');
68
- expect(controlsId).toBeTruthy();
69
- expect(document.getElementById(controlsId ?? '')).not.toBeNull();
70
- });
71
- });
@@ -1,132 +0,0 @@
1
- .row {
2
- display: flex;
3
- flex-wrap: wrap;
4
- gap: var(--sv-space-2);
5
- }
6
-
7
- .swatch {
8
- width: var(--sv-space-8);
9
- height: var(--sv-space-8);
10
- border-radius: var(--sv-radius-md);
11
- border: 2px solid transparent;
12
- padding: 0;
13
- cursor: pointer;
14
- }
15
-
16
- .swatch:disabled {
17
- opacity: 0.5;
18
- cursor: not-allowed;
19
- }
20
-
21
- .swatchSelected {
22
- border-color: var(--sv-color-accent);
23
- outline: 2px solid var(--sv-color-focus-ring);
24
- outline-offset: 1px;
25
- }
26
-
27
- /* Dashed/outlined rather than filled — there's no real color value to paint
28
- for "no color". */
29
- .swatchNone {
30
- display: flex;
31
- align-items: center;
32
- justify-content: center;
33
- background-color: var(--sv-color-surface-sunken);
34
- border: 2px dashed var(--sv-color-border-strong);
35
- color: var(--sv-color-text-muted);
36
- }
37
-
38
- .swatchNone.swatchSelected {
39
- border-style: solid;
40
- }
41
-
42
- /* Wraps the native color input so a decorative "+" glyph can sit on top of
43
- it while it's empty (a native `<input type="color">` can't have DOM
44
- children of its own) and so the same `.swatchSelected` ring used above can
45
- be applied to the wrapper without fighting the input's own default
46
- focus/border rendering. */
47
- .customWrapper {
48
- position: relative;
49
- display: inline-flex;
50
- align-items: center;
51
- justify-content: center;
52
- width: var(--sv-space-8);
53
- height: var(--sv-space-8);
54
- border-radius: var(--sv-radius-md);
55
- border: 2px solid transparent;
56
- }
57
-
58
- .customWrapper.swatchSelected {
59
- /* Same visual treatment as .swatchSelected, but scoped to the wrapper —
60
- the input itself is styled borderless below, so this is the only
61
- border/outline actually rendered for the custom trigger. */
62
- border-color: var(--sv-color-accent);
63
- }
64
-
65
- /* Before a custom color is actually chosen — same dashed/outlined treatment
66
- as .swatchNone, since there's equally no real color value to paint yet. */
67
- .customWrapperEmpty {
68
- background-color: var(--sv-color-surface-sunken);
69
- border-style: dashed;
70
- border-color: var(--sv-color-border-strong);
71
- }
72
-
73
- /* Reset the native control to a plain color swatch matching the curated
74
- ones above — browsers default `<input type="color">` to its own chrome
75
- (a bordered box with visible padding around the swatch). */
76
- .customInput {
77
- width: 100%;
78
- height: 100%;
79
- padding: 0;
80
- border: none;
81
- border-radius: var(--sv-radius-md);
82
- cursor: pointer;
83
- background: none;
84
- }
85
-
86
- /* Invisible but still clickable/focusable while empty — the input always
87
- holds *some* real hex internally (no true empty state), but that value
88
- was never actually chosen by the user, so it must never render as this
89
- trigger's own swatch color. Becomes visible again the moment a real
90
- choice makes it into `value` (`.customWrapperEmpty` stops applying). */
91
- .customWrapperEmpty .customInput {
92
- opacity: 0;
93
- }
94
-
95
- .customInput:disabled {
96
- opacity: 0.5;
97
- cursor: not-allowed;
98
- }
99
-
100
- .customWrapperEmpty .customInput:disabled {
101
- opacity: 0;
102
- }
103
-
104
- .customInput::-webkit-color-swatch-wrapper {
105
- padding: 0;
106
- border-radius: var(--sv-radius-md);
107
- }
108
-
109
- .customInput::-webkit-color-swatch {
110
- border: none;
111
- border-radius: var(--sv-radius-md);
112
- }
113
-
114
- .customInput::-moz-color-swatch {
115
- border: none;
116
- border-radius: var(--sv-radius-md);
117
- }
118
-
119
- /* `inset: 0` alone doesn't center this — the icon already has an explicit
120
- width/height (its own size class), so an absolutely positioned box with
121
- all four insets pinned to 0 resolves against top/left rather than
122
- stretching to let flex centering do anything, landing the glyph in the
123
- corner instead of the middle. `top/left: 50%` + `translate(-50%, -50%)`
124
- centers a fixed-size element regardless of its own dimensions. */
125
- .customPlusIcon {
126
- position: absolute;
127
- top: 50%;
128
- left: 50%;
129
- transform: translate(-50%, -50%);
130
- color: var(--sv-color-text-muted);
131
- pointer-events: none;
132
- }
@@ -1,80 +0,0 @@
1
- import { useState } from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { ColorPicker } from './ColorPicker';
4
-
5
- const meta = {
6
- title: 'Components/ColorPicker',
7
- component: ColorPicker,
8
- parameters: {
9
- layout: 'padded',
10
- docs: {
11
- description: {
12
- component:
13
- 'A row of curated swatch suggestions plus a native `<input type="color">` trigger for picking any color, not just the curated set — every browser\'s own full-spectrum picker, guaranteed valid hex output, no bespoke a11y work.',
14
- },
15
- },
16
- },
17
- args: {
18
- swatches: [],
19
- value: null,
20
- onChange: () => {},
21
- onSelectionComplete: () => {},
22
- 'aria-label': 'Color',
23
- },
24
- } satisfies Meta<typeof ColorPicker>;
25
-
26
- export default meta;
27
- type Story = StoryObj<typeof meta>;
28
-
29
- const SWATCHES = [
30
- { label: 'Sky', value: '#b5c9e8' },
31
- { label: 'Sage', value: '#c9e0c4' },
32
- { label: 'Sand', value: '#e8d3b5' },
33
- { label: 'Clay', value: '#e0c4c4' },
34
- { label: 'Lilac', value: '#d8c4e0' },
35
- { label: 'Ink', value: '#3b5166' },
36
- { label: 'Forest', value: '#3f5c4c' },
37
- ];
38
-
39
- function ControlledColorPicker({
40
- initial = null,
41
- allowNone = false,
42
- }: {
43
- initial?: string | null;
44
- allowNone?: boolean;
45
- }) {
46
- const [value, setValue] = useState<string | null>(initial);
47
- return (
48
- <ColorPicker
49
- swatches={SWATCHES}
50
- value={value}
51
- onChange={setValue}
52
- allowNone={allowNone}
53
- aria-label="Board color"
54
- />
55
- );
56
- }
57
-
58
- export const Default: Story = {
59
- render: () => <ControlledColorPicker initial="#c9e0c4" />,
60
- };
61
-
62
- export const WithNoColorOption: Story = {
63
- render: () => <ControlledColorPicker allowNone />,
64
- };
65
-
66
- export const CustomColorSelected: Story = {
67
- render: () => <ControlledColorPicker initial="#7a3fd6" />,
68
- };
69
-
70
- export const Disabled: Story = {
71
- render: () => (
72
- <ColorPicker
73
- swatches={SWATCHES}
74
- value="#b5c9e8"
75
- onChange={() => {}}
76
- aria-label="Board color"
77
- disabled
78
- />
79
- ),
80
- };
@@ -1,157 +0,0 @@
1
- 'use client';
2
-
3
- import { Icon } from '../Icon/Icon';
4
- import styles from './ColorPicker.module.css';
5
-
6
- export interface ColorPickerSwatch {
7
- /** Accessible name and tooltip, e.g. "Sky". */
8
- label: string;
9
- /** 6-digit hex, e.g. "#b5c9e8". */
10
- value: string;
11
- }
12
-
13
- export interface ColorPickerProps {
14
- /** Curated quick-pick suggestions, in display order. */
15
- swatches: readonly ColorPickerSwatch[];
16
- /** Current hex value, or `null` for no color. Compared case-insensitively
17
- * against `swatches` — a value that doesn't match any swatch renders as
18
- * the active "custom" selection instead. */
19
- value: string | null;
20
- onChange: (value: string | null) => void;
21
- /**
22
- * Fires once after a discrete, complete pick — a swatch click or the "no
23
- * color" click. Optional; most callers don't need it. Deliberately NOT
24
- * fired from the native custom-color `<input type="color">`'s `onChange`
25
- * — that can fire repeatedly while the user is still dragging inside the
26
- * browser's own color dialog, so a caller using this to auto-close a
27
- * wrapping `Popover` would otherwise slam it shut mid-adjustment.
28
- */
29
- onSelectionComplete?: () => void;
30
- /** Shows a leading "no color" option. Off by default — most consumers
31
- * (anything painting a fixed-size chip) always need a real color; only
32
- * a board canvas-style consumer typically wants "none" as a real choice. */
33
- allowNone?: boolean;
34
- noneLabel?: string;
35
- /** Accessible name for the native color-input trigger that lets a user
36
- * pick any color, not just a curated swatch. */
37
- customLabel?: string;
38
- disabled?: boolean;
39
- 'aria-label': string;
40
- className?: string;
41
- }
42
-
43
- function normalize(hex: string): string {
44
- return hex.toLowerCase();
45
- }
46
-
47
- /**
48
- * ColorPicker — a row of curated swatch suggestions plus a native
49
- * `<input type="color">` trigger for picking any color, not just the
50
- * curated set. The native color input is deliberately not a custom-built
51
- * hue/saturation picker: it already gives every browser's own full-spectrum
52
- * picker (with an eyedropper tool in most), guarantees valid hex output, and
53
- * needs no bespoke a11y work of its own.
54
- *
55
- * `value` drives which affordance reads as selected: a hex matching a
56
- * swatch highlights that swatch; a hex matching none of them highlights the
57
- * custom trigger instead (its own dial shows that color); `null` (only
58
- * meaningful with `allowNone`) highlights the "no color" option.
59
- *
60
- * The custom trigger shows a plain "+" on a neutral dashed box until a
61
- * genuinely custom color is active — it never previews an arbitrary dial
62
- * color the user hasn't actually chosen. The underlying native color input
63
- * still needs *some* real hex to hold internally at all times (it has no
64
- * true empty state), so that starting value stays invisible (`opacity: 0`
65
- * on the input itself) rather than painted as this trigger's own swatch.
66
- */
67
- export function ColorPicker({
68
- swatches,
69
- value,
70
- onChange,
71
- onSelectionComplete,
72
- allowNone = false,
73
- noneLabel = 'No color',
74
- customLabel = 'Custom color',
75
- disabled = false,
76
- 'aria-label': ariaLabel,
77
- className,
78
- }: ColorPickerProps) {
79
- const normalizedValue = value ? normalize(value) : null;
80
- const matchedSwatch = swatches.find((s) => normalize(s.value) === normalizedValue);
81
- const isCustomActive = normalizedValue !== null && !matchedSwatch;
82
- // The native input always needs a real hex to display (it has no "empty"
83
- // state) — the active custom color when there is one, otherwise a neutral
84
- // starting point for whenever it's next opened.
85
- const customDialValue = isCustomActive && value ? value : (swatches[0]?.value ?? '#000000');
86
-
87
- return (
88
- <div
89
- className={[styles.row, className].filter(Boolean).join(' ')}
90
- role="group"
91
- aria-label={ariaLabel}
92
- >
93
- {allowNone && (
94
- <button
95
- type="button"
96
- role="radio"
97
- aria-checked={value === null}
98
- aria-label={noneLabel}
99
- title={noneLabel}
100
- disabled={disabled}
101
- className={[styles.swatch, styles.swatchNone, value === null ? styles.swatchSelected : '']
102
- .filter(Boolean)
103
- .join(' ')}
104
- onClick={() => {
105
- onChange(null);
106
- onSelectionComplete?.();
107
- }}
108
- >
109
- <Icon name="x" size="sm" aria-hidden={true} />
110
- </button>
111
- )}
112
- {swatches.map((s) => (
113
- <button
114
- key={s.value}
115
- type="button"
116
- role="radio"
117
- aria-checked={normalize(s.value) === normalizedValue}
118
- aria-label={s.label}
119
- title={s.label}
120
- disabled={disabled}
121
- className={[
122
- styles.swatch,
123
- normalize(s.value) === normalizedValue ? styles.swatchSelected : '',
124
- ]
125
- .filter(Boolean)
126
- .join(' ')}
127
- style={{ backgroundColor: s.value }}
128
- onClick={() => {
129
- onChange(s.value);
130
- onSelectionComplete?.();
131
- }}
132
- />
133
- ))}
134
- <span
135
- className={[
136
- styles.customWrapper,
137
- isCustomActive ? styles.swatchSelected : styles.customWrapperEmpty,
138
- ]
139
- .filter(Boolean)
140
- .join(' ')}
141
- >
142
- <input
143
- type="color"
144
- className={styles.customInput}
145
- aria-label={customLabel}
146
- title={customLabel}
147
- disabled={disabled}
148
- value={customDialValue}
149
- onChange={(e) => onChange(e.target.value)}
150
- />
151
- {!isCustomActive && (
152
- <Icon name="plus" size="sm" aria-hidden={true} className={styles.customPlusIcon} />
153
- )}
154
- </span>
155
- </div>
156
- );
157
- }
@@ -1,117 +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 { ColorPicker } from '../ColorPicker';
5
-
6
- afterEach(cleanup);
7
-
8
- const SWATCHES = [
9
- { label: 'Sky', value: '#b5c9e8' },
10
- { label: 'Sage', value: '#c9e0c4' },
11
- ];
12
-
13
- describe('ColorPicker', () => {
14
- it('renders a swatch button per entry', () => {
15
- render(<ColorPicker swatches={SWATCHES} value={null} onChange={() => {}} aria-label="Color" />);
16
- expect(screen.getByRole('radio', { name: 'Sky' })).toBeTruthy();
17
- expect(screen.getByRole('radio', { name: 'Sage' })).toBeTruthy();
18
- });
19
-
20
- it('marks the swatch matching value as checked', () => {
21
- render(
22
- <ColorPicker swatches={SWATCHES} value="#c9e0c4" onChange={() => {}} aria-label="Color" />,
23
- );
24
- expect(screen.getByRole('radio', { name: 'Sage' }).getAttribute('aria-checked')).toBe('true');
25
- expect(screen.getByRole('radio', { name: 'Sky' }).getAttribute('aria-checked')).toBe('false');
26
- });
27
-
28
- it('matches swatches case-insensitively', () => {
29
- render(
30
- <ColorPicker swatches={SWATCHES} value="#C9E0C4" onChange={() => {}} aria-label="Color" />,
31
- );
32
- expect(screen.getByRole('radio', { name: 'Sage' }).getAttribute('aria-checked')).toBe('true');
33
- });
34
-
35
- it('calls onChange with the swatch value when clicked', () => {
36
- const onChange = vi.fn();
37
- render(<ColorPicker swatches={SWATCHES} value={null} onChange={onChange} aria-label="Color" />);
38
- fireEvent.click(screen.getByRole('radio', { name: 'Sky' }));
39
- expect(onChange).toHaveBeenCalledWith('#b5c9e8');
40
- });
41
-
42
- it('does not render a "no color" option by default', () => {
43
- render(<ColorPicker swatches={SWATCHES} value={null} onChange={() => {}} aria-label="Color" />);
44
- expect(screen.queryByRole('radio', { name: 'No color' })).toBeNull();
45
- });
46
-
47
- it('renders and wires up the "no color" option when allowNone is set', () => {
48
- const onChange = vi.fn();
49
- render(
50
- <ColorPicker
51
- swatches={SWATCHES}
52
- value="#b5c9e8"
53
- onChange={onChange}
54
- allowNone
55
- aria-label="Color"
56
- />,
57
- );
58
- const noneOption = screen.getByRole('radio', { name: 'No color' });
59
- expect(noneOption.getAttribute('aria-checked')).toBe('false');
60
- fireEvent.click(noneOption);
61
- expect(onChange).toHaveBeenCalledWith(null);
62
- });
63
-
64
- it('marks "no color" as checked when value is null', () => {
65
- render(
66
- <ColorPicker
67
- swatches={SWATCHES}
68
- value={null}
69
- onChange={() => {}}
70
- allowNone
71
- aria-label="Color"
72
- />,
73
- );
74
- expect(screen.getByRole('radio', { name: 'No color' }).getAttribute('aria-checked')).toBe(
75
- 'true',
76
- );
77
- });
78
-
79
- it('renders the native color input trigger for custom colors', () => {
80
- render(<ColorPicker swatches={SWATCHES} value={null} onChange={() => {}} aria-label="Color" />);
81
- const custom = screen.getByLabelText('Custom color') as HTMLInputElement;
82
- expect(custom.type).toBe('color');
83
- });
84
-
85
- it('shows the custom value on the native input when it matches no swatch', () => {
86
- render(
87
- <ColorPicker swatches={SWATCHES} value="#7a3fd6" onChange={() => {}} aria-label="Color" />,
88
- );
89
- const custom = screen.getByLabelText('Custom color') as HTMLInputElement;
90
- expect(custom.value).toBe('#7a3fd6');
91
- // Neither curated swatch should read as checked once a custom color is active.
92
- expect(screen.getByRole('radio', { name: 'Sky' }).getAttribute('aria-checked')).toBe('false');
93
- expect(screen.getByRole('radio', { name: 'Sage' }).getAttribute('aria-checked')).toBe('false');
94
- });
95
-
96
- it('calls onChange with the picked value when the custom input changes', () => {
97
- const onChange = vi.fn();
98
- render(<ColorPicker swatches={SWATCHES} value={null} onChange={onChange} aria-label="Color" />);
99
- const custom = screen.getByLabelText('Custom color') as HTMLInputElement;
100
- fireEvent.change(custom, { target: { value: '#123456' } });
101
- expect(onChange).toHaveBeenCalledWith('#123456');
102
- });
103
-
104
- it('disables every swatch and the custom input when disabled', () => {
105
- render(
106
- <ColorPicker
107
- swatches={SWATCHES}
108
- value={null}
109
- onChange={() => {}}
110
- disabled
111
- aria-label="Color"
112
- />,
113
- );
114
- expect((screen.getByRole('radio', { name: 'Sky' }) as HTMLButtonElement).disabled).toBe(true);
115
- expect((screen.getByLabelText('Custom color') as HTMLInputElement).disabled).toBe(true);
116
- });
117
- });