aural-ui 2.0.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 (308) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +456 -0
  3. package/dist/components/aspect-ratio/AspectRatio.stories.tsx +1327 -0
  4. package/dist/components/aspect-ratio/index.tsx +10 -0
  5. package/dist/components/aspect-ratio/meta.ts +8 -0
  6. package/dist/components/avatar/Avatar.stories.tsx +645 -0
  7. package/dist/components/avatar/index.tsx +50 -0
  8. package/dist/components/avatar/meta.ts +8 -0
  9. package/dist/components/badge/Badge.stories.tsx +169 -0
  10. package/dist/components/badge/index.tsx +28 -0
  11. package/dist/components/badge/meta.ts +6 -0
  12. package/dist/components/banner/Banner.stories.tsx +475 -0
  13. package/dist/components/banner/index.tsx +256 -0
  14. package/dist/components/banner/meta.ts +36 -0
  15. package/dist/components/button/Button.stories.tsx +74 -0
  16. package/dist/components/button/index.tsx +158 -0
  17. package/dist/components/button/meta.ts +33 -0
  18. package/dist/components/card/Card.stories.tsx +377 -0
  19. package/dist/components/card/index.tsx +85 -0
  20. package/dist/components/card/meta.ts +14 -0
  21. package/dist/components/char-count/CharCount.stories.tsx +334 -0
  22. package/dist/components/char-count/index.tsx +51 -0
  23. package/dist/components/char-count/meta.ts +13 -0
  24. package/dist/components/checkbox/Checkbox.stories.tsx +209 -0
  25. package/dist/components/checkbox/index.tsx +34 -0
  26. package/dist/components/checkbox/meta.ts +19 -0
  27. package/dist/components/chip/Chip.stories.tsx +207 -0
  28. package/dist/components/chip/index.tsx +92 -0
  29. package/dist/components/chip/meta.ts +17 -0
  30. package/dist/components/circular-loader/CircularLoader.stories.tsx +741 -0
  31. package/dist/components/circular-loader/index.tsx +138 -0
  32. package/dist/components/circular-loader/meta.ts +11 -0
  33. package/dist/components/collapsible/Collapsible.stories.tsx +319 -0
  34. package/dist/components/collapsible/index.tsx +158 -0
  35. package/dist/components/collapsible/meta.ts +22 -0
  36. package/dist/components/command/Command.stories.tsx +996 -0
  37. package/dist/components/command/index.tsx +324 -0
  38. package/dist/components/command/meta.ts +18 -0
  39. package/dist/components/dialog/Dialog.stories.tsx +963 -0
  40. package/dist/components/dialog/index.tsx +250 -0
  41. package/dist/components/dialog/meta.ts +28 -0
  42. package/dist/components/divider/Divider.stories.tsx +633 -0
  43. package/dist/components/divider/index.tsx +181 -0
  44. package/dist/components/divider/meta.ts +12 -0
  45. package/dist/components/dot-loader/DotLoader.stories.tsx +352 -0
  46. package/dist/components/dot-loader/index.tsx +78 -0
  47. package/dist/components/dot-loader/meta.ts +14 -0
  48. package/dist/components/dropdown/Dropdown.stories.tsx +1210 -0
  49. package/dist/components/dropdown/index.tsx +479 -0
  50. package/dist/components/dropdown/meta.ts +21 -0
  51. package/dist/components/form/Form.stories.tsx +320 -0
  52. package/dist/components/form/index.tsx +183 -0
  53. package/dist/components/form/meta.ts +11 -0
  54. package/dist/components/helper-text/HelperText.stories.tsx +254 -0
  55. package/dist/components/helper-text/index.tsx +102 -0
  56. package/dist/components/helper-text/meta.ts +18 -0
  57. package/dist/components/hover-card/HoverCard.stories.tsx +1328 -0
  58. package/dist/components/hover-card/index.tsx +42 -0
  59. package/dist/components/hover-card/meta.ts +12 -0
  60. package/dist/components/icon-button/IconButton.stories.tsx +252 -0
  61. package/dist/components/icon-button/index.tsx +130 -0
  62. package/dist/components/icon-button/meta.ts +20 -0
  63. package/dist/components/if-else/if-else.stories.tsx +100 -0
  64. package/dist/components/if-else/index.tsx +56 -0
  65. package/dist/components/if-else/meta.ts +6 -0
  66. package/dist/components/index.ts +70 -0
  67. package/dist/components/input/Input.stories.tsx +431 -0
  68. package/dist/components/input/index.tsx +487 -0
  69. package/dist/components/input/meta.ts +28 -0
  70. package/dist/components/label/Label.stories.tsx +200 -0
  71. package/dist/components/label/index.tsx +43 -0
  72. package/dist/components/label/meta.ts +14 -0
  73. package/dist/components/list/List.stories.tsx +963 -0
  74. package/dist/components/list/index.tsx +567 -0
  75. package/dist/components/list/meta.ts +24 -0
  76. package/dist/components/marquee/Marquee.stories.tsx +819 -0
  77. package/dist/components/marquee/index.tsx +107 -0
  78. package/dist/components/marquee/meta.ts +6 -0
  79. package/dist/components/overlay/Overlay.stories.tsx +954 -0
  80. package/dist/components/overlay/index.tsx +58 -0
  81. package/dist/components/overlay/meta.ts +10 -0
  82. package/dist/components/pagination/Pagination.stories.tsx +354 -0
  83. package/dist/components/pagination/index.tsx +455 -0
  84. package/dist/components/pagination/meta.ts +29 -0
  85. package/dist/components/popover/Popover.stories.tsx +1037 -0
  86. package/dist/components/popover/index.tsx +67 -0
  87. package/dist/components/popover/meta.ts +12 -0
  88. package/dist/components/radio/Radio.stories.tsx +146 -0
  89. package/dist/components/radio/index.tsx +41 -0
  90. package/dist/components/radio/meta.ts +19 -0
  91. package/dist/components/resizable/Resizable.stories.tsx +866 -0
  92. package/dist/components/resizable/index.tsx +55 -0
  93. package/dist/components/resizable/meta.ts +12 -0
  94. package/dist/components/scroll-area/ScrollArea.stories.tsx +1104 -0
  95. package/dist/components/scroll-area/index.tsx +55 -0
  96. package/dist/components/scroll-area/meta.ts +8 -0
  97. package/dist/components/search/Search.stories.tsx +678 -0
  98. package/dist/components/search/index.tsx +141 -0
  99. package/dist/components/search/meta.ts +6 -0
  100. package/dist/components/select/Select.stories.tsx +962 -0
  101. package/dist/components/select/index.tsx +512 -0
  102. package/dist/components/select/meta.ts +40 -0
  103. package/dist/components/sheet/Sheet.stories.tsx +1060 -0
  104. package/dist/components/sheet/index.tsx +440 -0
  105. package/dist/components/sheet/meta.ts +38 -0
  106. package/dist/components/skelton/Skelton.stories.tsx +859 -0
  107. package/dist/components/skelton/index.tsx +17 -0
  108. package/dist/components/skelton/meta.ts +6 -0
  109. package/dist/components/slider/Slider.stories.tsx +876 -0
  110. package/dist/components/slider/index.tsx +156 -0
  111. package/dist/components/slider/meta.ts +29 -0
  112. package/dist/components/stepper/Stepper.stories.tsx +639 -0
  113. package/dist/components/stepper/index.tsx +650 -0
  114. package/dist/components/stepper/meta.ts +19 -0
  115. package/dist/components/switch/Switch.stories.tsx +85 -0
  116. package/dist/components/switch/index.tsx +37 -0
  117. package/dist/components/switch/meta.ts +24 -0
  118. package/dist/components/switch-case/SwitchCase.stories.tsx +209 -0
  119. package/dist/components/switch-case/index.tsx +89 -0
  120. package/dist/components/switch-case/meta.ts +6 -0
  121. package/dist/components/table/Table.stories.tsx +1095 -0
  122. package/dist/components/table/index.tsx +113 -0
  123. package/dist/components/table/meta.ts +20 -0
  124. package/dist/components/tabs/Tabs.stories.tsx +1379 -0
  125. package/dist/components/tabs/index.tsx +186 -0
  126. package/dist/components/tabs/meta.ts +25 -0
  127. package/dist/components/tag/Tag.stories.tsx +625 -0
  128. package/dist/components/tag/index.tsx +320 -0
  129. package/dist/components/tag/meta.ts +52 -0
  130. package/dist/components/textarea/TextArea.stories.tsx +723 -0
  131. package/dist/components/textarea/index.tsx +480 -0
  132. package/dist/components/textarea/meta.ts +23 -0
  133. package/dist/components/toast/Toast.stories.tsx +1427 -0
  134. package/dist/components/toast/index.tsx +26 -0
  135. package/dist/components/toast/meta.ts +19 -0
  136. package/dist/components/toggle/Toggle.stories.tsx +1093 -0
  137. package/dist/components/toggle/index.tsx +44 -0
  138. package/dist/components/toggle/meta.ts +19 -0
  139. package/dist/components/tooltip/Tooltip.stories.tsx +1548 -0
  140. package/dist/components/tooltip/index.tsx +304 -0
  141. package/dist/components/tooltip/meta.ts +21 -0
  142. package/dist/components/typography/Typography.stories.tsx +197 -0
  143. package/dist/components/typography/index.tsx +184 -0
  144. package/dist/components/typography/meta.ts +38 -0
  145. package/dist/fonts/LabGrotesque-Regular.ttf +0 -0
  146. package/dist/fonts/LabGrotesqueTRIAL-Bold.otf +0 -0
  147. package/dist/fonts/LabGrotesqueTRIAL-Light.otf +0 -0
  148. package/dist/fonts/LabGrotesqueTRIAL-Medium.otf +0 -0
  149. package/dist/fonts/LabGrotesqueTRIAL-Regular.otf +0 -0
  150. package/dist/fonts/PPSupplySans-Regular (1).otf +0 -0
  151. package/dist/fonts/PPSupplySans-Regular.otf +0 -0
  152. package/dist/fonts/PPSupplySans-Ultralight.otf +0 -0
  153. package/dist/hooks/index.ts +3 -0
  154. package/dist/hooks/use-previous/UsePrevious.stories.tsx +997 -0
  155. package/dist/hooks/use-previous/index.ts +15 -0
  156. package/dist/hooks/use-previous/meta.ts +6 -0
  157. package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +983 -0
  158. package/dist/hooks/use-standalone-pagination/index.ts +146 -0
  159. package/dist/hooks/use-standalone-pagination/meta.ts +6 -0
  160. package/dist/icons/Icons.stories.tsx +29 -0
  161. package/dist/icons/alert-icon/AlertIcon.stories.tsx +991 -0
  162. package/dist/icons/alert-icon/index.tsx +48 -0
  163. package/dist/icons/alert-icon/meta.ts +8 -0
  164. package/dist/icons/all-icons.tsx +738 -0
  165. package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +1031 -0
  166. package/dist/icons/angle-down-icon/index.tsx +25 -0
  167. package/dist/icons/angle-down-icon/meta.ts +8 -0
  168. package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +1080 -0
  169. package/dist/icons/arrow-box-left-icon/index.tsx +24 -0
  170. package/dist/icons/arrow-box-left-icon/meta.ts +8 -0
  171. package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +1151 -0
  172. package/dist/icons/arrow-right-icon/index.tsx +26 -0
  173. package/dist/icons/arrow-right-icon/meta.ts +8 -0
  174. package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +1273 -0
  175. package/dist/icons/arrow-right-up-icon/index.tsx +24 -0
  176. package/dist/icons/arrow-right-up-icon/meta.ts +8 -0
  177. package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +670 -0
  178. package/dist/icons/art-board-icon/index.tsx +24 -0
  179. package/dist/icons/art-board-icon/meta.ts +7 -0
  180. package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +1244 -0
  181. package/dist/icons/audio-bar-icon/index.tsx +19 -0
  182. package/dist/icons/audio-bar-icon/meta.ts +8 -0
  183. package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +1239 -0
  184. package/dist/icons/bubble-check-icon/index.tsx +24 -0
  185. package/dist/icons/bubble-check-icon/meta.ts +8 -0
  186. package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +1228 -0
  187. package/dist/icons/bubble-crossed-icon/index.tsx +24 -0
  188. package/dist/icons/bubble-crossed-icon/meta.ts +8 -0
  189. package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +912 -0
  190. package/dist/icons/bubble-sparkle-icon/index.tsx +26 -0
  191. package/dist/icons/bubble-sparkle-icon/meta.ts +8 -0
  192. package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +1021 -0
  193. package/dist/icons/chevron-double-left-icon/index.tsx +34 -0
  194. package/dist/icons/chevron-double-left-icon/meta.ts +8 -0
  195. package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +1021 -0
  196. package/dist/icons/chevron-double-right-icon/index.tsx +34 -0
  197. package/dist/icons/chevron-double-right-icon/meta.ts +8 -0
  198. package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +1001 -0
  199. package/dist/icons/chevron-down-icon/index.tsx +27 -0
  200. package/dist/icons/chevron-down-icon/meta.ts +8 -0
  201. package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +1029 -0
  202. package/dist/icons/chevron-left-icon/index.tsx +27 -0
  203. package/dist/icons/chevron-left-icon/meta.ts +8 -0
  204. package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +1021 -0
  205. package/dist/icons/chevron-right-icon/index.tsx +27 -0
  206. package/dist/icons/chevron-right-icon/meta.ts +8 -0
  207. package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +1036 -0
  208. package/dist/icons/chevron-up-icon/index.tsx +27 -0
  209. package/dist/icons/chevron-up-icon/meta.ts +8 -0
  210. package/dist/icons/command-icon/CommandIcon.stories.tsx +1098 -0
  211. package/dist/icons/command-icon/index.tsx +24 -0
  212. package/dist/icons/command-icon/meta.ts +8 -0
  213. package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +1061 -0
  214. package/dist/icons/cross-circle-icon/index.tsx +23 -0
  215. package/dist/icons/cross-circle-icon/meta.ts +8 -0
  216. package/dist/icons/cross-icon/CrossIcon.stories.tsx +1027 -0
  217. package/dist/icons/cross-icon/index.tsx +24 -0
  218. package/dist/icons/cross-icon/meta.ts +8 -0
  219. package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +1092 -0
  220. package/dist/icons/edit-big-icon/index.tsx +22 -0
  221. package/dist/icons/edit-big-icon/meta.ts +8 -0
  222. package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +1090 -0
  223. package/dist/icons/eye-close-icon/index.tsx +26 -0
  224. package/dist/icons/eye-close-icon/meta.ts +8 -0
  225. package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +1098 -0
  226. package/dist/icons/eye-open-icon/index.tsx +24 -0
  227. package/dist/icons/eye-open-icon/meta.ts +8 -0
  228. package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +1071 -0
  229. package/dist/icons/feature-shine-icon/index.tsx +29 -0
  230. package/dist/icons/feature-shine-icon/meta.ts +8 -0
  231. package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +1115 -0
  232. package/dist/icons/file-chart-icon/index.tsx +24 -0
  233. package/dist/icons/file-chart-icon/meta.ts +8 -0
  234. package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +668 -0
  235. package/dist/icons/file-text-icon/index.tsx +24 -0
  236. package/dist/icons/file-text-icon/meta.ts +8 -0
  237. package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +1239 -0
  238. package/dist/icons/grip-vertical-icon/index.tsx +28 -0
  239. package/dist/icons/grip-vertical-icon/meta.ts +8 -0
  240. package/dist/icons/image-icon/ImageIcon.stories.tsx +1181 -0
  241. package/dist/icons/image-icon/index.tsx +24 -0
  242. package/dist/icons/image-icon/meta.ts +8 -0
  243. package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +1248 -0
  244. package/dist/icons/import-folder-icon/index.tsx +22 -0
  245. package/dist/icons/import-folder-icon/meta.ts +8 -0
  246. package/dist/icons/index.ts +46 -0
  247. package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +1272 -0
  248. package/dist/icons/light-bulb-simple-icon/index.tsx +24 -0
  249. package/dist/icons/light-bulb-simple-icon/meta.ts +8 -0
  250. package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +1245 -0
  251. package/dist/icons/magic-book-icon/index.tsx +32 -0
  252. package/dist/icons/magic-book-icon/meta.ts +8 -0
  253. package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +1251 -0
  254. package/dist/icons/maintenance-icon/index.tsx +23 -0
  255. package/dist/icons/maintenance-icon/meta.ts +8 -0
  256. package/dist/icons/message-icon/MessageIcon.stories.tsx +595 -0
  257. package/dist/icons/message-icon/index.tsx +30 -0
  258. package/dist/icons/message-icon/meta.ts +8 -0
  259. package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +1245 -0
  260. package/dist/icons/move-horizontal-icon/index.tsx +23 -0
  261. package/dist/icons/move-horizontal-icon/meta.ts +8 -0
  262. package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +1196 -0
  263. package/dist/icons/move-vertical-icon/index.tsx +23 -0
  264. package/dist/icons/move-vertical-icon/meta.ts +8 -0
  265. package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +1167 -0
  266. package/dist/icons/page-search-icon/index.tsx +21 -0
  267. package/dist/icons/page-search-icon/meta.ts +8 -0
  268. package/dist/icons/pencil-icon/PencilIcon.stories.tsx +1131 -0
  269. package/dist/icons/pencil-icon/index.tsx +21 -0
  270. package/dist/icons/pencil-icon/meta.ts +8 -0
  271. package/dist/icons/plus-icon/PlusIcon.stories.tsx +1151 -0
  272. package/dist/icons/plus-icon/index.tsx +24 -0
  273. package/dist/icons/plus-icon/meta.ts +8 -0
  274. package/dist/icons/search-icon/SearchIcon.stories.tsx +1181 -0
  275. package/dist/icons/search-icon/index.tsx +24 -0
  276. package/dist/icons/search-icon/meta.ts +8 -0
  277. package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +1167 -0
  278. package/dist/icons/site-logo-icon/index.tsx +79 -0
  279. package/dist/icons/site-logo-icon/meta.ts +8 -0
  280. package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +637 -0
  281. package/dist/icons/spinner-gradient-icon/index.tsx +53 -0
  282. package/dist/icons/spinner-gradient-icon/meta.ts +8 -0
  283. package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +644 -0
  284. package/dist/icons/spinner-solid-icon/index.tsx +59 -0
  285. package/dist/icons/spinner-solid-icon/meta.ts +8 -0
  286. package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +736 -0
  287. package/dist/icons/spinner-solid-neutral-icon/index.tsx +53 -0
  288. package/dist/icons/spinner-solid-neutral-icon/meta.ts +8 -0
  289. package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +1204 -0
  290. package/dist/icons/tick-circle-icon/index.tsx +23 -0
  291. package/dist/icons/tick-circle-icon/meta.ts +8 -0
  292. package/dist/icons/tick-icon/TickIcon.stories.tsx +1340 -0
  293. package/dist/icons/tick-icon/index.tsx +24 -0
  294. package/dist/icons/tick-icon/meta.ts +8 -0
  295. package/dist/icons/trash-icon/TrashIcon.stories.tsx +996 -0
  296. package/dist/icons/trash-icon/index.tsx +24 -0
  297. package/dist/icons/trash-icon/meta.ts +8 -0
  298. package/dist/icons/upload-icon/UploadIcon.stories.tsx +947 -0
  299. package/dist/icons/upload-icon/index.tsx +24 -0
  300. package/dist/icons/upload-icon/meta.ts +8 -0
  301. package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +1045 -0
  302. package/dist/icons/vertical-menu-icon/index.tsx +27 -0
  303. package/dist/icons/vertical-menu-icon/meta.ts +8 -0
  304. package/dist/index.d.ts +6 -0
  305. package/dist/index.js +206 -0
  306. package/dist/lib/utils.ts +6 -0
  307. package/dist/styles/aural-theme.css +1008 -0
  308. package/package.json +142 -0
@@ -0,0 +1,1093 @@
1
+ import React from "react"
2
+ import {
3
+ AlertIcon,
4
+ EditBigIcon,
5
+ EyeCloseIcon,
6
+ EyeOpenIcon,
7
+ FileChartIcon,
8
+ PlusIcon,
9
+ SearchIcon,
10
+ TickCircleIcon,
11
+ TrashIcon,
12
+ } from "@icons/index"
13
+ import type { Meta, StoryObj } from "@storybook/react"
14
+
15
+ import { Toggle } from "."
16
+
17
+ const meta: Meta<typeof Toggle> = {
18
+ title: "Components/UI/Toggle",
19
+ component: Toggle,
20
+ parameters: {
21
+ layout: "centered",
22
+ backgrounds: {
23
+ default: "dark",
24
+ values: [
25
+ { name: "dark", value: "#0a0a0a" },
26
+ { name: "light", value: "#ffffff" },
27
+ ],
28
+ },
29
+ docs: {
30
+ description: {
31
+ component: `
32
+ # Toggle Component
33
+
34
+ A flexible toggle button component built on top of Radix UI's Toggle primitive, providing on/off state management with visual feedback.
35
+
36
+ ## Features
37
+
38
+ - **State Management**: Built-in pressed/unpressed state handling
39
+ - **Keyboard Accessible**: Full keyboard navigation support
40
+ - **Multiple Variants**: Default and outline styles
41
+ - **Size Options**: Small, default, and large sizes
42
+ - **Icon Support**: Automatic icon sizing and styling
43
+ - **Disabled State**: Proper disabled state handling
44
+ - **Focus Management**: Clear focus indicators
45
+ - **ARIA Support**: Proper accessibility attributes
46
+
47
+ ## Variants
48
+
49
+ ### Default
50
+ - **default**: Transparent background with accent highlighting
51
+ - **outline**: Border style with shadow and hover effects
52
+
53
+ ### Sizes
54
+ - **sm**: Small (32px height, compact padding)
55
+ - **default**: Standard (36px height, balanced padding)
56
+ - **lg**: Large (40px height, generous padding)
57
+
58
+ ## Usage Examples
59
+
60
+ ### Basic Toggle
61
+ \`\`\`tsx
62
+ <Toggle aria-label="Toggle bold">
63
+ Bold
64
+ </Toggle>
65
+ \`\`\`
66
+
67
+ ### With Icon
68
+ \`\`\`tsx
69
+ <Toggle aria-label="Toggle notifications">
70
+ <AlertIcon />
71
+ Notifications
72
+ </Toggle>
73
+ \`\`\`
74
+
75
+ ### Icon Only
76
+ \`\`\`tsx
77
+ <Toggle aria-label="Toggle visibility">
78
+ <EyeOpenIcon />
79
+ </Toggle>
80
+ \`\`\`
81
+
82
+ ### Controlled State
83
+ \`\`\`tsx
84
+ const [pressed, setPressed] = useState(false)
85
+
86
+ <Toggle
87
+ pressed={pressed}
88
+ onPressedChange={setPressed}
89
+ aria-label="Toggle feature"
90
+ >
91
+ Feature
92
+ </Toggle>
93
+ \`\`\`
94
+
95
+ ### Different Variants
96
+ \`\`\`tsx
97
+ <Toggle variant="outline" size="sm">
98
+ Small Outline
99
+ </Toggle>
100
+ \`\`\`
101
+
102
+ ## Accessibility
103
+
104
+ - **ARIA Label**: Always provide \`aria-label\` for screen readers
105
+ - **Keyboard Navigation**: Spacebar and Enter toggle state
106
+ - **Focus Indicators**: Clear visual focus ring
107
+ - **State Announcement**: Screen readers announce pressed state
108
+ - **Semantic HTML**: Uses proper button semantics
109
+
110
+ ## States
111
+
112
+ - **Default**: Unpressed/off state
113
+ - **Pressed**: Pressed/on state with accent styling
114
+ - **Hover**: Subtle background change on hover
115
+ - **Focus**: Clear focus ring for keyboard navigation
116
+ - **Disabled**: Reduced opacity and no interaction
117
+
118
+ ## Best Practices
119
+
120
+ - Always provide descriptive \`aria-label\` attributes
121
+ - Use consistent toggle patterns throughout your app
122
+ - Consider using icons to enhance visual clarity
123
+ - Test with keyboard navigation and screen readers
124
+ - Provide visual feedback for state changes
125
+ `,
126
+ },
127
+ },
128
+ },
129
+ tags: ["autodocs"],
130
+ argTypes: {
131
+ variant: {
132
+ control: "select",
133
+ options: ["default", "outline"],
134
+ description: "Visual style variant",
135
+ },
136
+ size: {
137
+ control: "select",
138
+ options: ["sm", "default", "lg"],
139
+ description: "Size of the toggle button",
140
+ },
141
+ pressed: {
142
+ control: "boolean",
143
+ description: "Controlled pressed state",
144
+ },
145
+ disabled: {
146
+ control: "boolean",
147
+ description: "Disabled state",
148
+ },
149
+ className: {
150
+ control: "text",
151
+ description: "Additional CSS classes",
152
+ },
153
+ },
154
+ }
155
+
156
+ export default meta
157
+ type Story = StoryObj<typeof Toggle>
158
+
159
+ // 1. Basic Toggle
160
+ export const Basic: Story = {
161
+ args: {
162
+ children: "Toggle me",
163
+ "aria-label": "Toggle basic example",
164
+ },
165
+ parameters: {
166
+ docs: {
167
+ description: {
168
+ story: "A simple toggle button with text content.",
169
+ },
170
+ },
171
+ },
172
+ }
173
+
174
+ // 2. Variants
175
+ export const Variants: Story = {
176
+ render: () => (
177
+ <div className="flex flex-col gap-8 p-8">
178
+ <h3 className="text-center text-lg font-medium text-white">
179
+ Toggle Variants
180
+ </h3>
181
+
182
+ <div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
183
+ {/* Default Variant */}
184
+ <div className="space-y-4">
185
+ <h4 className="text-sm font-medium text-white/70">Default Variant</h4>
186
+ <div className="flex flex-wrap gap-4">
187
+ <Toggle aria-label="Default unpressed">Default</Toggle>
188
+ <Toggle defaultPressed aria-label="Default pressed">
189
+ Pressed
190
+ </Toggle>
191
+ <Toggle disabled aria-label="Default disabled">
192
+ Disabled
193
+ </Toggle>
194
+ </div>
195
+ </div>
196
+
197
+ {/* Outline Variant */}
198
+ <div className="space-y-4">
199
+ <h4 className="text-sm font-medium text-white/70">Outline Variant</h4>
200
+ <div className="flex flex-wrap gap-4">
201
+ <Toggle variant="outline" aria-label="Outline unpressed">
202
+ Outline
203
+ </Toggle>
204
+ <Toggle
205
+ variant="outline"
206
+ defaultPressed
207
+ aria-label="Outline pressed"
208
+ >
209
+ Pressed
210
+ </Toggle>
211
+ <Toggle variant="outline" disabled aria-label="Outline disabled">
212
+ Disabled
213
+ </Toggle>
214
+ </div>
215
+ </div>
216
+
217
+ {/* Filled Variant */}
218
+ <div className="space-y-4">
219
+ <h4 className="text-sm font-medium text-white/70">Filled Variant</h4>
220
+ <div className="flex flex-wrap gap-4">
221
+ <Toggle variant="filled" aria-label="Filled unpressed">
222
+ Filled
223
+ </Toggle>
224
+ <Toggle variant="filled" defaultPressed aria-label="Filled pressed">
225
+ Pressed
226
+ </Toggle>
227
+ <Toggle variant="filled" disabled aria-label="Filled disabled">
228
+ Disabled
229
+ </Toggle>
230
+ </div>
231
+ </div>
232
+ </div>
233
+ </div>
234
+ ),
235
+ parameters: {
236
+ docs: {
237
+ description: {
238
+ story:
239
+ "Different visual variants showing default and outline styles in various states.",
240
+ },
241
+ },
242
+ },
243
+ }
244
+
245
+ // 3. Sizes
246
+ export const Sizes: Story = {
247
+ render: () => (
248
+ <div className="space-y-8 p-8">
249
+ <h3 className="text-center text-lg font-medium text-white">
250
+ Toggle Sizes
251
+ </h3>
252
+
253
+ <div className="space-y-6">
254
+ {/* Size Comparison */}
255
+ <div className="space-y-4">
256
+ <h4 className="text-center text-sm font-medium text-white/70">
257
+ Size Comparison
258
+ </h4>
259
+ <div className="flex items-center justify-center gap-4">
260
+ <div className="flex flex-col items-center gap-2">
261
+ <Toggle size="sm" aria-label="Small toggle">
262
+ Small
263
+ </Toggle>
264
+ <span className="text-xs text-white/60">Small (32px)</span>
265
+ </div>
266
+ <div className="flex flex-col items-center gap-2">
267
+ <Toggle size="default" aria-label="Default toggle">
268
+ Default
269
+ </Toggle>
270
+ <span className="text-xs text-white/60">Default (36px)</span>
271
+ </div>
272
+ <div className="flex flex-col items-center gap-2">
273
+ <Toggle size="lg" aria-label="Large toggle">
274
+ Large
275
+ </Toggle>
276
+ <span className="text-xs text-white/60">Large (40px)</span>
277
+ </div>
278
+ </div>
279
+ </div>
280
+
281
+ {/* Sizes with Icons */}
282
+ <div className="space-y-4">
283
+ <h4 className="text-center text-sm font-medium text-white/70">
284
+ With Icons
285
+ </h4>
286
+ <div className="flex items-center justify-center gap-4">
287
+ <Toggle size="sm" aria-label="Small with icon">
288
+ <AlertIcon />
289
+ Small
290
+ </Toggle>
291
+ <Toggle size="default" aria-label="Default with icon">
292
+ <SearchIcon />
293
+ Default
294
+ </Toggle>
295
+ <Toggle size="lg" aria-label="Large with icon">
296
+ <EditBigIcon />
297
+ Large
298
+ </Toggle>
299
+ </div>
300
+ </div>
301
+
302
+ {/* Icon Only Sizes */}
303
+ <div className="space-y-4">
304
+ <h4 className="text-center text-sm font-medium text-white/70">
305
+ Icon Only
306
+ </h4>
307
+ <div className="flex items-center justify-center gap-4">
308
+ <Toggle size="sm" aria-label="Small icon only">
309
+ <PlusIcon />
310
+ </Toggle>
311
+ <Toggle size="default" aria-label="Default icon only">
312
+ <SearchIcon />
313
+ </Toggle>
314
+ <Toggle size="lg" aria-label="Large icon only">
315
+ <EditBigIcon />
316
+ </Toggle>
317
+ </div>
318
+ </div>
319
+ </div>
320
+ </div>
321
+ ),
322
+ parameters: {
323
+ docs: {
324
+ description: {
325
+ story:
326
+ "Different size options for toggles, including text, icon with text, and icon-only variants.",
327
+ },
328
+ },
329
+ },
330
+ }
331
+
332
+ // 4. Icon Toggles
333
+ export const IconToggles: Story = {
334
+ render: () => {
335
+ const [notifications, setNotifications] = React.useState(false)
336
+ const [visibility, setVisibility] = React.useState(false)
337
+ const [completed, setCompleted] = React.useState(false)
338
+
339
+ return (
340
+ <div className="space-y-8 p-8">
341
+ <h3 className="text-center text-lg font-medium text-white">
342
+ Icon Toggles
343
+ </h3>
344
+
345
+ <div className="space-y-6">
346
+ {/* Icon with Text */}
347
+ <div className="space-y-4">
348
+ <h4 className="text-center text-sm font-medium text-white/70">
349
+ Icon with Text
350
+ </h4>
351
+ <div className="flex flex-wrap justify-center gap-4">
352
+ <Toggle
353
+ pressed={notifications}
354
+ onPressedChange={setNotifications}
355
+ aria-label="Toggle notifications"
356
+ >
357
+ <AlertIcon />
358
+ Notifications
359
+ </Toggle>
360
+
361
+ <Toggle
362
+ pressed={visibility}
363
+ onPressedChange={setVisibility}
364
+ aria-label="Toggle visibility"
365
+ >
366
+ {visibility ? <EyeOpenIcon /> : <EyeCloseIcon />}
367
+ {visibility ? "Visible" : "Hidden"}
368
+ </Toggle>
369
+
370
+ <Toggle
371
+ pressed={completed}
372
+ onPressedChange={setCompleted}
373
+ aria-label="Toggle completion"
374
+ >
375
+ <TickCircleIcon />
376
+ Complete
377
+ </Toggle>
378
+ </div>
379
+ </div>
380
+
381
+ {/* Icon Only */}
382
+ <div className="space-y-4">
383
+ <h4 className="text-center text-sm font-medium text-white/70">
384
+ Icon Only
385
+ </h4>
386
+ <div className="flex flex-wrap justify-center gap-4">
387
+ <Toggle aria-label="Toggle search">
388
+ <SearchIcon />
389
+ </Toggle>
390
+
391
+ <Toggle aria-label="Toggle edit mode">
392
+ <EditBigIcon />
393
+ </Toggle>
394
+
395
+ <Toggle aria-label="Toggle charts">
396
+ <FileChartIcon />
397
+ </Toggle>
398
+
399
+ <Toggle aria-label="Add to favorites" defaultPressed>
400
+ <PlusIcon />
401
+ </Toggle>
402
+
403
+ <Toggle aria-label="Delete mode" variant="outline">
404
+ <TrashIcon />
405
+ </Toggle>
406
+ </div>
407
+ </div>
408
+
409
+ {/* Different Variants */}
410
+ <div className="space-y-4">
411
+ <h4 className="text-center text-sm font-medium text-white/70">
412
+ Different Variants
413
+ </h4>
414
+ <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
415
+ <div className="space-y-2">
416
+ <span className="text-xs text-white/60">Default Variant</span>
417
+ <div className="flex flex-wrap gap-2">
418
+ <Toggle aria-label="Default alert">
419
+ <AlertIcon />
420
+ </Toggle>
421
+ <Toggle defaultPressed aria-label="Default search">
422
+ <SearchIcon />
423
+ </Toggle>
424
+ <Toggle aria-label="Default edit">
425
+ <EditBigIcon />
426
+ </Toggle>
427
+ </div>
428
+ </div>
429
+
430
+ <div className="space-y-2">
431
+ <span className="text-xs text-white/60">Outline Variant</span>
432
+ <div className="flex flex-wrap gap-2">
433
+ <Toggle variant="outline" aria-label="Outline alert">
434
+ <AlertIcon />
435
+ </Toggle>
436
+ <Toggle
437
+ variant="outline"
438
+ defaultPressed
439
+ aria-label="Outline search"
440
+ >
441
+ <SearchIcon />
442
+ </Toggle>
443
+ <Toggle variant="outline" aria-label="Outline edit">
444
+ <EditBigIcon />
445
+ </Toggle>
446
+ </div>
447
+ </div>
448
+ </div>
449
+ </div>
450
+ </div>
451
+ </div>
452
+ )
453
+ },
454
+ parameters: {
455
+ docs: {
456
+ description: {
457
+ story:
458
+ "Icon-based toggles showing different configurations including dynamic icons and various states.",
459
+ },
460
+ },
461
+ },
462
+ }
463
+
464
+ // 5. Interactive States
465
+ export const InteractiveStates: Story = {
466
+ render: () => {
467
+ const [states, setStates] = React.useState({
468
+ bold: false,
469
+ italic: false,
470
+ underline: false,
471
+ notifications: true,
472
+ autoSave: false,
473
+ darkMode: true,
474
+ })
475
+
476
+ const updateState = (key: keyof typeof states) => {
477
+ setStates((prev) => ({ ...prev, [key]: !prev[key] }))
478
+ }
479
+
480
+ return (
481
+ <div className="space-y-8 p-8">
482
+ <h3 className="text-center text-lg font-medium text-white">
483
+ Interactive States
484
+ </h3>
485
+
486
+ <div className="space-y-6">
487
+ {/* Text Formatting Toolbar */}
488
+ <div className="space-y-4">
489
+ <h4 className="text-center text-sm font-medium text-white/70">
490
+ Text Formatting Toolbar
491
+ </h4>
492
+ <div className="flex justify-center">
493
+ <div className="flex items-center gap-1 rounded-lg border border-white/10 bg-white/5 p-2">
494
+ <Toggle
495
+ size="sm"
496
+ pressed={states.bold}
497
+ onPressedChange={() => updateState("bold")}
498
+ aria-label="Toggle bold"
499
+ >
500
+ <span className="font-bold">B</span>
501
+ </Toggle>
502
+ <Toggle
503
+ size="sm"
504
+ pressed={states.italic}
505
+ onPressedChange={() => updateState("italic")}
506
+ aria-label="Toggle italic"
507
+ >
508
+ <span className="italic">I</span>
509
+ </Toggle>
510
+ <Toggle
511
+ size="sm"
512
+ pressed={states.underline}
513
+ onPressedChange={() => updateState("underline")}
514
+ aria-label="Toggle underline"
515
+ >
516
+ <span className="underline">U</span>
517
+ </Toggle>
518
+ <div className="mx-2 h-6 w-px bg-white/20"></div>
519
+ <Toggle size="sm" aria-label="Add item">
520
+ <PlusIcon />
521
+ </Toggle>
522
+ <Toggle size="sm" aria-label="Search">
523
+ <SearchIcon />
524
+ </Toggle>
525
+ </div>
526
+ </div>
527
+ </div>
528
+
529
+ {/* Settings Panel */}
530
+ <div className="space-y-4">
531
+ <h4 className="text-center text-sm font-medium text-white/70">
532
+ Settings Panel
533
+ </h4>
534
+ <div className="mx-auto max-w-xs space-y-3">
535
+ <div className="flex items-center justify-between rounded-lg border border-white/10 bg-white/5 p-3">
536
+ <div className="flex items-center gap-3">
537
+ <AlertIcon className="h-4 w-4 text-blue-400" />
538
+ <span className="text-sm text-white">Notifications</span>
539
+ </div>
540
+ <Toggle
541
+ size="sm"
542
+ pressed={states.notifications}
543
+ onPressedChange={() => updateState("notifications")}
544
+ aria-label="Toggle notifications"
545
+ />
546
+ </div>
547
+
548
+ <div className="flex items-center justify-between rounded-lg border border-white/10 bg-white/5 p-3">
549
+ <div className="flex items-center gap-3">
550
+ <TickCircleIcon className="h-4 w-4 text-green-400" />
551
+ <span className="text-sm text-white">Auto Save</span>
552
+ </div>
553
+ <Toggle
554
+ size="sm"
555
+ pressed={states.autoSave}
556
+ onPressedChange={() => updateState("autoSave")}
557
+ aria-label="Toggle auto save"
558
+ />
559
+ </div>
560
+
561
+ <div className="flex items-center justify-between rounded-lg border border-white/10 bg-white/5 p-3">
562
+ <div className="flex items-center gap-3">
563
+ <EyeOpenIcon className="h-4 w-4 text-purple-400" />
564
+ <span className="text-sm text-white">Dark Mode</span>
565
+ </div>
566
+ <Toggle
567
+ size="sm"
568
+ pressed={states.darkMode}
569
+ onPressedChange={() => updateState("darkMode")}
570
+ aria-label="Toggle dark mode"
571
+ />
572
+ </div>
573
+ </div>
574
+ </div>
575
+
576
+ {/* State Display */}
577
+ <div className="space-y-4">
578
+ <h4 className="text-center text-sm font-medium text-white/70">
579
+ Current States
580
+ </h4>
581
+ <div className="mx-auto max-w-md rounded-lg border border-white/10 bg-white/5 p-4">
582
+ <div className="grid grid-cols-2 gap-2 text-xs">
583
+ {Object.entries(states).map(([key, value]) => (
584
+ <div key={key} className="flex justify-between">
585
+ <span className="text-white/70 capitalize">{key}:</span>
586
+ <span className={value ? "text-green-400" : "text-red-400"}>
587
+ {value ? "ON" : "OFF"}
588
+ </span>
589
+ </div>
590
+ ))}
591
+ </div>
592
+ </div>
593
+ </div>
594
+ </div>
595
+ </div>
596
+ )
597
+ },
598
+ parameters: {
599
+ docs: {
600
+ description: {
601
+ story:
602
+ "Interactive examples showing toggles in real-world scenarios like toolbars and settings panels.",
603
+ },
604
+ },
605
+ },
606
+ }
607
+
608
+ // 6. Accessibility Demo
609
+ export const AccessibilityDemo: Story = {
610
+ render: () => (
611
+ <div className="space-y-8 p-8">
612
+ <h3 className="text-center text-lg font-medium text-white">
613
+ Accessibility Features
614
+ </h3>
615
+
616
+ <div className="space-y-6">
617
+ <div className="rounded-lg border border-blue-500/30 bg-blue-900/10 p-4">
618
+ <h4 className="mb-2 text-sm font-medium text-blue-300">
619
+ Keyboard Navigation
620
+ </h4>
621
+ <p className="mb-2 text-xs text-blue-200/70">
622
+ Try these keyboard interactions:
623
+ </p>
624
+ <ul className="space-y-1 text-xs text-blue-200/70">
625
+ <li>
626
+ • <kbd className="rounded bg-white/10 px-1">Tab</kbd> to focus
627
+ toggles
628
+ </li>
629
+ <li>
630
+ • <kbd className="rounded bg-white/10 px-1">Space</kbd> or{" "}
631
+ <kbd className="rounded bg-white/10 px-1">Enter</kbd> to toggle
632
+ state
633
+ </li>
634
+ <li>• Clear focus indicators show current position</li>
635
+ <li>• Screen readers announce pressed state</li>
636
+ </ul>
637
+ </div>
638
+
639
+ {/* Keyboard Accessible Examples */}
640
+ <div className="space-y-4">
641
+ <h4 className="text-sm font-medium text-white/70">
642
+ Keyboard Accessible Toggles
643
+ </h4>
644
+ <div className="flex flex-wrap justify-center gap-4">
645
+ <Toggle aria-label="Toggle feature A - currently off">
646
+ <AlertIcon />
647
+ Feature A
648
+ </Toggle>
649
+
650
+ <Toggle defaultPressed aria-label="Toggle feature B - currently on">
651
+ <TickCircleIcon />
652
+ Feature B
653
+ </Toggle>
654
+
655
+ <Toggle
656
+ variant="outline"
657
+ aria-label="Toggle visibility - show or hide content"
658
+ >
659
+ <EyeOpenIcon />
660
+ Visibility
661
+ </Toggle>
662
+
663
+ <Toggle size="sm" aria-label="Toggle search mode">
664
+ <SearchIcon />
665
+ </Toggle>
666
+ </div>
667
+ </div>
668
+
669
+ {/* ARIA Labels Demo */}
670
+ <div className="space-y-4">
671
+ <h4 className="text-sm font-medium text-white/70">
672
+ ARIA Labels Best Practices
673
+ </h4>
674
+ <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
675
+ <div className="space-y-3">
676
+ <span className="text-xs text-white/60">Good Examples</span>
677
+ <div className="space-y-2">
678
+ <Toggle aria-label="Toggle notifications - receive alerts when new messages arrive">
679
+ <AlertIcon />
680
+ Notifications
681
+ </Toggle>
682
+ <Toggle aria-label="Toggle edit mode - switch between viewing and editing">
683
+ <EditBigIcon />
684
+ Edit Mode
685
+ </Toggle>
686
+ </div>
687
+ </div>
688
+
689
+ <div className="space-y-3">
690
+ <span className="text-xs text-white/60">Code Examples</span>
691
+ <div className="rounded border border-white/10 bg-white/5 p-3 font-mono text-xs text-white/80">
692
+ <div>aria-label="Toggle notifications"</div>
693
+ <div>aria-label="Show/hide password"</div>
694
+ <div>aria-label="Enable dark mode"</div>
695
+ </div>
696
+ </div>
697
+ </div>
698
+ </div>
699
+
700
+ <div className="rounded-lg border border-amber-500/30 bg-amber-900/10 p-4">
701
+ <h4 className="mb-2 text-sm font-medium text-amber-300">
702
+ Best Practices
703
+ </h4>
704
+ <ul className="space-y-1 text-xs text-amber-200/70">
705
+ <li>• Always provide descriptive aria-label attributes</li>
706
+ <li>• Include current state in label when helpful</li>
707
+ <li>• Use consistent toggle patterns across your app</li>
708
+ <li>• Test with screen readers and keyboard navigation</li>
709
+ <li>• Ensure sufficient color contrast for all states</li>
710
+ <li>• Provide visual feedback for state changes</li>
711
+ </ul>
712
+ </div>
713
+ </div>
714
+ </div>
715
+ ),
716
+ parameters: {
717
+ docs: {
718
+ description: {
719
+ story:
720
+ "Accessibility features including keyboard navigation, ARIA labels, and best practices for inclusive design.",
721
+ },
722
+ },
723
+ },
724
+ }
725
+
726
+ // 7. Use Cases
727
+ export const UseCases: Story = {
728
+ render: () => {
729
+ const [preferences, setPreferences] = React.useState({
730
+ notifications: true,
731
+ autoSave: false,
732
+ showPreview: true,
733
+ darkMode: true,
734
+ })
735
+
736
+ const [toolbar, setToolbar] = React.useState({
737
+ bold: false,
738
+ italic: false,
739
+ list: false,
740
+ code: false,
741
+ })
742
+
743
+ const updatePreference = (key: keyof typeof preferences) => {
744
+ setPreferences((prev) => ({ ...prev, [key]: !prev[key] }))
745
+ }
746
+
747
+ const updateToolbar = (key: keyof typeof toolbar) => {
748
+ setToolbar((prev) => ({ ...prev, [key]: !prev[key] }))
749
+ }
750
+
751
+ return (
752
+ <div className="space-y-8 p-8">
753
+ <h3 className="text-center text-lg font-medium text-white">
754
+ Real-world Use Cases
755
+ </h3>
756
+
757
+ <div className="space-y-8">
758
+ {/* Editor Toolbar */}
759
+ <div className="space-y-4">
760
+ <h4 className="text-sm font-medium text-white/70">
761
+ Editor Toolbar
762
+ </h4>
763
+ <div className="rounded-lg border border-white/10 bg-white/5 p-4">
764
+ <div className="flex items-center gap-1">
765
+ <Toggle
766
+ size="sm"
767
+ pressed={toolbar.bold}
768
+ onPressedChange={() => updateToolbar("bold")}
769
+ aria-label="Toggle bold formatting"
770
+ >
771
+ <span className="text-sm font-bold">B</span>
772
+ </Toggle>
773
+ <Toggle
774
+ size="sm"
775
+ pressed={toolbar.italic}
776
+ onPressedChange={() => updateToolbar("italic")}
777
+ aria-label="Toggle italic formatting"
778
+ >
779
+ <span className="text-sm italic">I</span>
780
+ </Toggle>
781
+ <div className="mx-2 h-4 w-px bg-white/20"></div>
782
+ <Toggle
783
+ size="sm"
784
+ pressed={toolbar.list}
785
+ onPressedChange={() => updateToolbar("list")}
786
+ aria-label="Toggle bullet list"
787
+ >
788
+ • List
789
+ </Toggle>
790
+ <Toggle
791
+ size="sm"
792
+ pressed={toolbar.code}
793
+ onPressedChange={() => updateToolbar("code")}
794
+ aria-label="Toggle code formatting"
795
+ >
796
+ <span className="font-mono text-sm">&lt;/&gt;</span>
797
+ </Toggle>
798
+ <div className="mx-2 h-4 w-px bg-white/20"></div>
799
+ <Toggle size="sm" aria-label="Insert image">
800
+ <FileChartIcon />
801
+ </Toggle>
802
+ <Toggle size="sm" aria-label="Add link">
803
+ <PlusIcon />
804
+ </Toggle>
805
+ </div>
806
+ </div>
807
+ </div>
808
+
809
+ {/* User Preferences */}
810
+ <div className="space-y-4">
811
+ <h4 className="text-sm font-medium text-white/70">
812
+ User Preferences
813
+ </h4>
814
+ <div className="grid grid-cols-1 gap-3 lg:grid-cols-2">
815
+ <div className="space-y-3">
816
+ <div className="flex items-center justify-between rounded-lg border border-white/10 bg-white/5 p-3">
817
+ <div className="flex items-center gap-3">
818
+ <AlertIcon className="h-4 w-4 text-blue-400" />
819
+ <div>
820
+ <div className="text-sm text-white">
821
+ Push Notifications
822
+ </div>
823
+ <div className="text-xs text-white/60">
824
+ Get notified of updates
825
+ </div>
826
+ </div>
827
+ </div>
828
+ <Toggle
829
+ pressed={preferences.notifications}
830
+ onPressedChange={() => updatePreference("notifications")}
831
+ aria-label="Toggle push notifications"
832
+ />
833
+ </div>
834
+
835
+ <div className="flex items-center justify-between rounded-lg border border-white/10 bg-white/5 p-3">
836
+ <div className="flex items-center gap-3">
837
+ <TickCircleIcon className="h-4 w-4 text-green-400" />
838
+ <div>
839
+ <div className="text-sm text-white">Auto Save</div>
840
+ <div className="text-xs text-white/60">
841
+ Save changes automatically
842
+ </div>
843
+ </div>
844
+ </div>
845
+ <Toggle
846
+ pressed={preferences.autoSave}
847
+ onPressedChange={() => updatePreference("autoSave")}
848
+ aria-label="Toggle auto save"
849
+ />
850
+ </div>
851
+ </div>
852
+
853
+ <div className="space-y-3">
854
+ <div className="flex items-center justify-between rounded-lg border border-white/10 bg-white/5 p-3">
855
+ <div className="flex items-center gap-3">
856
+ <EyeOpenIcon className="h-4 w-4 text-purple-400" />
857
+ <div>
858
+ <div className="text-sm text-white">Preview Mode</div>
859
+ <div className="text-xs text-white/60">
860
+ Show live preview
861
+ </div>
862
+ </div>
863
+ </div>
864
+ <Toggle
865
+ pressed={preferences.showPreview}
866
+ onPressedChange={() => updatePreference("showPreview")}
867
+ aria-label="Toggle preview mode"
868
+ />
869
+ </div>
870
+
871
+ <div className="flex items-center justify-between rounded-lg border border-white/10 bg-white/5 p-3">
872
+ <div className="flex items-center gap-3">
873
+ <span className="text-lg">🌙</span>
874
+ <div>
875
+ <div className="text-sm text-white">Dark Mode</div>
876
+ <div className="text-xs text-white/60">
877
+ Use dark theme
878
+ </div>
879
+ </div>
880
+ </div>
881
+ <Toggle
882
+ pressed={preferences.darkMode}
883
+ onPressedChange={() => updatePreference("darkMode")}
884
+ aria-label="Toggle dark mode"
885
+ />
886
+ </div>
887
+ </div>
888
+ </div>
889
+ </div>
890
+
891
+ {/* Filter Toolbar */}
892
+ <div className="space-y-4">
893
+ <h4 className="text-sm font-medium text-white/70">
894
+ Filter Toolbar
895
+ </h4>
896
+ <div className="rounded-lg border border-white/10 bg-white/5 p-4">
897
+ <div className="flex flex-wrap gap-2">
898
+ <Toggle
899
+ variant="outline"
900
+ size="sm"
901
+ aria-label="Show completed items"
902
+ >
903
+ <TickCircleIcon />
904
+ Completed
905
+ </Toggle>
906
+ <Toggle
907
+ variant="outline"
908
+ size="sm"
909
+ aria-label="Show pending items"
910
+ >
911
+ <AlertIcon />
912
+ Pending
913
+ </Toggle>
914
+ <Toggle
915
+ variant="outline"
916
+ size="sm"
917
+ aria-label="Show archived items"
918
+ >
919
+ <FileChartIcon />
920
+ Archived
921
+ </Toggle>
922
+ <Toggle
923
+ variant="outline"
924
+ size="sm"
925
+ defaultPressed
926
+ aria-label="Show active items"
927
+ >
928
+ <EyeOpenIcon />
929
+ Active
930
+ </Toggle>
931
+ </div>
932
+ </div>
933
+ </div>
934
+
935
+ {/* View Options */}
936
+ <div className="space-y-4">
937
+ <h4 className="text-sm font-medium text-white/70">View Options</h4>
938
+ <div className="flex justify-center gap-1 rounded-lg border border-white/10 bg-white/5 p-1">
939
+ <Toggle size="sm" defaultPressed aria-label="Grid view">
940
+ Grid
941
+ </Toggle>
942
+ <Toggle size="sm" aria-label="List view">
943
+ List
944
+ </Toggle>
945
+ <Toggle size="sm" aria-label="Card view">
946
+ Cards
947
+ </Toggle>
948
+ </div>
949
+ </div>
950
+ </div>
951
+ </div>
952
+ )
953
+ },
954
+ parameters: {
955
+ docs: {
956
+ description: {
957
+ story:
958
+ "Real-world examples showing toggles in editor toolbars, user preferences, filters, and view options.",
959
+ },
960
+ },
961
+ },
962
+ }
963
+
964
+ // 8. Controlled vs Uncontrolled
965
+ export const ControlledVsUncontrolled: Story = {
966
+ render: () => {
967
+ const [controlledState, setControlledState] = React.useState(false)
968
+ const [multipleStates, setMultipleStates] = React.useState({
969
+ option1: true,
970
+ option2: false,
971
+ option3: true,
972
+ })
973
+
974
+ return (
975
+ <div className="space-y-8 p-8">
976
+ <h3 className="text-center text-lg font-medium text-white">
977
+ Controlled vs Uncontrolled
978
+ </h3>
979
+
980
+ <div className="grid grid-cols-1 gap-8 lg:grid-cols-2">
981
+ {/* Uncontrolled */}
982
+ <div className="space-y-4">
983
+ <h4 className="text-sm font-medium text-white/70">
984
+ Uncontrolled (Internal State)
985
+ </h4>
986
+ <div className="space-y-3">
987
+ <Toggle aria-label="Uncontrolled toggle 1">Default State</Toggle>
988
+ <Toggle defaultPressed aria-label="Uncontrolled toggle 2">
989
+ Default Pressed
990
+ </Toggle>
991
+ <Toggle variant="outline" aria-label="Uncontrolled toggle 3">
992
+ <AlertIcon />
993
+ With Icon
994
+ </Toggle>
995
+ </div>
996
+ <div className="rounded border border-white/10 bg-white/5 p-3 font-mono text-xs text-white/80">
997
+ <div>{"<Toggle>"}</div>
998
+ <div>{" Default State"}</div>
999
+ <div>{"</Toggle>"}</div>
1000
+ <br />
1001
+ <div>{"<Toggle defaultPressed>"}</div>
1002
+ <div>{" Default Pressed"}</div>
1003
+ <div>{"</Toggle>"}</div>
1004
+ </div>
1005
+ </div>
1006
+
1007
+ {/* Controlled */}
1008
+ <div className="space-y-4">
1009
+ <h4 className="text-sm font-medium text-white/70">
1010
+ Controlled (External State)
1011
+ </h4>
1012
+ <div className="space-y-3">
1013
+ <Toggle
1014
+ pressed={controlledState}
1015
+ onPressedChange={setControlledState}
1016
+ aria-label="Controlled toggle"
1017
+ >
1018
+ Controlled: {controlledState ? "ON" : "OFF"}
1019
+ </Toggle>
1020
+
1021
+ <div className="space-y-2">
1022
+ {Object.entries(multipleStates).map(([key, value]) => (
1023
+ <Toggle
1024
+ key={key}
1025
+ variant="outline"
1026
+ size="sm"
1027
+ pressed={value}
1028
+ onPressedChange={(pressed) =>
1029
+ setMultipleStates((prev) => ({ ...prev, [key]: pressed }))
1030
+ }
1031
+ aria-label={`Toggle ${key}`}
1032
+ >
1033
+ <TickCircleIcon />
1034
+ {key}: {value ? "ON" : "OFF"}
1035
+ </Toggle>
1036
+ ))}
1037
+ </div>
1038
+ </div>
1039
+
1040
+ <div className="rounded border border-white/10 bg-white/5 p-3 font-mono text-xs text-white/80">
1041
+ <div>{"const [state, setState] = useState(false)"}</div>
1042
+ <br />
1043
+ <div>{"<Toggle"}</div>
1044
+ <div>{" pressed={state}"}</div>
1045
+ <div>{" onPressedChange={setState}"}</div>
1046
+ <div>{">"}</div>
1047
+ <div>{" Controlled"}</div>
1048
+ <div>{"</Toggle>"}</div>
1049
+ </div>
1050
+ </div>
1051
+ </div>
1052
+
1053
+ <div className="rounded-lg border border-blue-500/30 bg-blue-900/10 p-4">
1054
+ <h4 className="mb-2 text-sm font-medium text-blue-300">
1055
+ When to Use Each
1056
+ </h4>
1057
+ <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
1058
+ <div>
1059
+ <h5 className="mb-1 text-xs font-medium text-blue-200">
1060
+ Uncontrolled
1061
+ </h5>
1062
+ <ul className="space-y-1 text-xs text-blue-200/70">
1063
+ <li>• Simple on/off toggles</li>
1064
+ <li>• No external state dependency</li>
1065
+ <li>• Form elements</li>
1066
+ <li>• Less code complexity</li>
1067
+ </ul>
1068
+ </div>
1069
+ <div>
1070
+ <h5 className="mb-1 text-xs font-medium text-blue-200">
1071
+ Controlled
1072
+ </h5>
1073
+ <ul className="space-y-1 text-xs text-blue-200/70">
1074
+ <li>• Complex state management</li>
1075
+ <li>• Multiple dependent toggles</li>
1076
+ <li>• Form validation</li>
1077
+ <li>• External state updates</li>
1078
+ </ul>
1079
+ </div>
1080
+ </div>
1081
+ </div>
1082
+ </div>
1083
+ )
1084
+ },
1085
+ parameters: {
1086
+ docs: {
1087
+ description: {
1088
+ story:
1089
+ "Comparison between controlled and uncontrolled toggle usage patterns with practical examples.",
1090
+ },
1091
+ },
1092
+ },
1093
+ }