@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,20 +0,0 @@
1
- .root {
2
- overflow: auto;
3
- overscroll-behavior: contain;
4
- scrollbar-width: thin;
5
- scrollbar-color: var(--sv-color-border-strong) transparent;
6
- }
7
-
8
- .root::-webkit-scrollbar {
9
- width: 8px;
10
- height: 8px;
11
- }
12
-
13
- .root::-webkit-scrollbar-track {
14
- background: transparent;
15
- }
16
-
17
- .root::-webkit-scrollbar-thumb {
18
- background: var(--sv-color-border-strong);
19
- border-radius: var(--sv-radius-full);
20
- }
@@ -1,57 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { ScrollArea } from './ScrollArea';
3
-
4
- const meta = {
5
- title: 'Components/ScrollArea',
6
- component: ScrollArea,
7
- parameters: { layout: 'padded' },
8
- args: { children: null },
9
- } satisfies Meta<typeof ScrollArea>;
10
-
11
- export default meta;
12
- type Story = StoryObj<typeof meta>;
13
-
14
- // ---------------------------------------------------------------------------
15
-
16
- export const Vertical: Story = {
17
- render: () => (
18
- <div style={{ width: 280 }}>
19
- <ScrollArea maxHeight={160}>
20
- <div style={{ display: 'flex', flexDirection: 'column', gap: 8, padding: 4 }}>
21
- {Array.from({ length: 20 }, (_, i) => (
22
- <div key={i} style={{ fontSize: 14 }}>
23
- Row {i + 1}
24
- </div>
25
- ))}
26
- </div>
27
- </ScrollArea>
28
- </div>
29
- ),
30
- };
31
-
32
- export const Horizontal: Story = {
33
- render: () => (
34
- <ScrollArea maxWidth={320}>
35
- <div style={{ display: 'flex', gap: 8, padding: 4, width: 'max-content' }}>
36
- {Array.from({ length: 12 }, (_, i) => (
37
- <div
38
- key={i}
39
- style={{
40
- width: 80,
41
- height: 60,
42
- flexShrink: 0,
43
- background: 'var(--sv-color-surface-sunken)',
44
- borderRadius: 'var(--sv-radius-md)',
45
- display: 'flex',
46
- alignItems: 'center',
47
- justifyContent: 'center',
48
- fontSize: 12,
49
- }}
50
- >
51
- {i + 1}
52
- </div>
53
- ))}
54
- </div>
55
- </ScrollArea>
56
- ),
57
- };
@@ -1,27 +0,0 @@
1
- import type { CSSProperties, ReactNode } from 'react';
2
- import styles from './ScrollArea.module.css';
3
-
4
- export interface ScrollAreaProps {
5
- children: ReactNode;
6
- /** Constrains the scrollable direction; content taller/wider than this scrolls. */
7
- maxHeight?: string | number;
8
- maxWidth?: string | number;
9
- className?: string;
10
- }
11
-
12
- /**
13
- * ScrollArea — a styled scrollable container (thin, token-colored scrollbar
14
- * instead of the OS default). Native overflow scrolling underneath — no
15
- * virtualization, no custom scroll physics.
16
- */
17
- export function ScrollArea({ children, maxHeight, maxWidth, className }: ScrollAreaProps) {
18
- const style: CSSProperties = {};
19
- if (maxHeight !== undefined) style.maxHeight = maxHeight;
20
- if (maxWidth !== undefined) style.maxWidth = maxWidth;
21
-
22
- return (
23
- <div className={[styles.root, className].filter(Boolean).join(' ')} style={style}>
24
- {children}
25
- </div>
26
- );
27
- }
@@ -1,39 +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 { ScrollArea } from '../ScrollArea';
5
-
6
- afterEach(cleanup);
7
-
8
- describe('ScrollArea', () => {
9
- it('renders children', () => {
10
- render(
11
- <ScrollArea>
12
- <div>content</div>
13
- </ScrollArea>,
14
- );
15
- expect(screen.getByText('content')).toBeDefined();
16
- });
17
-
18
- it('applies maxHeight/maxWidth as inline styles when given', () => {
19
- render(
20
- <ScrollArea maxHeight={200} maxWidth="100%">
21
- <div data-testid="child">content</div>
22
- </ScrollArea>,
23
- );
24
- const root = screen.getByTestId('child').parentElement;
25
- expect(root?.style.maxHeight).toBe('200px');
26
- expect(root?.style.maxWidth).toBe('100%');
27
- });
28
-
29
- it('does not set maxHeight/maxWidth styles when omitted', () => {
30
- render(
31
- <ScrollArea>
32
- <div data-testid="child">content</div>
33
- </ScrollArea>,
34
- );
35
- const root = screen.getByTestId('child').parentElement;
36
- expect(root?.style.maxHeight).toBe('');
37
- expect(root?.style.maxWidth).toBe('');
38
- });
39
- });
@@ -1,55 +0,0 @@
1
- .track {
2
- display: inline-flex;
3
- background: var(--sv-color-surface-sunken);
4
- border-radius: var(--sv-radius-full);
5
- border: 1px solid var(--sv-color-border);
6
- padding: 2px;
7
- gap: 2px;
8
- }
9
-
10
- /* Size variants */
11
- .md .segment {
12
- padding: var(--sv-space-1) var(--sv-space-3);
13
- font-size: var(--sv-font-size-sm);
14
- }
15
-
16
- .sm .segment {
17
- padding: 2px var(--sv-space-2);
18
- font-size: var(--sv-font-size-caption);
19
- }
20
-
21
- .segment {
22
- border: none;
23
- border-radius: var(--sv-radius-full);
24
- font-family: var(--sv-font-family);
25
- font-weight: var(--sv-font-weight-medium);
26
- line-height: 1;
27
- cursor: pointer;
28
- transition:
29
- background-color 0.12s ease,
30
- color 0.12s ease,
31
- box-shadow 0.12s ease;
32
- white-space: nowrap;
33
- }
34
-
35
- .segment:focus-visible {
36
- outline: 2px solid var(--sv-color-focus-ring);
37
- outline-offset: 1px;
38
- }
39
-
40
- .active {
41
- background: var(--sv-color-surface);
42
- color: var(--sv-color-text-primary);
43
- box-shadow: var(--sv-shadow-card);
44
- }
45
-
46
- .inactive {
47
- background: transparent;
48
- color: var(--sv-color-text-muted);
49
- }
50
-
51
- @media (hover: hover) {
52
- .inactive:hover {
53
- color: var(--sv-color-text-primary);
54
- }
55
- }
@@ -1,118 +0,0 @@
1
- import { useState } from 'react';
2
- import type { Meta, StoryObj } from '@storybook/react-vite';
3
- import { SegmentedControl } from './SegmentedControl';
4
-
5
- const meta = {
6
- title: 'Components/SegmentedControl',
7
- component: SegmentedControl,
8
- parameters: {
9
- layout: 'centered',
10
- docs: {
11
- description: {
12
- component:
13
- 'Pill-based 2–3 option picker for inline use in table rows and dialogs. Renders as `role="radiogroup"` with `role="radio"` segments.',
14
- },
15
- },
16
- },
17
- args: {
18
- value: 'a',
19
- onChange: () => {},
20
- options: [
21
- { label: 'A', value: 'a' },
22
- { label: 'B', value: 'b' },
23
- ],
24
- 'aria-label': 'Select option',
25
- },
26
- } satisfies Meta<typeof SegmentedControl>;
27
-
28
- export default meta;
29
- type Story = StoryObj<typeof meta>;
30
-
31
- // ---------------------------------------------------------------------------
32
-
33
- export const TwoOption: Story = {
34
- render: (_args) => {
35
- const [role, setRole] = useState<'user' | 'admin'>('user');
36
- return (
37
- <SegmentedControl
38
- value={role}
39
- onChange={setRole}
40
- options={[
41
- { label: 'User', value: 'user' },
42
- { label: 'Admin', value: 'admin' },
43
- ]}
44
- aria-label="Role"
45
- />
46
- );
47
- },
48
- };
49
-
50
- export const ThreeOption: Story = {
51
- render: (_args) => {
52
- const [role, setRole] = useState<'user' | 'admin' | 'owner'>('user');
53
- return (
54
- <SegmentedControl
55
- value={role}
56
- onChange={setRole}
57
- options={[
58
- { label: 'User', value: 'user' },
59
- { label: 'Admin', value: 'admin' },
60
- { label: 'Owner', value: 'owner' },
61
- ]}
62
- aria-label="Role"
63
- />
64
- );
65
- },
66
- };
67
-
68
- export const SmallSize: Story = {
69
- render: (_args) => {
70
- const [role, setRole] = useState<'user' | 'admin'>('user');
71
- return (
72
- <SegmentedControl
73
- value={role}
74
- onChange={setRole}
75
- size="sm"
76
- options={[
77
- { label: 'User', value: 'user' },
78
- { label: 'Admin', value: 'admin' },
79
- ]}
80
- aria-label="Role"
81
- />
82
- );
83
- },
84
- };
85
-
86
- /** Table-row context — sm size next to other table content. */
87
- export const InTableRow: Story = {
88
- render: (_args) => {
89
- const [role, setRole] = useState<'user' | 'admin'>('user');
90
- return (
91
- <div
92
- style={{
93
- display: 'flex',
94
- alignItems: 'center',
95
- gap: 16,
96
- padding: '10px 12px',
97
- border: '1px solid var(--sv-color-border)',
98
- borderRadius: 'var(--sv-radius-md)',
99
- fontFamily: 'var(--sv-font-family)',
100
- fontSize: 'var(--sv-font-size-sm)',
101
- color: 'var(--sv-color-text-primary)',
102
- }}
103
- >
104
- <span>Test User</span>
105
- <SegmentedControl
106
- value={role}
107
- onChange={setRole}
108
- size="sm"
109
- options={[
110
- { label: 'User', value: 'user' },
111
- { label: 'Admin', value: 'admin' },
112
- ]}
113
- aria-label="User role"
114
- />
115
- </div>
116
- );
117
- },
118
- };
@@ -1,56 +0,0 @@
1
- 'use client';
2
-
3
- import styles from './SegmentedControl.module.css';
4
-
5
- export interface SegmentedOption<T extends string = string> {
6
- label: string;
7
- value: T;
8
- }
9
-
10
- export interface SegmentedControlProps<T extends string = string> {
11
- value: T;
12
- onChange: (value: T) => void;
13
- options: SegmentedOption<T>[];
14
- size?: 'sm' | 'md';
15
- 'aria-label': string;
16
- }
17
-
18
- /**
19
- * SegmentedControl — pill-based 2–3 option picker for inline use in table rows
20
- * and dialogs (e.g. User / Admin / Owner role switcher).
21
- *
22
- * Renders as `<div role="radiogroup">` with `<button role="radio">` children —
23
- * correct semantics without a native `<input type="radio">` (which needs an id/name
24
- * pair and a `<form>` context to function correctly in all browsers).
25
- */
26
- export function SegmentedControl<T extends string = string>({
27
- value,
28
- onChange,
29
- options,
30
- size = 'md',
31
- 'aria-label': ariaLabel,
32
- }: SegmentedControlProps<T>) {
33
- return (
34
- <div
35
- role="radiogroup"
36
- aria-label={ariaLabel}
37
- className={[styles.track, styles[size]].join(' ')}
38
- >
39
- {options.map((opt) => {
40
- const active = opt.value === value;
41
- return (
42
- <button
43
- key={opt.value}
44
- type="button"
45
- role="radio"
46
- aria-checked={active}
47
- className={[styles.segment, active ? styles.active : styles.inactive].join(' ')}
48
- onClick={() => onChange(opt.value)}
49
- >
50
- {opt.label}
51
- </button>
52
- );
53
- })}
54
- </div>
55
- );
56
- }
@@ -1,63 +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
-
5
- afterEach(cleanup);
6
- import { SegmentedControl } from '../SegmentedControl';
7
-
8
- const options = [
9
- { label: 'User', value: 'user' as const },
10
- { label: 'Admin', value: 'admin' as const },
11
- { label: 'Owner', value: 'owner' as const },
12
- ];
13
-
14
- describe('SegmentedControl', () => {
15
- it('renders all options as radio buttons', () => {
16
- render(
17
- <SegmentedControl value="user" onChange={() => {}} options={options} aria-label="Role" />,
18
- );
19
- expect(screen.getAllByRole('radio').length).toBe(3);
20
- });
21
-
22
- it('marks the active option as checked', () => {
23
- render(
24
- <SegmentedControl value="admin" onChange={() => {}} options={options} aria-label="Role" />,
25
- );
26
- expect(screen.getByRole('radio', { name: 'Admin' }).getAttribute('aria-checked')).toBe('true');
27
- expect(screen.getByRole('radio', { name: 'User' }).getAttribute('aria-checked')).toBe('false');
28
- });
29
-
30
- it('calls onChange with the selected value on click', () => {
31
- const onChange = vi.fn();
32
- render(
33
- <SegmentedControl value="user" onChange={onChange} options={options} aria-label="Role" />,
34
- );
35
- fireEvent.click(screen.getByRole('radio', { name: 'Admin' }));
36
- expect(onChange).toHaveBeenCalledWith('admin');
37
- });
38
-
39
- it('exposes a radiogroup with the given aria-label', () => {
40
- render(
41
- <SegmentedControl
42
- value="user"
43
- onChange={() => {}}
44
- options={options}
45
- aria-label="Select role"
46
- />,
47
- );
48
- expect(screen.getByRole('radiogroup', { name: 'Select role' })).toBeDefined();
49
- });
50
-
51
- it('applies size class to the track', () => {
52
- const { container } = render(
53
- <SegmentedControl
54
- value="user"
55
- onChange={() => {}}
56
- options={options}
57
- size="sm"
58
- aria-label="Role"
59
- />,
60
- );
61
- expect((container.firstChild as HTMLElement).className).toContain('sm');
62
- });
63
- });
@@ -1,82 +0,0 @@
1
- /* Wrapper provides the positioning context for the custom chevron */
2
- .wrapper {
3
- position: relative;
4
- display: block;
5
- width: 100%;
6
- }
7
-
8
- .select {
9
- display: block;
10
- width: 100%;
11
- /* 36px rendered height. Explicit height + border-box, same technique as
12
- Input. Right-pad to clear the custom chevron. */
13
- height: 36px;
14
- box-sizing: border-box;
15
- padding: 4px var(--sv-space-8) 4px var(--sv-space-3);
16
- font-family: var(--sv-font-family);
17
- font-size: var(--sv-font-size-sm);
18
- line-height: 1.5;
19
- color: var(--sv-color-text-primary);
20
- background-color: var(--sv-color-surface);
21
- border: 1px solid var(--sv-color-border-strong);
22
- border-radius: var(--sv-radius-md);
23
- cursor: pointer;
24
- /* Remove native OS chevron */
25
- appearance: none;
26
- transition:
27
- border-color 0.15s ease,
28
- box-shadow 0.15s ease;
29
- }
30
-
31
- /* sm — compact for table cells and inline controls. 32px height. */
32
- .sm .select {
33
- height: 32px;
34
- padding: 2px var(--sv-space-6) 2px var(--sv-space-2);
35
- font-size: var(--sv-font-size-sm);
36
- line-height: 1.4;
37
- border-radius: var(--sv-radius-sm);
38
- }
39
-
40
- /* iOS Safari zooms the page when a <select> under 16px receives focus, exactly
41
- as it does for text inputs. Lift the default size to >=16px on touch devices;
42
- the compact `.sm` variant is for dense desktop tables and is left untouched. */
43
- @media (pointer: coarse) {
44
- .select {
45
- font-size: var(--sv-font-size-md);
46
- }
47
- }
48
-
49
- .select:focus-visible {
50
- outline: none;
51
- border-color: var(--sv-color-accent);
52
- box-shadow: 0 0 0 2px var(--sv-color-focus-ring);
53
- }
54
-
55
- .select:disabled {
56
- opacity: 0.5;
57
- cursor: not-allowed;
58
- }
59
-
60
- /* Compact size variant — reduced padding for table-cell usage */
61
- .sm .select {
62
- padding-top: var(--sv-space-1);
63
- padding-bottom: var(--sv-space-1);
64
- font-size: var(--sv-font-size-sm);
65
- }
66
-
67
- /* SVG chevron — matches the icon stroke style used across the UI */
68
- .chevron {
69
- pointer-events: none;
70
- position: absolute;
71
- right: var(--sv-space-3);
72
- top: 50%;
73
- transform: translateY(-50%);
74
- color: var(--sv-color-text-muted);
75
- flex-shrink: 0;
76
- }
77
-
78
- .sm .chevron {
79
- right: var(--sv-space-2);
80
- width: 10px;
81
- height: 10px;
82
- }
@@ -1,115 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import { Select } from './Select';
3
-
4
- const meta = {
5
- title: 'Components/Select',
6
- component: Select,
7
- parameters: {
8
- layout: 'centered',
9
- docs: {
10
- description: {
11
- component:
12
- 'Styled native `<select>` — same visual language as `Input`. Preserves native picker on mobile for maximum accessibility. RSC-safe.',
13
- },
14
- },
15
- },
16
- argTypes: {
17
- disabled: { control: 'boolean' },
18
- },
19
- } satisfies Meta<typeof Select>;
20
-
21
- export default meta;
22
- type Story = StoryObj<typeof meta>;
23
-
24
- // ---------------------------------------------------------------------------
25
-
26
- export const Default: Story = {
27
- render: (_args) => (
28
- <div style={{ width: 280, fontFamily: 'var(--sv-font-family)' }}>
29
- <label
30
- htmlFor="role-select"
31
- style={{
32
- display: 'block',
33
- marginBottom: 4,
34
- fontSize: 'var(--sv-font-size-sm)',
35
- fontWeight: 'var(--sv-font-weight-medium)',
36
- color: 'var(--sv-color-text-primary)',
37
- }}
38
- >
39
- Role
40
- </label>
41
- <Select id="role-select" defaultValue="user">
42
- <option value="user">User</option>
43
- <option value="admin">Admin</option>
44
- <option value="owner">Owner</option>
45
- </Select>
46
- </div>
47
- ),
48
- };
49
-
50
- export const Disabled: Story = {
51
- render: (_args) => (
52
- <div style={{ width: 280 }}>
53
- <Select disabled defaultValue="user">
54
- <option value="user">User</option>
55
- <option value="admin">Admin</option>
56
- </Select>
57
- </div>
58
- ),
59
- };
60
-
61
- /** Form context — several fields together matching the spec layout. */
62
- export const FormContext: Story = {
63
- render: (_args) => {
64
- const fieldStyle: React.CSSProperties = {
65
- display: 'flex',
66
- flexDirection: 'column',
67
- gap: 4,
68
- };
69
- const labelStyle: React.CSSProperties = {
70
- fontSize: 'var(--sv-font-size-sm)',
71
- fontWeight: 'var(--sv-font-weight-medium)',
72
- color: 'var(--sv-color-text-primary)',
73
- fontFamily: 'var(--sv-font-family)',
74
- };
75
-
76
- return (
77
- <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: 16 }}>
78
- <div style={fieldStyle}>
79
- <label htmlFor="lang-select" style={labelStyle}>
80
- Language
81
- </label>
82
- <Select id="lang-select" defaultValue="en-us">
83
- <option value="en-us">English (US)</option>
84
- <option value="en-gb">English (UK)</option>
85
- <option value="fr">Français</option>
86
- <option value="de">Deutsch</option>
87
- <option value="ja">日本語</option>
88
- </Select>
89
- </div>
90
- <div style={fieldStyle}>
91
- <label htmlFor="tz-select" style={labelStyle}>
92
- Timezone
93
- </label>
94
- <Select id="tz-select" defaultValue="asia-colombo">
95
- <option value="asia-colombo">Asia/Colombo (UTC+5:30)</option>
96
- <option value="utc">UTC</option>
97
- <option value="america-ny">America/New_York (UTC−5)</option>
98
- <option value="europe-london">Europe/London (UTC+0)</option>
99
- </Select>
100
- </div>
101
- <div style={fieldStyle}>
102
- <label htmlFor="poll-select" style={labelStyle}>
103
- Poll interval
104
- </label>
105
- <Select id="poll-select" defaultValue="30">
106
- <option value="15">Every 15 seconds</option>
107
- <option value="30">Every 30 seconds</option>
108
- <option value="60">Every minute</option>
109
- <option value="300">Every 5 minutes</option>
110
- </Select>
111
- </div>
112
- </div>
113
- );
114
- },
115
- };
@@ -1,48 +0,0 @@
1
- import type { SelectHTMLAttributes } from 'react';
2
- import styles from './Select.module.css';
3
-
4
- export type SelectProps = Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'> & {
5
- /** 'md' (default) — standard form field height. 'sm' — compact for table cells and inline controls. */
6
- size?: 'sm' | 'md';
7
- };
8
-
9
- /**
10
- * Select — styled wrapper around the native `<select>`. Inherits the same
11
- * height, border, radius, and focus ring as `Input` for visual consistency.
12
- * Uses the native picker on mobile — no custom dropdown, maximum a11y coverage.
13
- *
14
- * RSC-safe: presentational, no hooks, forwards all native select props.
15
- *
16
- * `className` sizes the outer box (the wrapper), not the `<select>` itself —
17
- * the chevron is absolutely positioned against the wrapper, so a className
18
- * that constrains only the `<select>` (e.g. `max-width`) shrinks the select
19
- * while the wrapper (and thus the chevron) stays full width, leaving the
20
- * chevron stranded past the visible box.
21
- */
22
- export function Select({ className, size = 'md', children, ...rest }: SelectProps) {
23
- return (
24
- <div
25
- className={[styles.wrapper, size === 'sm' ? styles.sm : undefined, className]
26
- .filter(Boolean)
27
- .join(' ')}
28
- >
29
- <select className={styles.select} {...rest}>
30
- {children}
31
- </select>
32
- <svg
33
- className={styles.chevron}
34
- aria-hidden="true"
35
- width="12"
36
- height="12"
37
- viewBox="0 0 24 24"
38
- fill="none"
39
- stroke="currentColor"
40
- strokeWidth="2"
41
- strokeLinecap="round"
42
- strokeLinejoin="round"
43
- >
44
- <polyline points="6 9 12 15 18 9" />
45
- </svg>
46
- </div>
47
- );
48
- }