aural-ui 3.0.7 → 4.1.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.
- package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1199
- package/dist/components/avatar/Avatar.stories.tsx +235 -237
- package/dist/components/badge/Badge.stories.tsx +379 -116
- package/dist/components/banner/Banner.stories.tsx +445 -391
- package/dist/components/breadcrumb/Breadcrumb.stories.tsx +453 -199
- package/dist/components/button/Button.stories.tsx +585 -230
- package/dist/components/button/index.tsx +7 -7
- package/dist/components/card/Card.stories.tsx +619 -301
- package/dist/components/char-count/CharCount.stories.tsx +350 -248
- package/dist/components/checkbox/Checkbox.stories.tsx +309 -167
- package/dist/components/chip/Chip.stories.tsx +362 -168
- package/dist/components/circular-loader/CircularLoader.stories.tsx +221 -620
- package/dist/components/clamp-lines/ClampLines.stories.tsx +246 -117
- package/dist/components/collapsible/Collapsible.stories.tsx +391 -252
- package/dist/components/command/Command.stories.tsx +533 -856
- package/dist/components/dialog/Dialog.stories.tsx +505 -949
- package/dist/components/divider/Divider.stories.tsx +265 -502
- package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
- package/dist/components/drawer/Drawer.stories.tsx +659 -993
- package/dist/components/drawer/index.tsx +3 -3
- package/dist/components/dropdown/Dropdown.stories.tsx +643 -1018
- package/dist/components/form/Form.stories.tsx +560 -274
- package/dist/components/helper-text/HelperText.stories.tsx +199 -200
- package/dist/components/hover-card/HoverCard.stories.tsx +318 -1221
- package/dist/components/icon-button/IconButton.stories.tsx +837 -194
- package/dist/components/if-else/if-else.stories.tsx +370 -83
- package/dist/components/input/Input.stories.tsx +436 -368
- package/dist/components/label/Label.stories.tsx +156 -154
- package/dist/components/list/List.stories.tsx +485 -822
- package/dist/components/marquee/Marquee.stories.tsx +356 -694
- package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -410
- package/dist/components/overlay/Overlay.stories.tsx +452 -818
- package/dist/components/overlay/index.tsx +4 -4
- package/dist/components/pagination/Pagination.stories.tsx +721 -210
- package/dist/components/popover/Popover.stories.tsx +484 -873
- package/dist/components/radio/Radio.stories.tsx +432 -124
- package/dist/components/resizable/Resizable.stories.tsx +496 -752
- package/dist/components/scroll-area/ScrollArea.stories.tsx +384 -1006
- package/dist/components/search/Search.stories.tsx +314 -575
- package/dist/components/select/Select.stories.tsx +684 -787
- package/dist/components/sheet/Sheet.stories.tsx +671 -936
- package/dist/components/skelton/Skelton.stories.tsx +230 -764
- package/dist/components/slider/Slider.stories.tsx +384 -737
- package/dist/components/stepper/Stepper.stories.tsx +371 -514
- package/dist/components/switch/Switch.stories.tsx +461 -208
- package/dist/components/switch-case/SwitchCase.stories.tsx +367 -188
- package/dist/components/table/Table.stories.tsx +770 -914
- package/dist/components/tabs/Tabs.stories.tsx +459 -1400
- package/dist/components/tag/Tag.stories.tsx +714 -542
- package/dist/components/textarea/TextArea.stories.tsx +621 -562
- package/dist/components/thumbnail-tags/ThumbnailTags.stories.tsx +228 -148
- package/dist/components/toast/Toast.stories.tsx +452 -1333
- package/dist/components/toggle/Toggle.stories.tsx +488 -909
- package/dist/components/tooltip/Tooltip.stories.tsx +344 -1372
- package/dist/components/typography/Typography.stories.tsx +406 -89
- package/dist/hooks/use-change-state/UseChangeState.stories.tsx +309 -606
- package/dist/hooks/use-previous/UsePrevious.stories.tsx +367 -917
- package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +639 -867
- package/dist/icons/Icons.stories.tsx +0 -12
- package/dist/icons/ai-avatar-icon/AiAvatarIcon.stories.tsx +226 -1013
- package/dist/icons/alert-icon/AlertIcon.stories.tsx +109 -929
- package/dist/icons/all-icons.tsx +124 -87
- package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +140 -971
- package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +148 -888
- package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +135 -1019
- package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +137 -953
- package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +138 -997
- package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +136 -942
- package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +148 -1092
- package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +146 -1211
- package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +126 -615
- package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +144 -1164
- package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +167 -985
- package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +122 -1179
- package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +124 -1168
- package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +119 -850
- package/dist/icons/camera-icon/CameraIcon.stories.tsx +112 -1213
- package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +117 -934
- package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +160 -961
- package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +163 -961
- package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +144 -942
- package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +129 -966
- package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +147 -964
- package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +145 -975
- package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +150 -1142
- package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +114 -461
- package/dist/icons/coin-icon/CoinIcon.stories.tsx +124 -1322
- package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +117 -1318
- package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +114 -903
- package/dist/icons/command-icon/CommandIcon.stories.tsx +127 -1042
- package/dist/icons/copy-icon/CopyIcon.stories.tsx +123 -962
- package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +147 -999
- package/dist/icons/cross-icon/CrossIcon.stories.tsx +139 -960
- package/dist/icons/download-icon/DownloadIcon.stories.tsx +126 -820
- package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +124 -1031
- package/dist/icons/email-icon/EmailIcon.stories.tsx +115 -936
- package/dist/icons/expand-icon/ExpandIcon.stories.tsx +112 -1111
- package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +144 -1025
- package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +143 -1036
- package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +127 -1011
- package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +126 -1056
- package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +125 -614
- package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +119 -1050
- package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +169 -989
- package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +115 -1145
- package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +115 -1122
- package/dist/icons/globe-icon/GlobeIcon.stories.tsx +130 -313
- package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +145 -940
- package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +119 -1174
- package/dist/icons/head-icon/HeadIcon.stories.tsx +111 -916
- package/dist/icons/heart-icon/HeartIcon.stories.tsx +120 -1019
- package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +119 -683
- package/dist/icons/image-icon/ImageIcon.stories.tsx +105 -1121
- package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +111 -1192
- package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +136 -1256
- package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +159 -962
- package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +161 -1385
- package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +124 -972
- package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +119 -948
- package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +119 -942
- package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +108 -1215
- package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +154 -1517
- package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +110 -1188
- package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +119 -678
- package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +123 -1184
- package/dist/icons/message-icon/MessageIcon.stories.tsx +114 -538
- package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +116 -1158
- package/dist/icons/moon-icon/MoonIcon.stories.tsx +120 -536
- package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +109 -1184
- package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +115 -1134
- package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +119 -971
- package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +111 -1100
- package/dist/icons/notes-icon/NotesIcon.stories.tsx +119 -1101
- package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +109 -1111
- package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +122 -684
- package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +113 -954
- package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +112 -877
- package/dist/icons/pause-icon/PauseIcon.stories.tsx +113 -1000
- package/dist/icons/pencil-icon/PencilIcon.stories.tsx +115 -1070
- package/dist/icons/phone-icon/PhoneIcon.stories.tsx +115 -978
- package/dist/icons/plus-icon/PlusIcon.stories.tsx +106 -1093
- package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +107 -829
- package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +102 -469
- package/dist/icons/search-icon/SearchIcon.stories.tsx +111 -1124
- package/dist/icons/setting-icon/SettingIcon.stories.tsx +107 -970
- package/dist/icons/share-icon/ShareIcon.stories.tsx +120 -1025
- package/dist/icons/shield-icon/ShieldIcon.stories.tsx +117 -931
- package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +137 -1104
- package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +172 -982
- package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +164 -983
- package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +105 -958
- package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +158 -580
- package/dist/icons/spinner-gradient-icon/index.tsx +6 -1
- package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +158 -587
- package/dist/icons/spinner-solid-icon/index.tsx +6 -1
- package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +146 -682
- package/dist/icons/spinner-solid-neutral-icon/index.tsx +1 -1
- package/dist/icons/star-icon/StarIcon.stories.tsx +124 -904
- package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +112 -964
- package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +116 -852
- package/dist/icons/sun-icon/SunIcon.stories.tsx +120 -831
- package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +116 -950
- package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +123 -980
- package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +156 -1427
- package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +146 -1142
- package/dist/icons/tick-icon/TickIcon.stories.tsx +145 -1276
- package/dist/icons/trash-icon/TrashIcon.stories.tsx +108 -933
- package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +157 -1402
- package/dist/icons/upload-icon/UploadIcon.stories.tsx +115 -889
- package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +118 -984
- package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +125 -1049
- package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +123 -1356
- package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +110 -1171
- package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +112 -1093
- package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +115 -1087
- package/dist/icons/warning-icon/WarningIcon.stories.tsx +122 -1046
- package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +161 -936
- package/dist/index.cjs +84 -84
- package/dist/index.js +84 -84
- package/dist/styles/aural-all-theme.css +1222 -0
- package/dist/styles/{aural-theme.css → aural-dark-theme.css} +15 -3
- package/dist/styles/aural-light-theme.css +1047 -0
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
63
|
+
description: "Size of the toggle",
|
|
140
64
|
},
|
|
141
65
|
pressed: {
|
|
142
66
|
control: "boolean",
|
|
@@ -146,174 +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.
|
|
160
|
-
|
|
79
|
+
// ─── 1. Playground ────────────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
export const Playground: Story = {
|
|
161
82
|
args: {
|
|
162
|
-
children: "Toggle
|
|
163
|
-
|
|
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:
|
|
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-center text-lg font-medium text-white">
|
|
179
|
-
Toggle Variants
|
|
180
|
-
</h3>
|
|
108
|
+
// ─── 2. All Variants ──────────────────────────────────────────────────────────
|
|
181
109
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
|
190
122
|
</Toggle>
|
|
191
|
-
<
|
|
192
|
-
|
|
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
|
|
193
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>
|
|
194
142
|
</div>
|
|
195
143
|
</div>
|
|
144
|
+
</div>
|
|
196
145
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
|
203
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">
|
|
204
161
|
<Toggle
|
|
205
162
|
variant="outline"
|
|
206
|
-
|
|
207
|
-
aria-label="Outline
|
|
163
|
+
size="default"
|
|
164
|
+
aria-label="Outline default"
|
|
208
165
|
>
|
|
209
|
-
|
|
210
|
-
</Toggle>
|
|
211
|
-
<Toggle variant="outline" disabled aria-label="Outline disabled">
|
|
212
|
-
Disabled
|
|
166
|
+
Default
|
|
213
167
|
</Toggle>
|
|
168
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
169
|
+
default
|
|
170
|
+
</p>
|
|
214
171
|
</div>
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
|
172
|
+
<div className="space-y-2 text-center">
|
|
173
|
+
<Toggle variant="outline" size="lg" aria-label="Outline large">
|
|
174
|
+
Large
|
|
229
175
|
</Toggle>
|
|
176
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
177
|
+
lg
|
|
178
|
+
</p>
|
|
230
179
|
</div>
|
|
231
180
|
</div>
|
|
232
181
|
</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
182
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
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">
|
|
289
191
|
Small
|
|
290
192
|
</Toggle>
|
|
291
|
-
<
|
|
292
|
-
|
|
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">
|
|
293
199
|
Default
|
|
294
200
|
</Toggle>
|
|
295
|
-
<
|
|
296
|
-
|
|
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">
|
|
297
207
|
Large
|
|
298
208
|
</Toggle>
|
|
209
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
210
|
+
lg
|
|
211
|
+
</p>
|
|
299
212
|
</div>
|
|
300
213
|
</div>
|
|
214
|
+
</div>
|
|
301
215
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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 />
|
|
310
225
|
</Toggle>
|
|
311
|
-
<
|
|
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">
|
|
312
232
|
<SearchIcon />
|
|
313
233
|
</Toggle>
|
|
314
|
-
<
|
|
315
|
-
|
|
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 />
|
|
316
241
|
</Toggle>
|
|
242
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
243
|
+
filled
|
|
244
|
+
</p>
|
|
317
245
|
</div>
|
|
318
246
|
</div>
|
|
319
247
|
</div>
|
|
@@ -323,393 +251,173 @@ export const Sizes: Story = {
|
|
|
323
251
|
docs: {
|
|
324
252
|
description: {
|
|
325
253
|
story:
|
|
326
|
-
"
|
|
254
|
+
"Full variant × size matrix for all three visual styles (default, outline, filled), plus icon-only instances across each variant.",
|
|
327
255
|
},
|
|
328
256
|
},
|
|
329
257
|
},
|
|
330
258
|
}
|
|
331
259
|
|
|
332
|
-
//
|
|
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>
|
|
260
|
+
// ─── 3. States ────────────────────────────────────────────────────────────────
|
|
344
261
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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>
|
|
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>
|
|
379
276
|
</div>
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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>
|
|
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>
|
|
407
284
|
</div>
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
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>
|
|
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>
|
|
449
292
|
</div>
|
|
450
293
|
</div>
|
|
451
294
|
</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
295
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
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>
|
|
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>
|
|
527
309
|
</div>
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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>
|
|
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>
|
|
574
321
|
</div>
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
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>
|
|
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>
|
|
593
329
|
</div>
|
|
594
330
|
</div>
|
|
595
331
|
</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
332
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
</
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
</
|
|
634
|
-
<
|
|
635
|
-
|
|
636
|
-
|
|
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>
|
|
637
363
|
</div>
|
|
364
|
+
</div>
|
|
638
365
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
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">
|
|
646
374
|
<AlertIcon />
|
|
647
|
-
Feature A
|
|
648
375
|
</Toggle>
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
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 />
|
|
653
383
|
</Toggle>
|
|
654
|
-
|
|
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">
|
|
655
397
|
<Toggle
|
|
656
398
|
variant="outline"
|
|
657
|
-
|
|
399
|
+
defaultPressed
|
|
400
|
+
aria-label="Trash pressed outline"
|
|
658
401
|
>
|
|
659
|
-
<
|
|
660
|
-
Visibility
|
|
661
|
-
</Toggle>
|
|
662
|
-
|
|
663
|
-
<Toggle size="sm" aria-label="Toggle search mode">
|
|
664
|
-
<SearchIcon />
|
|
402
|
+
<TrashIcon />
|
|
665
403
|
</Toggle>
|
|
404
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
405
|
+
Pressed outline
|
|
406
|
+
</p>
|
|
666
407
|
</div>
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
<
|
|
676
|
-
|
|
677
|
-
|
|
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>
|
|
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>
|
|
697
419
|
</div>
|
|
698
420
|
</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
421
|
</div>
|
|
714
422
|
</div>
|
|
715
423
|
),
|
|
@@ -717,365 +425,236 @@ export const AccessibilityDemo: Story = {
|
|
|
717
425
|
docs: {
|
|
718
426
|
description: {
|
|
719
427
|
story:
|
|
720
|
-
"
|
|
428
|
+
"Pressed, unpressed, and disabled states rendered for each variant. Disabled toggles suppress pointer events and render at reduced opacity.",
|
|
721
429
|
},
|
|
722
430
|
},
|
|
723
431
|
},
|
|
724
432
|
}
|
|
725
433
|
|
|
726
|
-
//
|
|
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
|
-
})
|
|
434
|
+
// ─── 4. Interactive ───────────────────────────────────────────────────────────
|
|
735
435
|
|
|
736
|
-
|
|
436
|
+
export const Interactive: Story = {
|
|
437
|
+
render: () => {
|
|
438
|
+
const [formatting, setFormatting] = useState({
|
|
737
439
|
bold: false,
|
|
738
440
|
italic: false,
|
|
739
|
-
|
|
441
|
+
underline: false,
|
|
740
442
|
code: false,
|
|
741
443
|
})
|
|
742
444
|
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
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] }))
|
|
746
456
|
|
|
747
|
-
const
|
|
748
|
-
|
|
749
|
-
|
|
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)
|
|
750
463
|
|
|
751
464
|
return (
|
|
752
|
-
<div className="
|
|
753
|
-
<
|
|
754
|
-
|
|
755
|
-
|
|
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>
|
|
756
512
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
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"></></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>
|
|
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>
|
|
805
522
|
</div>
|
|
806
523
|
</div>
|
|
807
|
-
</div>
|
|
808
524
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
User Preferences
|
|
813
|
-
</h4>
|
|
814
|
-
<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 */}
|
|
815
528
|
<div className="space-y-3">
|
|
816
|
-
<
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
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>
|
|
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">
|
|
828
533
|
<Toggle
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
<
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
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" />
|
|
845
558
|
<Toggle
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
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>
|
|
850
573
|
</div>
|
|
851
574
|
</div>
|
|
852
575
|
|
|
576
|
+
{/* Playback controls */}
|
|
853
577
|
<div className="space-y-3">
|
|
854
|
-
<
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
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>
|
|
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">
|
|
864
582
|
<Toggle
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
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>
|
|
881
601
|
<Toggle
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
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>
|
|
886
611
|
</div>
|
|
887
612
|
</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
613
|
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
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]) => (
|
|
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>
|
|
1023
628
|
<Toggle
|
|
1024
|
-
key={key}
|
|
1025
629
|
variant="outline"
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
setMultipleStates((prev) => ({ ...prev, [key]: pressed }))
|
|
1030
|
-
}
|
|
1031
|
-
aria-label={`Toggle ${key}`}
|
|
630
|
+
pressed={done}
|
|
631
|
+
onPressedChange={setDone}
|
|
632
|
+
aria-label="Toggle complete"
|
|
1032
633
|
>
|
|
1033
634
|
<TickCircleIcon />
|
|
1034
|
-
{
|
|
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
|
|
1035
649
|
</Toggle>
|
|
1036
|
-
|
|
650
|
+
</div>
|
|
1037
651
|
</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
652
|
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
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>
|
|
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>
|
|
1079
658
|
</div>
|
|
1080
659
|
</div>
|
|
1081
660
|
</div>
|
|
@@ -1086,7 +665,7 @@ export const ControlledVsUncontrolled: Story = {
|
|
|
1086
665
|
docs: {
|
|
1087
666
|
description: {
|
|
1088
667
|
story:
|
|
1089
|
-
"
|
|
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.",
|
|
1090
669
|
},
|
|
1091
670
|
},
|
|
1092
671
|
},
|