@ds-mo/ui 0.2.4 → 0.4.0

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 (356) hide show
  1. package/dist/components/ds-accordion.d.ts +11 -0
  2. package/dist/components/ds-accordion.js +2 -0
  3. package/dist/components/ds-accordion.js.map +1 -0
  4. package/dist/components/ds-badge.d.ts +11 -0
  5. package/dist/components/ds-badge.js +2 -0
  6. package/dist/components/ds-badge.js.map +1 -0
  7. package/dist/components/ds-banner.d.ts +11 -0
  8. package/dist/components/ds-banner.js +2 -0
  9. package/dist/components/ds-banner.js.map +1 -0
  10. package/dist/components/ds-breadcrumb.d.ts +11 -0
  11. package/dist/components/ds-breadcrumb.js +2 -0
  12. package/dist/components/ds-breadcrumb.js.map +1 -0
  13. package/dist/components/ds-button.d.ts +11 -0
  14. package/dist/components/ds-button.js +2 -0
  15. package/dist/components/ds-button.js.map +1 -0
  16. package/dist/components/ds-card.d.ts +11 -0
  17. package/dist/components/ds-card.js +2 -0
  18. package/dist/components/ds-card.js.map +1 -0
  19. package/dist/components/ds-checkbox.d.ts +11 -0
  20. package/dist/components/ds-checkbox.js +2 -0
  21. package/dist/components/ds-checkbox.js.map +1 -0
  22. package/dist/components/ds-divider.d.ts +11 -0
  23. package/dist/components/ds-divider.js +2 -0
  24. package/dist/components/ds-divider.js.map +1 -0
  25. package/dist/components/ds-empty-state.d.ts +11 -0
  26. package/dist/components/ds-empty-state.js +2 -0
  27. package/dist/components/ds-empty-state.js.map +1 -0
  28. package/dist/components/ds-fade.d.ts +11 -0
  29. package/dist/components/ds-fade.js +2 -0
  30. package/dist/components/ds-fade.js.map +1 -0
  31. package/dist/components/ds-field.d.ts +11 -0
  32. package/dist/components/ds-field.js +2 -0
  33. package/dist/components/ds-field.js.map +1 -0
  34. package/dist/components/ds-header.d.ts +11 -0
  35. package/dist/components/ds-header.js +2 -0
  36. package/dist/components/ds-header.js.map +1 -0
  37. package/dist/components/ds-input.d.ts +11 -0
  38. package/dist/components/ds-input.js +2 -0
  39. package/dist/components/ds-input.js.map +1 -0
  40. package/dist/components/ds-loader.d.ts +11 -0
  41. package/dist/components/ds-loader.js +2 -0
  42. package/dist/components/ds-loader.js.map +1 -0
  43. package/dist/components/ds-menu.d.ts +11 -0
  44. package/dist/components/ds-menu.js +2 -0
  45. package/dist/components/ds-menu.js.map +1 -0
  46. package/dist/components/ds-modal.d.ts +11 -0
  47. package/dist/components/ds-modal.js +2 -0
  48. package/dist/components/ds-modal.js.map +1 -0
  49. package/dist/components/ds-pagination.d.ts +11 -0
  50. package/dist/components/ds-pagination.js +2 -0
  51. package/dist/components/ds-pagination.js.map +1 -0
  52. package/dist/components/ds-radio-group.d.ts +11 -0
  53. package/dist/components/ds-radio-group.js +2 -0
  54. package/dist/components/ds-radio-group.js.map +1 -0
  55. package/dist/components/ds-scrollbar.d.ts +11 -0
  56. package/dist/components/ds-scrollbar.js +2 -0
  57. package/dist/components/ds-scrollbar.js.map +1 -0
  58. package/dist/components/ds-sidebar.d.ts +11 -0
  59. package/dist/components/ds-sidebar.js +2 -0
  60. package/dist/components/ds-sidebar.js.map +1 -0
  61. package/dist/components/ds-skeleton.d.ts +11 -0
  62. package/dist/components/ds-skeleton.js +2 -0
  63. package/dist/components/ds-skeleton.js.map +1 -0
  64. package/dist/components/ds-slider.d.ts +11 -0
  65. package/dist/components/ds-slider.js +2 -0
  66. package/dist/components/ds-slider.js.map +1 -0
  67. package/dist/components/ds-surface.d.ts +11 -0
  68. package/dist/components/ds-surface.js +2 -0
  69. package/dist/components/ds-surface.js.map +1 -0
  70. package/dist/components/ds-tab-group.d.ts +11 -0
  71. package/dist/components/ds-tab-group.js +2 -0
  72. package/dist/components/ds-tab-group.js.map +1 -0
  73. package/dist/components/ds-table.d.ts +11 -0
  74. package/dist/components/ds-table.js +2 -0
  75. package/dist/components/ds-table.js.map +1 -0
  76. package/dist/components/ds-tag.d.ts +11 -0
  77. package/dist/components/ds-tag.js +2 -0
  78. package/dist/components/ds-tag.js.map +1 -0
  79. package/dist/components/ds-text.d.ts +11 -0
  80. package/dist/components/ds-text.js +2 -0
  81. package/dist/components/ds-text.js.map +1 -0
  82. package/dist/components/ds-toast-provider.d.ts +11 -0
  83. package/dist/components/ds-toast-provider.js +2 -0
  84. package/dist/components/ds-toast-provider.js.map +1 -0
  85. package/dist/components/ds-toggle.d.ts +11 -0
  86. package/dist/components/ds-toggle.js +2 -0
  87. package/dist/components/ds-toggle.js.map +1 -0
  88. package/dist/components/ds-tooltip.d.ts +11 -0
  89. package/dist/components/ds-tooltip.js +2 -0
  90. package/dist/components/ds-tooltip.js.map +1 -0
  91. package/dist/components/index.d.ts +33 -0
  92. package/dist/components/index.js +2 -0
  93. package/dist/components/index.js.map +1 -0
  94. package/dist/components/p-BcuUR5Ao.js +2 -0
  95. package/dist/components/p-BcuUR5Ao.js.map +1 -0
  96. package/dist/types/.stencil/Accordion/Accordion.d.ts +28 -0
  97. package/dist/types/.stencil/Badge/Badge.d.ts +8 -0
  98. package/dist/types/.stencil/Badge/index.d.ts +2 -0
  99. package/dist/types/.stencil/Banner/Banner.d.ts +29 -0
  100. package/dist/types/.stencil/Breadcrumb/Breadcrumb.d.ts +16 -0
  101. package/dist/types/.stencil/Button/Button.d.ts +38 -0
  102. package/dist/types/.stencil/Button/index.d.ts +2 -0
  103. package/dist/types/.stencil/Card/Card.d.ts +8 -0
  104. package/dist/types/.stencil/Checkbox/Checkbox.d.ts +13 -0
  105. package/dist/types/.stencil/Checkbox/index.d.ts +2 -0
  106. package/dist/types/.stencil/Divider/Divider.d.ts +7 -0
  107. package/dist/types/.stencil/Divider/index.d.ts +2 -0
  108. package/dist/types/.stencil/EmptyState/EmptyState.d.ts +7 -0
  109. package/dist/types/.stencil/Fade/Fade.d.ts +10 -0
  110. package/dist/types/.stencil/Fade/index.d.ts +2 -0
  111. package/dist/types/.stencil/Field/Field.d.ts +8 -0
  112. package/dist/types/.stencil/Header/Header.d.ts +7 -0
  113. package/dist/types/.stencil/Input/Input.d.ts +26 -0
  114. package/dist/types/.stencil/Input/index.d.ts +2 -0
  115. package/dist/types/.stencil/Loader/Loader.d.ts +12 -0
  116. package/dist/types/.stencil/Loader/index.d.ts +2 -0
  117. package/dist/types/.stencil/Menu/Menu.d.ts +60 -0
  118. package/dist/types/.stencil/Modal/Modal.d.ts +31 -0
  119. package/dist/types/.stencil/Pagination/Pagination.d.ts +11 -0
  120. package/dist/types/.stencil/RadioGroup/RadioGroup.d.ts +21 -0
  121. package/dist/types/.stencil/RadioGroup/index.d.ts +2 -0
  122. package/dist/types/.stencil/Scrollbar/Scrollbar.d.ts +27 -0
  123. package/dist/types/.stencil/Sidebar/Sidebar.d.ts +29 -0
  124. package/dist/types/.stencil/Skeleton/Skeleton.d.ts +16 -0
  125. package/dist/types/.stencil/Skeleton/index.d.ts +2 -0
  126. package/dist/types/.stencil/Slider/Slider.d.ts +18 -0
  127. package/dist/types/.stencil/Slider/index.d.ts +2 -0
  128. package/dist/types/.stencil/Surface/Surface.d.ts +22 -0
  129. package/dist/types/.stencil/TabGroup/TabGroup.d.ts +29 -0
  130. package/dist/types/.stencil/Table/Table.d.ts +50 -0
  131. package/dist/types/.stencil/Tag/Tag.d.ts +32 -0
  132. package/dist/types/.stencil/Tag/index.d.ts +2 -0
  133. package/dist/types/.stencil/Text/Text.d.ts +22 -0
  134. package/dist/types/.stencil/Text/index.d.ts +2 -0
  135. package/dist/types/.stencil/Toast/Toast.d.ts +15 -0
  136. package/dist/types/.stencil/Toast/toast-service.d.ts +24 -0
  137. package/dist/types/.stencil/Toggle/Toggle.d.ts +10 -0
  138. package/dist/types/.stencil/Toggle/index.d.ts +2 -0
  139. package/dist/types/.stencil/Tooltip/Tooltip.d.ts +36 -0
  140. package/dist/types/components.d.ts +2024 -0
  141. package/dist/types/stencil-public-runtime.d.ts +1860 -0
  142. package/package.json +33 -29
  143. package/src/angular/angular-component-lib/utils.ts +65 -0
  144. package/src/angular/index.ts +35 -0
  145. package/src/angular/proxies.ts +819 -0
  146. package/dist/index.css +0 -2
  147. package/dist/index.d.ts +0 -969
  148. package/dist/index.js +0 -2492
  149. package/dist/index.js.map +0 -1
  150. package/dist/r/accordion.json +0 -79
  151. package/dist/r/badge.json +0 -69
  152. package/dist/r/banner.json +0 -90
  153. package/dist/r/breadcrumb.json +0 -70
  154. package/dist/r/button-group.json +0 -65
  155. package/dist/r/button.json +0 -137
  156. package/dist/r/card.json +0 -82
  157. package/dist/r/checkbox.json +0 -91
  158. package/dist/r/divider.json +0 -57
  159. package/dist/r/empty-state.json +0 -69
  160. package/dist/r/error-boundary.json +0 -66
  161. package/dist/r/fade.json +0 -65
  162. package/dist/r/field.json +0 -71
  163. package/dist/r/header.json +0 -67
  164. package/dist/r/input.json +0 -77
  165. package/dist/r/loader.json +0 -54
  166. package/dist/r/menu.json +0 -130
  167. package/dist/r/modal.json +0 -93
  168. package/dist/r/pagination.json +0 -80
  169. package/dist/r/radio.json +0 -85
  170. package/dist/r/registry.json +0 -1600
  171. package/dist/r/scrollbar.json +0 -68
  172. package/dist/r/select.json +0 -93
  173. package/dist/r/sidebar.json +0 -105
  174. package/dist/r/skeleton.json +0 -72
  175. package/dist/r/slider.json +0 -87
  176. package/dist/r/surface.json +0 -97
  177. package/dist/r/tab-group.json +0 -72
  178. package/dist/r/tab.json +0 -71
  179. package/dist/r/table.json +0 -110
  180. package/dist/r/tag.json +0 -110
  181. package/dist/r/text.json +0 -94
  182. package/dist/r/toast.json +0 -77
  183. package/dist/r/toggle-button-group.json +0 -65
  184. package/dist/r/toggle-button.json +0 -94
  185. package/dist/r/toggle.json +0 -65
  186. package/dist/r/tooltip.json +0 -86
  187. package/src/components/Accordion/Accordion.module.css +0 -66
  188. package/src/components/Accordion/Accordion.stories.tsx +0 -95
  189. package/src/components/Accordion/Accordion.tsx +0 -122
  190. package/src/components/Accordion/index.ts +0 -2
  191. package/src/components/Badge/Badge.module.css +0 -6
  192. package/src/components/Badge/Badge.stories.tsx +0 -99
  193. package/src/components/Badge/Badge.tsx +0 -23
  194. package/src/components/Badge/index.ts +0 -2
  195. package/src/components/Banner/Banner.module.css +0 -67
  196. package/src/components/Banner/Banner.stories.tsx +0 -81
  197. package/src/components/Banner/Banner.tsx +0 -109
  198. package/src/components/Banner/index.ts +0 -2
  199. package/src/components/Breadcrumb/Breadcrumb.module.css +0 -46
  200. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -72
  201. package/src/components/Breadcrumb/Breadcrumb.tsx +0 -68
  202. package/src/components/Breadcrumb/index.ts +0 -2
  203. package/src/components/Button/Button.mdx +0 -143
  204. package/src/components/Button/Button.module.css +0 -343
  205. package/src/components/Button/Button.stories.tsx +0 -575
  206. package/src/components/Button/Button.tsx +0 -201
  207. package/src/components/Button/index.ts +0 -10
  208. package/src/components/ButtonGroup/ButtonGroup.module.css +0 -157
  209. package/src/components/ButtonGroup/ButtonGroup.stories.tsx +0 -384
  210. package/src/components/ButtonGroup/ButtonGroup.tsx +0 -122
  211. package/src/components/ButtonGroup/index.ts +0 -2
  212. package/src/components/Card/Card.module.css +0 -36
  213. package/src/components/Card/Card.stories.tsx +0 -78
  214. package/src/components/Card/Card.tsx +0 -53
  215. package/src/components/Card/index.ts +0 -2
  216. package/src/components/Checkbox/Checkbox.module.css +0 -47
  217. package/src/components/Checkbox/Checkbox.stories.tsx +0 -129
  218. package/src/components/Checkbox/Checkbox.tsx +0 -68
  219. package/src/components/Checkbox/index.ts +0 -2
  220. package/src/components/Divider/Divider.module.css +0 -19
  221. package/src/components/Divider/Divider.stories.tsx +0 -55
  222. package/src/components/Divider/Divider.tsx +0 -28
  223. package/src/components/Divider/index.ts +0 -2
  224. package/src/components/EmptyState/EmptyState.module.css +0 -8
  225. package/src/components/EmptyState/EmptyState.stories.tsx +0 -53
  226. package/src/components/EmptyState/EmptyState.tsx +0 -31
  227. package/src/components/EmptyState/index.ts +0 -2
  228. package/src/components/ErrorBoundary/ErrorBoundary.module.css +0 -18
  229. package/src/components/ErrorBoundary/ErrorBoundary.stories.tsx +0 -38
  230. package/src/components/ErrorBoundary/ErrorBoundary.tsx +0 -50
  231. package/src/components/ErrorBoundary/index.ts +0 -2
  232. package/src/components/Fade/Fade.module.css +0 -31
  233. package/src/components/Fade/Fade.stories.tsx +0 -35
  234. package/src/components/Fade/Fade.tsx +0 -33
  235. package/src/components/Fade/index.ts +0 -2
  236. package/src/components/Field/Field.module.css +0 -5
  237. package/src/components/Field/Field.stories.tsx +0 -111
  238. package/src/components/Field/Field.tsx +0 -22
  239. package/src/components/Field/index.ts +0 -2
  240. package/src/components/Header/Header.module.css +0 -33
  241. package/src/components/Header/Header.stories.tsx +0 -52
  242. package/src/components/Header/Header.tsx +0 -42
  243. package/src/components/Header/index.ts +0 -2
  244. package/src/components/Input/Input.module.css +0 -71
  245. package/src/components/Input/Input.stories.tsx +0 -135
  246. package/src/components/Input/Input.tsx +0 -76
  247. package/src/components/Input/index.ts +0 -2
  248. package/src/components/LabelWrap/LabelWrap.module.css +0 -34
  249. package/src/components/LabelWrap/LabelWrap.tsx +0 -32
  250. package/src/components/LabelWrap/index.ts +0 -1
  251. package/src/components/Loader/Loader.module.css +0 -9
  252. package/src/components/Loader/Loader.stories.tsx +0 -44
  253. package/src/components/Loader/Loader.tsx +0 -43
  254. package/src/components/Loader/index.ts +0 -2
  255. package/src/components/Menu/DestructiveMenuItem.module.css +0 -57
  256. package/src/components/Menu/DestructiveMenuItem.tsx +0 -64
  257. package/src/components/Menu/Menu.module.css +0 -49
  258. package/src/components/Menu/Menu.stories.tsx +0 -129
  259. package/src/components/Menu/Menu.tsx +0 -269
  260. package/src/components/Menu/MenuItem.module.css +0 -84
  261. package/src/components/Menu/MenuItem.tsx +0 -101
  262. package/src/components/Menu/index.ts +0 -6
  263. package/src/components/Modal/Modal.module.css +0 -67
  264. package/src/components/Modal/Modal.stories.tsx +0 -71
  265. package/src/components/Modal/Modal.tsx +0 -122
  266. package/src/components/Modal/index.ts +0 -2
  267. package/src/components/Pagination/Pagination.module.css +0 -64
  268. package/src/components/Pagination/Pagination.stories.tsx +0 -51
  269. package/src/components/Pagination/Pagination.tsx +0 -103
  270. package/src/components/Pagination/index.ts +0 -2
  271. package/src/components/Radio/Radio.module.css +0 -61
  272. package/src/components/Radio/Radio.stories.tsx +0 -101
  273. package/src/components/Radio/Radio.tsx +0 -108
  274. package/src/components/Radio/index.ts +0 -2
  275. package/src/components/Scrollbar/Scrollbar.module.css +0 -81
  276. package/src/components/Scrollbar/Scrollbar.stories.tsx +0 -46
  277. package/src/components/Scrollbar/Scrollbar.tsx +0 -187
  278. package/src/components/Scrollbar/index.ts +0 -2
  279. package/src/components/Select/Select.module.css +0 -31
  280. package/src/components/Select/Select.stories.tsx +0 -59
  281. package/src/components/Select/Select.tsx +0 -92
  282. package/src/components/Select/index.ts +0 -2
  283. package/src/components/Sidebar/Sidebar.module.css +0 -161
  284. package/src/components/Sidebar/Sidebar.stories.tsx +0 -125
  285. package/src/components/Sidebar/Sidebar.tsx +0 -129
  286. package/src/components/Sidebar/SidebarItem.tsx +0 -57
  287. package/src/components/Sidebar/SidebarSection.tsx +0 -42
  288. package/src/components/Sidebar/index.ts +0 -6
  289. package/src/components/Skeleton/Skeleton.module.css +0 -53
  290. package/src/components/Skeleton/Skeleton.stories.tsx +0 -89
  291. package/src/components/Skeleton/Skeleton.tsx +0 -66
  292. package/src/components/Skeleton/index.ts +0 -2
  293. package/src/components/Slider/Slider.module.css +0 -62
  294. package/src/components/Slider/Slider.stories.tsx +0 -120
  295. package/src/components/Slider/Slider.tsx +0 -74
  296. package/src/components/Slider/index.ts +0 -2
  297. package/src/components/Surface/Surface.module.css +0 -222
  298. package/src/components/Surface/Surface.stories.tsx +0 -213
  299. package/src/components/Surface/Surface.tsx +0 -219
  300. package/src/components/Surface/index.ts +0 -12
  301. package/src/components/Tab/Tab.module.css +0 -66
  302. package/src/components/Tab/Tab.stories.tsx +0 -103
  303. package/src/components/Tab/Tab.tsx +0 -41
  304. package/src/components/Tab/index.ts +0 -2
  305. package/src/components/TabGroup/TabGroup.module.css +0 -26
  306. package/src/components/TabGroup/TabGroup.stories.tsx +0 -60
  307. package/src/components/TabGroup/TabGroup.tsx +0 -83
  308. package/src/components/TabGroup/index.ts +0 -2
  309. package/src/components/Table/Table.module.css +0 -130
  310. package/src/components/Table/Table.stories.tsx +0 -111
  311. package/src/components/Table/Table.tsx +0 -226
  312. package/src/components/Table/index.ts +0 -11
  313. package/src/components/Tag/Tag.module.css +0 -270
  314. package/src/components/Tag/Tag.stories.tsx +0 -399
  315. package/src/components/Tag/Tag.tsx +0 -162
  316. package/src/components/Tag/index.ts +0 -2
  317. package/src/components/Text/Text.module.css +0 -166
  318. package/src/components/Text/Text.stories.tsx +0 -212
  319. package/src/components/Text/Text.tsx +0 -181
  320. package/src/components/Text/index.ts +0 -13
  321. package/src/components/Toast/Toast.module.css +0 -91
  322. package/src/components/Toast/Toast.stories.tsx +0 -66
  323. package/src/components/Toast/Toast.tsx +0 -182
  324. package/src/components/Toast/index.ts +0 -8
  325. package/src/components/Toggle/Toggle.module.css +0 -87
  326. package/src/components/Toggle/Toggle.stories.tsx +0 -85
  327. package/src/components/Toggle/Toggle.tsx +0 -52
  328. package/src/components/Toggle/index.ts +0 -2
  329. package/src/components/ToggleButton/ToggleButton.module.css +0 -172
  330. package/src/components/ToggleButton/ToggleButton.stories.tsx +0 -299
  331. package/src/components/ToggleButton/ToggleButton.tsx +0 -118
  332. package/src/components/ToggleButton/index.ts +0 -2
  333. package/src/components/ToggleButtonGroup/ToggleButtonGroup.module.css +0 -163
  334. package/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx +0 -341
  335. package/src/components/ToggleButtonGroup/ToggleButtonGroup.tsx +0 -111
  336. package/src/components/ToggleButtonGroup/index.ts +0 -2
  337. package/src/components/Tooltip/Tooltip.module.css +0 -45
  338. package/src/components/Tooltip/Tooltip.stories.tsx +0 -46
  339. package/src/components/Tooltip/Tooltip.tsx +0 -224
  340. package/src/components/Tooltip/index.ts +0 -2
  341. package/src/css-modules.d.ts +0 -4
  342. package/src/docs/ColorUsage.mdx +0 -195
  343. package/src/docs/ElevationUsage.mdx +0 -95
  344. package/src/docs/Introduction.mdx +0 -97
  345. package/src/docs/OpticalSizing.mdx +0 -178
  346. package/src/docs/TypographyUsage.mdx +0 -121
  347. package/src/index.ts +0 -154
  348. package/src/stories/Colors.stories.tsx +0 -528
  349. package/src/stories/Dimensions.stories.tsx +0 -200
  350. package/src/stories/Effects.stories.tsx +0 -231
  351. package/src/stories/Icons.stories.tsx +0 -159
  352. package/src/stories/Typography.stories.tsx +0 -157
  353. package/src/types/icons.ts +0 -15
  354. package/src/types/index.ts +0 -1
  355. package/src/utils/cn.ts +0 -6
  356. package/src/utils/css-tokens.ts +0 -22
@@ -1,118 +0,0 @@
1
- import React, { forwardRef } from 'react';
2
- import { cn } from '@/utils/cn';
3
- import { Text } from '@/components/Text';
4
- import { LabelWrap } from '@/components/LabelWrap';
5
- import type { IconComponent } from '@/types/icons';
6
- import styles from './ToggleButton.module.css';
7
-
8
- export type ToggleButtonElevation = 'none' | 'flat' | 'elevated' | 'floating';
9
- export type ToggleButtonSize = 'md' | 'sm' | 'xs';
10
- export type ToggleButtonBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';
11
-
12
- export interface ToggleButtonProps {
13
- /**
14
- * Chrome level.
15
- * none — ghost (transparent, no border, no shadow)
16
- * flat — border only, transparent bg
17
- * elevated — bg-primary + shadow [default]
18
- * floating — bg-primary + FAB-strength shadow
19
- */
20
- elevation?: ToggleButtonElevation;
21
- /** Label text. */
22
- label?: string;
23
- /** Leading icon component. */
24
- icon?: IconComponent;
25
- /** Size: md (32px), sm (24px), xs (16px). Defaults to 'md'. */
26
- size?: ToggleButtonSize;
27
- /** Pill shape. */
28
- rounded?: boolean;
29
- /** Parent surface context. Adjusts hover tokens for toggle buttons on colored backgrounds. */
30
- background?: ToggleButtonBackground;
31
- /** Controlled pressed state. */
32
- pressed: boolean;
33
- /** Called when pressed state changes. */
34
- onPressedChange: (pressed: boolean) => void;
35
- inactive?: boolean;
36
- className?: string;
37
- id?: string;
38
- 'aria-label'?: string;
39
- }
40
-
41
- const ICON_SIZE_MAP: Record<ToggleButtonSize, number> = { md: 20, sm: 16, xs: 12 };
42
-
43
- const TEXT_STYLE_MAP: Record<ToggleButtonSize, string> = {
44
- md: 'text-body-medium-emphasis',
45
- sm: 'text-body-small-emphasis',
46
- xs: 'text-caption-emphasis',
47
- };
48
-
49
- export const ToggleButton = forwardRef<HTMLButtonElement, ToggleButtonProps>(
50
- (
51
- {
52
- elevation = 'elevated',
53
- label,
54
- icon: Icon,
55
- size = 'md',
56
- rounded = false,
57
- background,
58
- pressed,
59
- onPressedChange,
60
- inactive = false,
61
- className,
62
- id,
63
- 'aria-label': ariaLabel,
64
- },
65
- ref
66
- ) => {
67
- const hasIcon = !!Icon;
68
- const hasLabel = !!label;
69
- const isIconOnly = hasIcon && !hasLabel;
70
- const isLabelOnly = hasLabel && !hasIcon;
71
- const isIconAndLabel = hasIcon && hasLabel;
72
- const iconSize = ICON_SIZE_MAP[size];
73
- const textStyle = TEXT_STYLE_MAP[size];
74
-
75
- const elevKey = elevation.charAt(0).toUpperCase() + elevation.slice(1);
76
-
77
- const classes = cn(
78
- styles.toggleButton,
79
- styles[`elevation${elevKey}`],
80
- size !== 'md' && styles[`size${size.toUpperCase()}`],
81
- rounded && styles.rounded,
82
- inactive && styles.inactive,
83
- isIconOnly && styles.iconOnly,
84
- isLabelOnly && styles.labelOnly,
85
- isIconAndLabel && styles.iconAndLabel,
86
- background && background !== 'faint' && styles[
87
- background === 'always-dark' ? 'onAlwaysDark'
88
- : `on${background.charAt(0).toUpperCase() + background.slice(1)}`
89
- ],
90
- pressed && styles.pressed,
91
- className,
92
- );
93
-
94
- return (
95
- <button
96
- ref={ref}
97
- id={id}
98
- className={classes}
99
- onClick={inactive ? undefined : () => onPressedChange(!pressed)}
100
- type="button"
101
- disabled={inactive}
102
- aria-label={ariaLabel || label || 'toggle'}
103
- aria-pressed={pressed}
104
- >
105
- {Icon && <Icon size={iconSize} />}
106
- {label && (
107
- <LabelWrap>
108
- <Text variant={textStyle as never} as="span" color="inherit">
109
- {label}
110
- </Text>
111
- </LabelWrap>
112
- )}
113
- </button>
114
- );
115
- }
116
- );
117
-
118
- ToggleButton.displayName = 'ToggleButton';
@@ -1,2 +0,0 @@
1
- export { ToggleButton } from './ToggleButton';
2
- export type { ToggleButtonProps, ToggleButtonElevation, ToggleButtonSize, ToggleButtonBackground } from './ToggleButton';
@@ -1,163 +0,0 @@
1
- /* ==========================================================================
2
- ToggleButtonGroup — flush row of ToggleButton components
3
- ========================================================================== */
4
-
5
- .group {
6
- display: inline-flex;
7
- align-items: stretch;
8
- border-radius: var(--dimension-radius-050);
9
- position: relative;
10
- }
11
-
12
- /* Inset ring / highlight overlay — sits above button children so it isn't
13
- covered by their backgrounds. Outset shadow stays on the element itself. */
14
- .group::after {
15
- content: '';
16
- position: absolute;
17
- inset: 0;
18
- border-radius: inherit;
19
- pointer-events: none;
20
- }
21
-
22
- /* ── Group-level elevation ──────────────────────────────────────────────── */
23
- /* Individual item chrome (shadow/border) is suppressed via .item below.
24
- The group container carries the elevation so it wraps the whole control. */
25
-
26
- /* Outset shadow on element; inset highlight on ::after (children would cover it otherwise) */
27
- .groupElevated { box-shadow: var(--effect-shadow-elevated-sm); }
28
- .groupElevated::after { box-shadow: var(--effect-highlight-elevated-sm); }
29
-
30
- /* Flat ring lives entirely on ::after — same reasoning as highlight */
31
- .groupFlat::after { box-shadow: inset 0 0 0 1px var(--color-border-tertiary); }
32
-
33
- .groupFloating { box-shadow: var(--effect-shadow-elevated-floating); }
34
- .groupFloating::after { box-shadow: var(--effect-highlight-elevated-floating); }
35
- /* groupNone = ghost — no shadow, no border */
36
-
37
- .groupRounded { border-radius: var(--dimension-radius-half); }
38
-
39
- /* ── Base item ─────────────────────────────────────────────────────────────── */
40
-
41
- .item {
42
- flex-shrink: 0;
43
- /* Suppress individual elevation so the group reads as one unit */
44
- box-shadow: none !important;
45
- /* Suppress noElevation individual border — divider handles separation */
46
- border: none !important;
47
- /* Suppress scale-on-press: transform would detach the divider from the
48
- adjacent button, creating a visible gap. Pressed state is still
49
- communicated via the ::after overlay colour. */
50
- }
51
- .item:active {
52
- transform: none !important;
53
- }
54
-
55
- /* ── Divider ────────────────────────────────────────────────────────────────
56
- * Rendered as a separate <div> between items so it is never part of any
57
- * button's stacking context — disabled (opacity: 0.5) or other state changes
58
- * on adjacent buttons cannot bleed through to the divider.
59
- * ─────────────────────────────────────────────────────────────────────────── */
60
-
61
- /* Full-height divider (elevated / flat / floating).
62
- * Rendered as a separate element (independent of adjacent button opacity),
63
- * then nudged ±0.5px so it overlaps each neighbour and paints on top via
64
- * z-index — this lets the alpha token (rgb(0 0 0 / 0.1)) composite over
65
- * whatever fill the buttons carry (white, blue pressed state, etc.). */
66
- .divider {
67
- width: 1px;
68
- flex-shrink: 0;
69
- background-color: var(--color-border-tertiary);
70
- position: relative;
71
- z-index: 1;
72
- margin: 0 -0.5px;
73
- pointer-events: none;
74
- }
75
-
76
- /* Ghost (elevation=none): short centred divider at icon height */
77
- .dividerGhost { height: 20px; align-self: center; } /* md default */
78
- .dividerGhostXS { height: 12px; }
79
- .dividerGhostSM { height: 16px; }
80
-
81
- /* Ghost hover-fade: hide the divider on either side of a hovered ghost button */
82
- .item:hover + .dividerGhost,
83
- .dividerGhost:has(+ .item:hover) { opacity: 0; }
84
-
85
- /* Ghost pressed-state: hide the divider on either side of a selected button */
86
- .itemPressed + .dividerGhost,
87
- .dividerGhost:has(+ .itemPressed) { opacity: 0; }
88
-
89
-
90
- /* ── Ghost interaction states: rounded chips ──────────────────────────────────
91
- * Ghost items have no connecting chrome — hover/press overlay and selected
92
- * state always appear as independent rounded chips (4px on all corners).
93
- * Rounded groups: outer corners of first/last become pill; inner stay 4px.
94
- *
95
- * Uses explicit longhands throughout to avoid shorthand/longhand cascade
96
- * ordering ambiguity with the !important rules in .first / .last / .middle.
97
- * ─────────────────────────────────────────────────────────────────────────── */
98
-
99
- /* ::after hover/press overlay — all positions: 4px all corners.
100
- Uses .group as ancestor (2-class specificity) to reliably beat
101
- .first / .last / .middle (1-class) regardless of load order. */
102
- .group .itemShort::after {
103
- border-top-left-radius: var(--dimension-radius-050) !important;
104
- border-top-right-radius: var(--dimension-radius-050) !important;
105
- border-bottom-right-radius: var(--dimension-radius-050) !important;
106
- border-bottom-left-radius: var(--dimension-radius-050) !important;
107
- }
108
-
109
- /* Selected chip — all positions: 4px all corners */
110
- .group .itemPressed {
111
- border-top-left-radius: var(--dimension-radius-050) !important;
112
- border-top-right-radius: var(--dimension-radius-050) !important;
113
- border-bottom-right-radius: var(--dimension-radius-050) !important;
114
- border-bottom-left-radius: var(--dimension-radius-050) !important;
115
- }
116
-
117
- /* ── Border radius: flatten only the inner-facing corners ──────────────────── */
118
- /* Outer corners keep the button's own radius — works for default + rounded */
119
-
120
- .first {
121
- border-top-right-radius: 0 !important;
122
- border-bottom-right-radius: 0 !important;
123
- }
124
-
125
- .last {
126
- border-top-left-radius: 0 !important;
127
- border-bottom-left-radius: 0 !important;
128
- }
129
-
130
- .middle {
131
- border-radius: 0 !important;
132
- }
133
-
134
- /* Rounded group: first — left corners become pill (3-class specificity) */
135
- .groupRounded .first.itemShort::after,
136
- .groupRounded .first.itemPressed {
137
- border-top-left-radius: var(--dimension-radius-half) !important;
138
- border-bottom-left-radius: var(--dimension-radius-half) !important;
139
- }
140
-
141
- /* Rounded group: last — right corners become pill (3-class specificity) */
142
- .groupRounded .last.itemShort::after,
143
- .groupRounded .last.itemPressed {
144
- border-top-right-radius: var(--dimension-radius-half) !important;
145
- border-bottom-right-radius: var(--dimension-radius-half) !important;
146
- }
147
-
148
- /* ── Rounded: inner-edge padding correction ────────────────────────────────── */
149
- /*
150
- * Rounded buttons add `space-050` extra padding on each side.
151
- * In a group the inner-facing edge should use base (non-pill) padding instead.
152
- * XS rounded has no extra padding so needs no correction.
153
- */
154
-
155
- /* MD — base padding: space-100 */
156
- .roundedFirstMD { padding-right: var(--dimension-space-100) !important; }
157
- .roundedLastMD { padding-left: var(--dimension-space-100) !important; }
158
- .roundedMidMD { padding-left: var(--dimension-space-100) !important; padding-right: var(--dimension-space-100) !important; }
159
-
160
- /* SM — base padding: space-075 */
161
- .roundedFirstSM { padding-right: var(--dimension-space-075) !important; }
162
- .roundedLastSM { padding-left: var(--dimension-space-075) !important; }
163
- .roundedMidSM { padding-left: var(--dimension-space-075) !important; padding-right: var(--dimension-space-075) !important; }
@@ -1,341 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react-vite';
2
- import React, { useState } from 'react';
3
- import { ToggleButtonGroup } from './ToggleButtonGroup';
4
- import { ToggleButton } from '@/components/ToggleButton';
5
- import type { ToggleButtonElevation } from '@/components/ToggleButton';
6
- import type { IconComponent } from '@/types/icons';
7
-
8
- const PlaceholderIcon: IconComponent = ({ size = 20 }) => (
9
- <svg width={size} height={size} viewBox="0 0 20 20" fill="currentColor">
10
- <circle cx="10" cy="10" r="6" />
11
- </svg>
12
- );
13
-
14
- interface PlaygroundArgs {
15
- elevation: ToggleButtonElevation;
16
- size: 'xs' | 'sm' | 'md';
17
- rounded: boolean;
18
- showIcon: boolean;
19
- }
20
-
21
- const meta: Meta<typeof ToggleButtonGroup> = {
22
- title: 'Primitives (Reviewed)/ToggleButtonGroup',
23
- component: ToggleButtonGroup,
24
- args: {
25
- elevation: 'elevated',
26
- size: 'md',
27
- rounded: false,
28
- showIcon: false,
29
- } as PlaygroundArgs,
30
- argTypes: {
31
- elevation: { control: 'select', options: ['elevated', 'flat', 'none', 'floating'] },
32
- size: { control: 'select', options: ['xs', 'sm', 'md'] },
33
- rounded: { control: 'boolean' },
34
- showIcon: { control: 'boolean' },
35
- } as Record<string, unknown>,
36
- };
37
-
38
- export default meta;
39
- type Story = StoryObj<typeof ToggleButtonGroup>;
40
-
41
- // ─── Matrix ───────────────────────────────────────────────────────────────────
42
-
43
- const col: React.CSSProperties = { display: 'flex', flexDirection: 'column', gap: 16, alignItems: 'flex-start' };
44
- const row: React.CSSProperties = { display: 'flex', gap: 16, alignItems: 'center' };
45
- const labelStyle: React.CSSProperties = { fontSize: 10, fontFamily: 'monospace', color: '#888', minWidth: 120, flexShrink: 0 };
46
- const section = (text: string) => (
47
- <div style={{ fontSize: 11, fontWeight: 600, letterSpacing: '0.05em', textTransform: 'uppercase', color: '#555', marginTop: 8 }}>
48
- {text}
49
- </div>
50
- );
51
- const divider = <hr style={{ border: 'none', borderTop: '1px solid #e0e0e0', margin: '8px 0 16px' }} />;
52
-
53
- // ─── Playground ──────────────────────────────────────────────────────────────
54
-
55
- export const Playground: Story = {
56
- render: (args) => {
57
- const a = args as unknown as PlaygroundArgs;
58
- const opts = ['First', 'Second', 'Third'] as const;
59
- const [selected, setSelected] = useState<string>('Second');
60
- return (
61
- <ToggleButtonGroup>
62
- {opts.map(opt => (
63
- <ToggleButton
64
- key={opt}
65
- elevation={a.elevation}
66
- size={a.size}
67
- rounded={a.rounded}
68
- icon={a.showIcon ? PlaceholderIcon : undefined}
69
- label={opt}
70
- pressed={selected === opt}
71
- onPressedChange={() => setSelected(opt)}
72
- />
73
- ))}
74
- </ToggleButtonGroup>
75
- );
76
- },
77
- };
78
-
79
- // ─── Matrix ───────────────────────────────────────────────────────────────────
80
-
81
- export const Matrix: Story = {
82
- parameters: { layout: 'padded' },
83
- render: () => {
84
- const [view, setView] = useState<'grid' | 'list' | 'table'>('grid');
85
- const [period, setPeriod] = useState<'day' | 'week' | 'month'>('week');
86
- const [multi, setMulti] = useState<Set<string>>(new Set(['b']));
87
- const toggleMulti = (key: string) => setMulti(prev => {
88
- const next = new Set(prev);
89
- next.has(key) ? next.delete(key) : next.add(key);
90
- return next;
91
- });
92
-
93
- return (
94
- <div style={{ ...col, fontFamily: 'sans-serif', gap: 0 }}>
95
-
96
- {section('Elevation — full-height vs short divider')}
97
- {divider}
98
- <div style={col}>
99
- <div style={row}>
100
- <span style={labelStyle}>elevated ↓ full</span>
101
- <ToggleButtonGroup>
102
- <ToggleButton elevation="elevated" label="Day" pressed={period === 'day'} onPressedChange={() => setPeriod('day')} />
103
- <ToggleButton elevation="elevated" label="Week" pressed={period === 'week'} onPressedChange={() => setPeriod('week')} />
104
- <ToggleButton elevation="elevated" label="Month" pressed={period === 'month'} onPressedChange={() => setPeriod('month')} />
105
- </ToggleButtonGroup>
106
- </div>
107
- <div style={row}>
108
- <span style={labelStyle}>flat ↓ full</span>
109
- <ToggleButtonGroup>
110
- <ToggleButton elevation="flat" label="Day" pressed={period === 'day'} onPressedChange={() => setPeriod('day')} />
111
- <ToggleButton elevation="flat" label="Week" pressed={period === 'week'} onPressedChange={() => setPeriod('week')} />
112
- <ToggleButton elevation="flat" label="Month" pressed={period === 'month'} onPressedChange={() => setPeriod('month')} />
113
- </ToggleButtonGroup>
114
- </div>
115
- <div style={row}>
116
- <span style={labelStyle}>none ↓ short</span>
117
- <ToggleButtonGroup>
118
- <ToggleButton elevation="none" label="Day" pressed={period === 'day'} onPressedChange={() => setPeriod('day')} />
119
- <ToggleButton elevation="none" label="Week" pressed={period === 'week'} onPressedChange={() => setPeriod('week')} />
120
- <ToggleButton elevation="none" label="Month" pressed={period === 'month'} onPressedChange={() => setPeriod('month')} />
121
- </ToggleButtonGroup>
122
- </div>
123
- </div>
124
-
125
- {section('Sizes')}
126
- {divider}
127
- <div style={col}>
128
- {(['md', 'sm', 'xs'] as const).map(size => (
129
- <div key={size} style={row}>
130
- <span style={labelStyle}>{size}</span>
131
- <ToggleButtonGroup>
132
- <ToggleButton elevation="elevated" size={size} label="Day" pressed={false} onPressedChange={() => {}} />
133
- <ToggleButton elevation="elevated" size={size} label="Week" pressed={true} onPressedChange={() => {}} />
134
- <ToggleButton elevation="elevated" size={size} label="Month" pressed={false} onPressedChange={() => {}} />
135
- </ToggleButtonGroup>
136
- </div>
137
- ))}
138
- </div>
139
-
140
- {section('Rounded — outer pill padding, inner base padding')}
141
- {divider}
142
- <div style={col}>
143
- <div style={row}>
144
- <span style={labelStyle}>elevated label</span>
145
- <ToggleButtonGroup>
146
- <ToggleButton elevation="elevated" label="Day" rounded pressed={period === 'day'} onPressedChange={() => setPeriod('day')} />
147
- <ToggleButton elevation="elevated" label="Week" rounded pressed={period === 'week'} onPressedChange={() => setPeriod('week')} />
148
- <ToggleButton elevation="elevated" label="Month" rounded pressed={period === 'month'} onPressedChange={() => setPeriod('month')} />
149
- </ToggleButtonGroup>
150
- </div>
151
- <div style={row}>
152
- <span style={labelStyle}>none label</span>
153
- <ToggleButtonGroup>
154
- <ToggleButton elevation="none" label="Day" rounded pressed={period === 'day'} onPressedChange={() => setPeriod('day')} />
155
- <ToggleButton elevation="none" label="Week" rounded pressed={period === 'week'} onPressedChange={() => setPeriod('week')} />
156
- <ToggleButton elevation="none" label="Month" rounded pressed={period === 'month'} onPressedChange={() => setPeriod('month')} />
157
- </ToggleButtonGroup>
158
- </div>
159
- <div style={row}>
160
- <span style={labelStyle}>icon only</span>
161
- <ToggleButtonGroup>
162
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} rounded aria-label="Grid" pressed={view === 'grid'} onPressedChange={() => setView('grid')} />
163
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} rounded aria-label="List" pressed={view === 'list'} onPressedChange={() => setView('list')} />
164
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} rounded aria-label="Table" pressed={view === 'table'} onPressedChange={() => setView('table')} />
165
- </ToggleButtonGroup>
166
- </div>
167
- </div>
168
-
169
- {section('With Icons')}
170
- {divider}
171
- <div style={col}>
172
- <div style={row}>
173
- <span style={labelStyle}>icon + label</span>
174
- <ToggleButtonGroup>
175
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} label="Grid" pressed={view === 'grid'} onPressedChange={() => setView('grid')} />
176
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} label="List" pressed={view === 'list'} onPressedChange={() => setView('list')} />
177
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} label="Table" pressed={view === 'table'} onPressedChange={() => setView('table')} />
178
- </ToggleButtonGroup>
179
- </div>
180
- <div style={row}>
181
- <span style={labelStyle}>icon only</span>
182
- <ToggleButtonGroup>
183
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} aria-label="Grid" pressed={view === 'grid'} onPressedChange={() => setView('grid')} />
184
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} aria-label="List" pressed={view === 'list'} onPressedChange={() => setView('list')} />
185
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} aria-label="Table" pressed={view === 'table'} onPressedChange={() => setView('table')} />
186
- </ToggleButtonGroup>
187
- </div>
188
- <div style={row}>
189
- <span style={labelStyle}>icon only rounded</span>
190
- <ToggleButtonGroup>
191
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} rounded aria-label="Grid" pressed={view === 'grid'} onPressedChange={() => setView('grid')} />
192
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} rounded aria-label="List" pressed={view === 'list'} onPressedChange={() => setView('list')} />
193
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} rounded aria-label="Table" pressed={view === 'table'} onPressedChange={() => setView('table')} />
194
- </ToggleButtonGroup>
195
- </div>
196
- </div>
197
-
198
- {section('Multi-select')}
199
- {divider}
200
- <div style={col}>
201
- <div style={row}>
202
- <span style={labelStyle}>independent</span>
203
- <ToggleButtonGroup>
204
- {(['a', 'b', 'c'] as const).map(key => (
205
- <ToggleButton
206
- key={key}
207
- elevation="elevated"
208
- label={key.toUpperCase()}
209
- pressed={multi.has(key)}
210
- onPressedChange={() => toggleMulti(key)}
211
- />
212
- ))}
213
- </ToggleButtonGroup>
214
- </div>
215
- </div>
216
-
217
- {section('States')}
218
- {divider}
219
- <div style={col}>
220
- <div style={row}>
221
- <span style={labelStyle}>none pressed</span>
222
- <ToggleButtonGroup>
223
- <ToggleButton elevation="elevated" label="One" pressed={false} onPressedChange={() => {}} />
224
- <ToggleButton elevation="elevated" label="Two" pressed={false} onPressedChange={() => {}} />
225
- <ToggleButton elevation="elevated" label="Three" pressed={false} onPressedChange={() => {}} />
226
- </ToggleButtonGroup>
227
- </div>
228
- <div style={row}>
229
- <span style={labelStyle}>all pressed</span>
230
- <ToggleButtonGroup>
231
- <ToggleButton elevation="elevated" label="One" pressed={true} onPressedChange={() => {}} />
232
- <ToggleButton elevation="elevated" label="Two" pressed={true} onPressedChange={() => {}} />
233
- <ToggleButton elevation="elevated" label="Three" pressed={true} onPressedChange={() => {}} />
234
- </ToggleButtonGroup>
235
- </div>
236
- <div style={row}>
237
- <span style={labelStyle}>with inactive</span>
238
- <ToggleButtonGroup>
239
- <ToggleButton elevation="elevated" label="One" pressed={false} onPressedChange={() => {}} />
240
- <ToggleButton elevation="elevated" label="Two" pressed={true} onPressedChange={() => {}} inactive />
241
- <ToggleButton elevation="elevated" label="Three" pressed={false} onPressedChange={() => {}} />
242
- </ToggleButtonGroup>
243
- </div>
244
- <div style={row}>
245
- <span style={labelStyle}>two items</span>
246
- <ToggleButtonGroup>
247
- <ToggleButton elevation="elevated" label="Left" pressed={false} onPressedChange={() => {}} />
248
- <ToggleButton elevation="elevated" label="Right" pressed={true} onPressedChange={() => {}} />
249
- </ToggleButtonGroup>
250
- </div>
251
- </div>
252
-
253
- </div>
254
- );
255
- },
256
- };
257
-
258
- // ─── Individual stories ───────────────────────────────────────────────────────
259
-
260
- export const SingleSelect: Story = {
261
- render: () => {
262
- const [selected, setSelected] = useState<'day' | 'week' | 'month'>('week');
263
- return (
264
- <ToggleButtonGroup>
265
- {(['day', 'week', 'month'] as const).map(opt => (
266
- <ToggleButton
267
- key={opt}
268
- elevation="elevated"
269
- label={opt.charAt(0).toUpperCase() + opt.slice(1)}
270
- pressed={selected === opt}
271
- onPressedChange={() => setSelected(opt)}
272
- />
273
- ))}
274
- </ToggleButtonGroup>
275
- );
276
- },
277
- };
278
-
279
- export const MultiSelect: Story = {
280
- render: () => {
281
- const [active, setActive] = useState(new Set(['bold']));
282
- const toggle = (key: string) => setActive(prev => {
283
- const next = new Set(prev);
284
- next.has(key) ? next.delete(key) : next.add(key);
285
- return next;
286
- });
287
- return (
288
- <ToggleButtonGroup>
289
- {(['Bold', 'Italic', 'Underline'] as const).map(opt => (
290
- <ToggleButton
291
- key={opt}
292
- elevation="elevated"
293
- label={opt}
294
- pressed={active.has(opt.toLowerCase())}
295
- onPressedChange={() => toggle(opt.toLowerCase())}
296
- />
297
- ))}
298
- </ToggleButtonGroup>
299
- );
300
- },
301
- };
302
-
303
- export const IconOnly: Story = {
304
- render: () => {
305
- const [view, setView] = useState<'grid' | 'list' | 'table'>('grid');
306
- return (
307
- <ToggleButtonGroup>
308
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} aria-label="Grid" pressed={view === 'grid'} onPressedChange={() => setView('grid')} />
309
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} aria-label="List" pressed={view === 'list'} onPressedChange={() => setView('list')} />
310
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} aria-label="Table" pressed={view === 'table'} onPressedChange={() => setView('table')} />
311
- </ToggleButtonGroup>
312
- );
313
- },
314
- };
315
-
316
- export const Rounded: Story = {
317
- render: () => {
318
- const [selected, setSelected] = useState<'day' | 'week' | 'month'>('week');
319
- return (
320
- <div style={{ display: 'flex', flexDirection: 'column', gap: 12, alignItems: 'flex-start' }}>
321
- <ToggleButtonGroup>
322
- {(['day', 'week', 'month'] as const).map(opt => (
323
- <ToggleButton
324
- key={opt}
325
- elevation="elevated"
326
- label={opt.charAt(0).toUpperCase() + opt.slice(1)}
327
- rounded
328
- pressed={selected === opt}
329
- onPressedChange={() => setSelected(opt)}
330
- />
331
- ))}
332
- </ToggleButtonGroup>
333
- <ToggleButtonGroup>
334
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} rounded aria-label="Grid" pressed={false} onPressedChange={() => {}} />
335
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} rounded aria-label="List" pressed={true} onPressedChange={() => {}} />
336
- <ToggleButton elevation="elevated" icon={PlaceholderIcon} rounded aria-label="Table" pressed={false} onPressedChange={() => {}} />
337
- </ToggleButtonGroup>
338
- </div>
339
- );
340
- },
341
- };