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