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
|
@@ -4,18 +4,16 @@ import { Button } from "@components/button"
|
|
|
4
4
|
import { Checkbox } from "@components/checkbox"
|
|
5
5
|
import Input from "@components/input"
|
|
6
6
|
import { Label } from "@components/label"
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "@components/select"
|
|
14
|
-
import Textarea from "@components/textarea"
|
|
15
|
-
import { CrossIcon } from "@icons/cross-icon"
|
|
16
|
-
import { EditBigIcon } from "@icons/edit-big-icon"
|
|
7
|
+
import { ChevronRightIcon } from "@icons/chevron-right-icon"
|
|
8
|
+
import { MaintenanceIcon } from "@icons/maintenance-icon"
|
|
9
|
+
import { MusicalNoteIcon } from "@icons/musical-note-icon"
|
|
10
|
+
import { SearchIcon } from "@icons/search-icon"
|
|
11
|
+
import { SiteLogoIcon } from "@icons/site-logo-icon"
|
|
12
|
+
import { TickCircleIcon } from "@icons/tick-circle-icon"
|
|
17
13
|
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
18
14
|
|
|
15
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
16
|
+
|
|
19
17
|
import {
|
|
20
18
|
Drawer,
|
|
21
19
|
DrawerClose,
|
|
@@ -27,194 +25,50 @@ import {
|
|
|
27
25
|
DrawerTrigger,
|
|
28
26
|
} from "."
|
|
29
27
|
|
|
30
|
-
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
const meta: Meta<any> = {
|
|
31
30
|
title: "Components/UI/Drawer",
|
|
32
31
|
component: Drawer,
|
|
33
32
|
parameters: {
|
|
34
33
|
layout: "centered",
|
|
35
|
-
backgrounds: {
|
|
36
|
-
default: "dark",
|
|
37
|
-
values: [
|
|
38
|
-
{ name: "dark", value: "#0a0a0a" },
|
|
39
|
-
{ name: "light", value: "#ffffff" },
|
|
40
|
-
],
|
|
41
|
-
},
|
|
42
34
|
docs: {
|
|
43
35
|
description: {
|
|
44
|
-
component:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
A slide-out drawer component built on Vaul primitives with support for multiple directions, smooth animations, customizable content sections, and enhanced accessibility features.
|
|
48
|
-
|
|
49
|
-
## Features
|
|
50
|
-
|
|
51
|
-
- **Multiple Directions**: Top, bottom, left, and right slide directions
|
|
52
|
-
- **Multiple Variants**: Neutral and gradient styles with custom styling
|
|
53
|
-
- **Custom Overlays**: Configurable opacity, glass effect, and noise texture
|
|
54
|
-
- **Smooth Animations**: Fade in/out animations for overlay and content with customizable duration
|
|
55
|
-
- **Accessible**: Full keyboard navigation, screen reader support, and focus management
|
|
56
|
-
- **Flexible Content**: Header, footer, and body sections with custom styling
|
|
57
|
-
- **Portal Rendering**: Renders outside normal DOM hierarchy for proper layering
|
|
58
|
-
- **Focus Management**: Automatic focus trapping and restoration
|
|
59
|
-
- **Responsive Design**: Adapts to different screen sizes with mobile-first approach
|
|
60
|
-
- **Drag Support**: Built-in drag gestures for intuitive interaction
|
|
61
|
-
- **Nested Support**: Support for nested drawers with proper z-index management
|
|
62
|
-
|
|
63
|
-
## Directions
|
|
64
|
-
|
|
65
|
-
The drawer can slide from different directions using the \`direction\` prop:
|
|
66
|
-
|
|
67
|
-
- **Bottom** (default): Slides up from the bottom - ideal for mobile navigation
|
|
68
|
-
- **Top**: Slides down from the top - useful for notifications or quick actions
|
|
69
|
-
- **Left**: Slides in from the left - perfect for navigation menus
|
|
70
|
-
- **Right**: Slides in from the right - great for settings or detail panels
|
|
71
|
-
|
|
72
|
-
## Usage Examples
|
|
73
|
-
|
|
74
|
-
### Basic Drawer with Direction Configuration
|
|
75
|
-
\`\`\`tsx
|
|
76
|
-
import { Drawer, DrawerContent, DrawerTrigger } from '@/components/drawer'
|
|
77
|
-
|
|
78
|
-
// Bottom drawer (default)
|
|
79
|
-
<Drawer>
|
|
80
|
-
<DrawerTrigger asChild>
|
|
81
|
-
<Button>Open Bottom Drawer</Button>
|
|
82
|
-
</DrawerTrigger>
|
|
83
|
-
<DrawerContent>
|
|
84
|
-
Content slides up from bottom
|
|
85
|
-
</DrawerContent>
|
|
86
|
-
</Drawer>
|
|
87
|
-
|
|
88
|
-
// Top drawer
|
|
89
|
-
<Drawer>
|
|
90
|
-
<DrawerTrigger asChild>
|
|
91
|
-
<Button>Open Top Drawer</Button>
|
|
92
|
-
</DrawerTrigger>
|
|
93
|
-
<DrawerContent>
|
|
94
|
-
Content slides down from top
|
|
95
|
-
</DrawerContent>
|
|
96
|
-
</Drawer>
|
|
97
|
-
|
|
98
|
-
// Left drawer
|
|
99
|
-
<Drawer>
|
|
100
|
-
<DrawerTrigger asChild>
|
|
101
|
-
<Button>Open Left Drawer</Button>
|
|
102
|
-
</DrawerTrigger>
|
|
103
|
-
<DrawerContent>
|
|
104
|
-
Content slides in from left
|
|
105
|
-
</DrawerContent>
|
|
106
|
-
</Drawer>
|
|
107
|
-
|
|
108
|
-
// Right drawer
|
|
109
|
-
<Drawer>
|
|
110
|
-
<DrawerTrigger asChild>
|
|
111
|
-
<Button>Open Right Drawer</Button>
|
|
112
|
-
</DrawerTrigger>
|
|
113
|
-
<DrawerContent>
|
|
114
|
-
Content slides in from right
|
|
115
|
-
</DrawerContent>
|
|
116
|
-
</Drawer>
|
|
117
|
-
|
|
118
|
-
### Drawer with Custom Overlay Effects
|
|
119
|
-
\`\`\`tsx
|
|
120
|
-
<Drawer>
|
|
121
|
-
<DrawerTrigger asChild>
|
|
122
|
-
<Button>Open Drawer with Custom Overlay</Button>
|
|
123
|
-
</DrawerTrigger>
|
|
124
|
-
<DrawerContent
|
|
125
|
-
noise="high"
|
|
126
|
-
opacity="medium"
|
|
127
|
-
glass="low"
|
|
128
|
-
>
|
|
129
|
-
Content with custom overlay effects
|
|
130
|
-
</DrawerContent>
|
|
131
|
-
</Drawer>
|
|
132
|
-
\`\`\`
|
|
133
|
-
|
|
134
|
-
### Overlay Configuration
|
|
135
|
-
|
|
136
|
-
The drawer supports configurable overlay effects through the \`opacity\`, \`glass\`, and \`noise\` props:
|
|
137
|
-
|
|
138
|
-
- **opacity**: Controls background dimming level
|
|
139
|
-
- \`"high"\` - Strong dimming (80%)
|
|
140
|
-
- \`"medium"\` - Balanced dimming (60%) - default
|
|
141
|
-
- \`"low"\` - Subtle dimming (40%)
|
|
142
|
-
- \`"none"\` - No dimming (100% coverage)
|
|
143
|
-
|
|
144
|
-
- **glass**: Controls backdrop blur effect
|
|
145
|
-
- \`"high"\` - Strong blur effect
|
|
146
|
-
- \`"medium"\` - Balanced blur effect
|
|
147
|
-
- \`"low"\` - Subtle blur effect - default
|
|
148
|
-
- \`"none"\` - No blur effect
|
|
149
|
-
|
|
150
|
-
- **noise**: Controls texture overlay
|
|
151
|
-
- \`"high"\` - Strong texture pattern
|
|
152
|
-
- \`"medium"\` - Balanced texture pattern
|
|
153
|
-
- \`"low"\` - Subtle texture pattern - default
|
|
154
|
-
- \`"none"\` - No texture pattern
|
|
155
|
-
|
|
156
|
-
### Usage Examples
|
|
157
|
-
|
|
158
|
-
\`\`\`tsx
|
|
159
|
-
// High opacity with glass effect
|
|
160
|
-
<DrawerContent opacity="high" glass="medium" noise="low">
|
|
161
|
-
Content with strong background dimming
|
|
162
|
-
</DrawerContent>
|
|
163
|
-
|
|
164
|
-
// Subtle overlay with texture
|
|
165
|
-
<DrawerContent opacity="low" glass="none" noise="high">
|
|
166
|
-
Content with subtle dimming and strong texture
|
|
167
|
-
</DrawerContent>
|
|
168
|
-
|
|
169
|
-
// No overlay effects
|
|
170
|
-
<DrawerContent opacity="none" glass="none" noise="none">
|
|
171
|
-
Content without any overlay effects
|
|
172
|
-
</DrawerContent>
|
|
173
|
-
\`\`\`
|
|
174
|
-
\`\`\`
|
|
175
|
-
|
|
176
|
-
### Drawer with Form Elements
|
|
177
|
-
\`\`\`tsx
|
|
178
|
-
<Drawer>
|
|
179
|
-
<DrawerTrigger asChild>
|
|
180
|
-
<Button>Open Form Drawer</Button>
|
|
181
|
-
</DrawerTrigger>
|
|
182
|
-
<DrawerContent>
|
|
183
|
-
<DrawerHeader>
|
|
184
|
-
<DrawerTitle>Contact Form</DrawerTitle>
|
|
185
|
-
<DrawerDescription>Fill out the form below to get in touch.</DrawerDescription>
|
|
186
|
-
</DrawerHeader>
|
|
187
|
-
<div className="space-y-4 p-4">
|
|
188
|
-
<Input placeholder="Name" />
|
|
189
|
-
<Input placeholder="Email" type="email" />
|
|
190
|
-
<Textarea placeholder="Message" rows={4} />
|
|
191
|
-
</div>
|
|
192
|
-
<DrawerFooter>
|
|
193
|
-
<Button>Submit</Button>
|
|
194
|
-
<DrawerClose asChild>
|
|
195
|
-
<Button variant="outline">Cancel</Button>
|
|
196
|
-
</DrawerClose>
|
|
197
|
-
</DrawerFooter>
|
|
198
|
-
</DrawerContent>
|
|
199
|
-
</Drawer>
|
|
200
|
-
\`\`\`
|
|
201
|
-
`,
|
|
36
|
+
component:
|
|
37
|
+
"A slide-out drawer built on Vaul primitives. Supports four slide directions, neutral and gradient variants, configurable glass/noise overlays, an optional swipe handle, and an optional backdrop overlay — ideal for mobile navigation, settings panels, and contextual actions.",
|
|
202
38
|
},
|
|
39
|
+
page: () => (
|
|
40
|
+
<AuralComponentDocsPage
|
|
41
|
+
features={[
|
|
42
|
+
{
|
|
43
|
+
title: "4 Slide Directions",
|
|
44
|
+
description: "Top, bottom, left, right",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: "Glass & Noise Overlay",
|
|
48
|
+
description: "Blur and grain levels",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
title: "Swipe Handle",
|
|
52
|
+
description: "Optional pill indicator",
|
|
53
|
+
},
|
|
54
|
+
]}
|
|
55
|
+
/>
|
|
56
|
+
),
|
|
203
57
|
},
|
|
204
58
|
},
|
|
205
59
|
argTypes: {
|
|
206
60
|
variant: {
|
|
207
61
|
control: { type: "select" },
|
|
208
62
|
options: ["neutral", "gradient"],
|
|
209
|
-
description: "
|
|
63
|
+
description: "Visual style variant",
|
|
210
64
|
},
|
|
211
65
|
showOverlay: {
|
|
212
66
|
control: { type: "boolean" },
|
|
213
|
-
description: "Whether to
|
|
67
|
+
description: "Whether to render the backdrop overlay",
|
|
214
68
|
},
|
|
215
69
|
showSwipeButton: {
|
|
216
70
|
control: { type: "boolean" },
|
|
217
|
-
description: "
|
|
71
|
+
description: "Show swipe indicator handle (bottom drawers only)",
|
|
218
72
|
},
|
|
219
73
|
opacity: {
|
|
220
74
|
control: { type: "select" },
|
|
@@ -224,12 +78,12 @@ The drawer supports configurable overlay effects through the \`opacity\`, \`glas
|
|
|
224
78
|
glass: {
|
|
225
79
|
control: { type: "select" },
|
|
226
80
|
options: ["high", "medium", "low", "none"],
|
|
227
|
-
description: "Overlay glass
|
|
81
|
+
description: "Overlay glass blur intensity",
|
|
228
82
|
},
|
|
229
83
|
noise: {
|
|
230
84
|
control: { type: "select" },
|
|
231
85
|
options: ["high", "medium", "low", "none"],
|
|
232
|
-
description: "Overlay noise texture
|
|
86
|
+
description: "Overlay noise texture intensity",
|
|
233
87
|
},
|
|
234
88
|
},
|
|
235
89
|
tags: ["autodocs"],
|
|
@@ -238,33 +92,28 @@ The drawer supports configurable overlay effects through the \`opacity\`, \`glas
|
|
|
238
92
|
export default meta
|
|
239
93
|
type Story = StoryObj<typeof Drawer>
|
|
240
94
|
|
|
241
|
-
//
|
|
242
|
-
|
|
95
|
+
// ─── Configurations ────────────────────────────────────────────────────────────
|
|
96
|
+
|
|
97
|
+
export const Configurations: Story = {
|
|
243
98
|
render: () => {
|
|
244
|
-
const
|
|
245
|
-
|
|
99
|
+
const DirDrawer = ({ direction, label, description }: any) => (
|
|
100
|
+
<div className="space-y-2 text-center">
|
|
246
101
|
<Drawer direction={direction}>
|
|
247
102
|
<DrawerTrigger asChild>
|
|
248
103
|
<Button variant="outline" size="sm">
|
|
249
|
-
{
|
|
104
|
+
{label}
|
|
250
105
|
</Button>
|
|
251
106
|
</DrawerTrigger>
|
|
252
107
|
<DrawerContent>
|
|
253
108
|
<DrawerHeader>
|
|
254
|
-
<DrawerTitle>{
|
|
109
|
+
<DrawerTitle>{label} Drawer</DrawerTitle>
|
|
255
110
|
<DrawerDescription>{description}</DrawerDescription>
|
|
256
111
|
</DrawerHeader>
|
|
257
|
-
<div className="p-
|
|
258
|
-
<div className="rounded-lg border
|
|
259
|
-
<
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
</div>
|
|
263
|
-
<div>
|
|
264
|
-
Content:{" "}
|
|
265
|
-
<span className="text-white">Slides from {direction}</span>
|
|
266
|
-
</div>
|
|
267
|
-
</div>
|
|
112
|
+
<div className="p-4">
|
|
113
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
114
|
+
<code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
|
|
115
|
+
direction="{direction}"
|
|
116
|
+
</code>
|
|
268
117
|
</div>
|
|
269
118
|
</div>
|
|
270
119
|
<DrawerFooter>
|
|
@@ -274,73 +123,202 @@ export const DirectionExamples: Story = {
|
|
|
274
123
|
</DrawerFooter>
|
|
275
124
|
</DrawerContent>
|
|
276
125
|
</Drawer>
|
|
277
|
-
|
|
278
|
-
|
|
126
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
127
|
+
{label}
|
|
128
|
+
</p>
|
|
129
|
+
</div>
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
const OverlayDrawer = ({ label, opacity, glass, noise }: any) => (
|
|
133
|
+
<div className="space-y-2 text-center">
|
|
134
|
+
<Drawer direction="bottom">
|
|
135
|
+
<DrawerTrigger asChild>
|
|
136
|
+
<Button variant="outline" size="sm">
|
|
137
|
+
{label}
|
|
138
|
+
</Button>
|
|
139
|
+
</DrawerTrigger>
|
|
140
|
+
<DrawerContent opacity={opacity} glass={glass} noise={noise}>
|
|
141
|
+
<DrawerHeader>
|
|
142
|
+
<DrawerTitle>{label}</DrawerTitle>
|
|
143
|
+
<DrawerDescription>Overlay configuration demo.</DrawerDescription>
|
|
144
|
+
</DrawerHeader>
|
|
145
|
+
<div className="p-4">
|
|
146
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
147
|
+
<code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
|
|
148
|
+
{opacity ? `opacity="${opacity}"` : ""}
|
|
149
|
+
{glass ? ` glass="${glass}"` : ""}
|
|
150
|
+
{noise ? ` noise="${noise}"` : ""}
|
|
151
|
+
</code>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
<DrawerFooter>
|
|
155
|
+
<DrawerClose asChild>
|
|
156
|
+
<Button>Close</Button>
|
|
157
|
+
</DrawerClose>
|
|
158
|
+
</DrawerFooter>
|
|
159
|
+
</DrawerContent>
|
|
160
|
+
</Drawer>
|
|
161
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
162
|
+
{label}
|
|
163
|
+
</p>
|
|
164
|
+
</div>
|
|
165
|
+
)
|
|
279
166
|
|
|
280
167
|
return (
|
|
281
168
|
<div className="space-y-8">
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
<
|
|
285
|
-
|
|
286
|
-
</
|
|
169
|
+
{/* All four directions */}
|
|
170
|
+
<div className="space-y-3">
|
|
171
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
172
|
+
Slide Directions
|
|
173
|
+
</h4>
|
|
174
|
+
<div className="flex flex-wrap gap-6">
|
|
175
|
+
<DirDrawer
|
|
176
|
+
direction="bottom"
|
|
177
|
+
label="Bottom"
|
|
178
|
+
description="Slides up from the bottom — default for mobile."
|
|
179
|
+
/>
|
|
180
|
+
<DirDrawer
|
|
181
|
+
direction="top"
|
|
182
|
+
label="Top"
|
|
183
|
+
description="Slides down from the top — ideal for notifications."
|
|
184
|
+
/>
|
|
185
|
+
<DirDrawer
|
|
186
|
+
direction="left"
|
|
187
|
+
label="Left"
|
|
188
|
+
description="Slides in from the left — navigation menus."
|
|
189
|
+
/>
|
|
190
|
+
<DirDrawer
|
|
191
|
+
direction="right"
|
|
192
|
+
label="Right"
|
|
193
|
+
description="Slides in from the right — settings panels."
|
|
194
|
+
/>
|
|
195
|
+
</div>
|
|
287
196
|
</div>
|
|
288
197
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
<
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
<div className="
|
|
296
|
-
<
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
198
|
+
{/* Variant styles */}
|
|
199
|
+
<div className="space-y-3">
|
|
200
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
201
|
+
Variant Styles
|
|
202
|
+
</h4>
|
|
203
|
+
<div className="flex flex-wrap gap-6">
|
|
204
|
+
<div className="space-y-2 text-center">
|
|
205
|
+
<Drawer direction="bottom">
|
|
206
|
+
<DrawerTrigger asChild>
|
|
207
|
+
<Button variant="outline" size="sm">
|
|
208
|
+
Neutral
|
|
209
|
+
</Button>
|
|
210
|
+
</DrawerTrigger>
|
|
211
|
+
<DrawerContent variant="neutral">
|
|
212
|
+
<DrawerHeader>
|
|
213
|
+
<DrawerTitle>Neutral Variant</DrawerTitle>
|
|
214
|
+
<DrawerDescription>
|
|
215
|
+
Frosted glass surface with backdrop blur.
|
|
216
|
+
</DrawerDescription>
|
|
217
|
+
</DrawerHeader>
|
|
218
|
+
<DrawerFooter>
|
|
219
|
+
<DrawerClose asChild>
|
|
220
|
+
<Button>Close</Button>
|
|
221
|
+
</DrawerClose>
|
|
222
|
+
</DrawerFooter>
|
|
223
|
+
</DrawerContent>
|
|
224
|
+
</Drawer>
|
|
225
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
226
|
+
Neutral
|
|
227
|
+
</p>
|
|
301
228
|
</div>
|
|
302
|
-
</div>
|
|
303
229
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
230
|
+
<div className="space-y-2 text-center">
|
|
231
|
+
<Drawer direction="bottom">
|
|
232
|
+
<DrawerTrigger asChild>
|
|
233
|
+
<Button variant="outline" size="sm">
|
|
234
|
+
Gradient
|
|
235
|
+
</Button>
|
|
236
|
+
</DrawerTrigger>
|
|
237
|
+
<DrawerContent variant="gradient">
|
|
238
|
+
<DrawerHeader>
|
|
239
|
+
<DrawerTitle>Gradient Variant</DrawerTitle>
|
|
240
|
+
<DrawerDescription>
|
|
241
|
+
Surface primary with a white gradient overlay.
|
|
242
|
+
</DrawerDescription>
|
|
243
|
+
</DrawerHeader>
|
|
244
|
+
<DrawerFooter>
|
|
245
|
+
<DrawerClose asChild>
|
|
246
|
+
<Button>Close</Button>
|
|
247
|
+
</DrawerClose>
|
|
248
|
+
</DrawerFooter>
|
|
249
|
+
</DrawerContent>
|
|
250
|
+
</Drawer>
|
|
251
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
252
|
+
Gradient
|
|
253
|
+
</p>
|
|
313
254
|
</div>
|
|
314
|
-
</div>
|
|
315
255
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
256
|
+
<div className="space-y-2 text-center">
|
|
257
|
+
<Drawer direction="bottom">
|
|
258
|
+
<DrawerTrigger asChild>
|
|
259
|
+
<Button variant="outline" size="sm">
|
|
260
|
+
Swipe handle
|
|
261
|
+
</Button>
|
|
262
|
+
</DrawerTrigger>
|
|
263
|
+
<DrawerContent showSwipeButton>
|
|
264
|
+
<DrawerHeader>
|
|
265
|
+
<DrawerTitle>Swipe Handle</DrawerTitle>
|
|
266
|
+
<DrawerDescription>
|
|
267
|
+
Pill handle appears at the top of bottom drawers.
|
|
268
|
+
</DrawerDescription>
|
|
269
|
+
</DrawerHeader>
|
|
270
|
+
<DrawerFooter>
|
|
271
|
+
<DrawerClose asChild>
|
|
272
|
+
<Button>Close</Button>
|
|
273
|
+
</DrawerClose>
|
|
274
|
+
</DrawerFooter>
|
|
275
|
+
</DrawerContent>
|
|
276
|
+
</Drawer>
|
|
277
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
278
|
+
Swipe button
|
|
279
|
+
</p>
|
|
327
280
|
</div>
|
|
328
|
-
</div>
|
|
329
281
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
282
|
+
<div className="space-y-2 text-center">
|
|
283
|
+
<Drawer direction="bottom">
|
|
284
|
+
<DrawerTrigger asChild>
|
|
285
|
+
<Button variant="outline" size="sm">
|
|
286
|
+
No overlay
|
|
287
|
+
</Button>
|
|
288
|
+
</DrawerTrigger>
|
|
289
|
+
<DrawerContent showOverlay={false}>
|
|
290
|
+
<DrawerHeader>
|
|
291
|
+
<DrawerTitle>No Overlay</DrawerTitle>
|
|
292
|
+
<DrawerDescription>
|
|
293
|
+
Drawer without the backdrop overlay.
|
|
294
|
+
</DrawerDescription>
|
|
295
|
+
</DrawerHeader>
|
|
296
|
+
<DrawerFooter>
|
|
297
|
+
<DrawerClose asChild>
|
|
298
|
+
<Button>Close</Button>
|
|
299
|
+
</DrawerClose>
|
|
300
|
+
</DrawerFooter>
|
|
301
|
+
</DrawerContent>
|
|
302
|
+
</Drawer>
|
|
303
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
304
|
+
No overlay
|
|
305
|
+
</p>
|
|
341
306
|
</div>
|
|
342
307
|
</div>
|
|
343
308
|
</div>
|
|
309
|
+
|
|
310
|
+
{/* Glass / noise options */}
|
|
311
|
+
<div className="space-y-3">
|
|
312
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
313
|
+
Glass & Noise Overlay Options
|
|
314
|
+
</h4>
|
|
315
|
+
<div className="flex flex-wrap gap-6">
|
|
316
|
+
<OverlayDrawer label="Low opacity" opacity="low" />
|
|
317
|
+
<OverlayDrawer label="High opacity" opacity="high" />
|
|
318
|
+
<OverlayDrawer label="High glass" glass="high" />
|
|
319
|
+
<OverlayDrawer label="Noise texture" noise="medium" />
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
344
322
|
</div>
|
|
345
323
|
)
|
|
346
324
|
},
|
|
@@ -348,597 +326,456 @@ export const DirectionExamples: Story = {
|
|
|
348
326
|
docs: {
|
|
349
327
|
description: {
|
|
350
328
|
story:
|
|
351
|
-
"
|
|
329
|
+
"Comparison of all four slide directions, both visual variants, swipe handle, overlay toggle, and glass/noise overlay options.",
|
|
352
330
|
},
|
|
353
331
|
},
|
|
354
332
|
},
|
|
355
333
|
}
|
|
356
334
|
|
|
357
|
-
//
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
<Drawer>
|
|
361
|
-
<DrawerTrigger asChild>
|
|
362
|
-
<Button>Open Drawer</Button>
|
|
363
|
-
</DrawerTrigger>
|
|
364
|
-
<DrawerContent>
|
|
365
|
-
<DrawerHeader>
|
|
366
|
-
<DrawerTitle>Basic Drawer</DrawerTitle>
|
|
367
|
-
<DrawerDescription>
|
|
368
|
-
This is a basic drawer example with header, content, and footer.
|
|
369
|
-
</DrawerDescription>
|
|
370
|
-
</DrawerHeader>
|
|
371
|
-
<p className="p-4 text-sm">
|
|
372
|
-
This is the main content area of the drawer. You can put any content
|
|
373
|
-
here.
|
|
374
|
-
</p>
|
|
375
|
-
<DrawerFooter>
|
|
376
|
-
<Button>Save Changes</Button>
|
|
377
|
-
<DrawerClose asChild>
|
|
378
|
-
<Button variant="outline">Cancel</Button>
|
|
379
|
-
</DrawerClose>
|
|
380
|
-
</DrawerFooter>
|
|
381
|
-
</DrawerContent>
|
|
382
|
-
</Drawer>
|
|
383
|
-
),
|
|
384
|
-
parameters: {
|
|
385
|
-
docs: {
|
|
386
|
-
description: {
|
|
387
|
-
story:
|
|
388
|
-
"Basic drawer example demonstrating the fundamental structure with header, content, and footer sections.",
|
|
389
|
-
},
|
|
390
|
-
},
|
|
391
|
-
},
|
|
392
|
-
}
|
|
393
|
-
// 2. Form Drawer with Select Components
|
|
394
|
-
export const FormDrawer: Story = {
|
|
335
|
+
// ─── Interactive ───────────────────────────────────────────────────────────────
|
|
336
|
+
|
|
337
|
+
export const Interactive: Story = {
|
|
395
338
|
render: () => {
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
339
|
+
const InteractiveDemo = () => {
|
|
340
|
+
const [direction, setDirection] = useState<
|
|
341
|
+
"top" | "bottom" | "left" | "right"
|
|
342
|
+
>("bottom")
|
|
343
|
+
const [variant, setVariant] = useState<"neutral" | "gradient">("neutral")
|
|
344
|
+
const [opacity, setOpacity] = useState<
|
|
345
|
+
"high" | "medium" | "low" | "none"
|
|
346
|
+
>("medium")
|
|
347
|
+
const [glass, setGlass] = useState<"high" | "medium" | "low" | "none">(
|
|
348
|
+
"none"
|
|
349
|
+
)
|
|
350
|
+
const [noise, setNoise] = useState<"high" | "medium" | "low" | "none">(
|
|
351
|
+
"none"
|
|
352
|
+
)
|
|
353
|
+
const [showSwipeButton, setShowSwipeButton] = useState(false)
|
|
354
|
+
const [name, setName] = useState("")
|
|
355
|
+
const [email, setEmail] = useState("")
|
|
356
|
+
const [submitted, setSubmitted] = useState(false)
|
|
357
|
+
|
|
358
|
+
const directions = ["bottom", "top", "left", "right"] as const
|
|
359
|
+
const variants = ["neutral", "gradient"] as const
|
|
360
|
+
const levels = ["none", "low", "medium", "high"] as const
|
|
361
|
+
|
|
362
|
+
const btnCls = (active: boolean) =>
|
|
363
|
+
`font-fm-text text-fm-sm leading-fm-sm rounded px-2 py-1 outline-none transition-colors ${
|
|
364
|
+
active
|
|
365
|
+
? "bg-fm-surface-contrast text-fm-contrast"
|
|
366
|
+
: "bg-fm-surface-secondary text-fm-secondary hover:text-fm-primary"
|
|
367
|
+
}`
|
|
404
368
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
369
|
+
return (
|
|
370
|
+
<div className="w-full p-8">
|
|
371
|
+
<div className="mx-auto max-w-3xl space-y-6">
|
|
372
|
+
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
|
373
|
+
{/* Controls panel */}
|
|
374
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-5 rounded-xl border p-5">
|
|
375
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
|
|
376
|
+
Configuration
|
|
377
|
+
</p>
|
|
378
|
+
|
|
379
|
+
<div className="space-y-2">
|
|
380
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
381
|
+
Direction
|
|
382
|
+
</p>
|
|
383
|
+
<div className="flex flex-wrap gap-1">
|
|
384
|
+
{directions.map((d) => (
|
|
385
|
+
<button
|
|
386
|
+
key={d}
|
|
387
|
+
onClick={() => setDirection(d)}
|
|
388
|
+
className={btnCls(direction === d)}
|
|
389
|
+
>
|
|
390
|
+
{d}
|
|
391
|
+
</button>
|
|
392
|
+
))}
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
409
395
|
|
|
410
|
-
|
|
411
|
-
<Drawer>
|
|
412
|
-
<DrawerTrigger asChild>
|
|
413
|
-
<Button className="gap-2">
|
|
414
|
-
<EditBigIcon className="h-4 w-4" />
|
|
415
|
-
Contact Form
|
|
416
|
-
</Button>
|
|
417
|
-
</DrawerTrigger>
|
|
418
|
-
<DrawerContent>
|
|
419
|
-
<DrawerHeader>
|
|
420
|
-
<DrawerTitle>Contact Form</DrawerTitle>
|
|
421
|
-
<DrawerDescription>
|
|
422
|
-
Fill out the form below to get in touch with us.
|
|
423
|
-
</DrawerDescription>
|
|
424
|
-
</DrawerHeader>
|
|
425
|
-
<form onSubmit={handleSubmit} className="space-y-4 overflow-auto p-4">
|
|
426
|
-
<div className="space-y-2">
|
|
427
|
-
<Label htmlFor="name">Name</Label>
|
|
428
|
-
<Input
|
|
429
|
-
id="name"
|
|
430
|
-
value={formData.name}
|
|
431
|
-
onChange={(e) =>
|
|
432
|
-
setFormData({ ...formData, name: e.target.value })
|
|
433
|
-
}
|
|
434
|
-
placeholder="Enter your name"
|
|
435
|
-
/>
|
|
436
|
-
</div>
|
|
437
|
-
<div className="space-y-2">
|
|
438
|
-
<Label htmlFor="email">Email</Label>
|
|
439
|
-
<Input
|
|
440
|
-
id="email"
|
|
441
|
-
type="email"
|
|
442
|
-
value={formData.email}
|
|
443
|
-
onChange={(e) =>
|
|
444
|
-
setFormData({ ...formData, email: e.target.value })
|
|
445
|
-
}
|
|
446
|
-
placeholder="Enter your email"
|
|
447
|
-
/>
|
|
448
|
-
</div>
|
|
449
|
-
<div className="space-y-2">
|
|
450
|
-
<Label htmlFor="category">Category</Label>
|
|
451
|
-
<Select
|
|
452
|
-
value={formData.category}
|
|
453
|
-
onValueChange={(value) =>
|
|
454
|
-
setFormData({ ...formData, category: value })
|
|
455
|
-
}
|
|
456
|
-
>
|
|
457
|
-
<SelectTrigger>
|
|
458
|
-
<SelectValue placeholder="Select a category" />
|
|
459
|
-
</SelectTrigger>
|
|
460
|
-
<SelectContent>
|
|
461
|
-
<SelectItem value="general">General Inquiry</SelectItem>
|
|
462
|
-
<SelectItem value="support">Technical Support</SelectItem>
|
|
463
|
-
<SelectItem value="sales">Sales Question</SelectItem>
|
|
464
|
-
<SelectItem value="feedback">Feedback</SelectItem>
|
|
465
|
-
</SelectContent>
|
|
466
|
-
</Select>
|
|
467
|
-
</div>
|
|
468
|
-
<div className="space-y-2">
|
|
469
|
-
<Label htmlFor="priority">Priority</Label>
|
|
470
|
-
<Select
|
|
471
|
-
value={formData.priority}
|
|
472
|
-
onValueChange={(value) =>
|
|
473
|
-
setFormData({ ...formData, priority: value })
|
|
474
|
-
}
|
|
475
|
-
>
|
|
476
|
-
<SelectTrigger>
|
|
477
|
-
<SelectValue placeholder="Select priority level" />
|
|
478
|
-
</SelectTrigger>
|
|
479
|
-
<SelectContent>
|
|
480
|
-
<SelectItem value="low">Low</SelectItem>
|
|
481
|
-
<SelectItem value="medium">Medium</SelectItem>
|
|
482
|
-
<SelectItem value="high">High</SelectItem>
|
|
483
|
-
<SelectItem value="urgent">Urgent</SelectItem>
|
|
484
|
-
</SelectContent>
|
|
485
|
-
</Select>
|
|
486
|
-
</div>
|
|
487
|
-
<div className="space-y-2">
|
|
488
|
-
<Label htmlFor="message">Message</Label>
|
|
489
|
-
<Textarea
|
|
490
|
-
id="message"
|
|
491
|
-
value={formData.message}
|
|
492
|
-
onChange={(e) =>
|
|
493
|
-
setFormData({ ...formData, message: e.target.value })
|
|
494
|
-
}
|
|
495
|
-
placeholder="Enter your message"
|
|
496
|
-
rows={4}
|
|
497
|
-
/>
|
|
498
|
-
</div>
|
|
499
|
-
<div className="flex items-center space-x-2">
|
|
500
|
-
<Checkbox
|
|
501
|
-
id="newsletter"
|
|
502
|
-
checked={formData.newsletter}
|
|
503
|
-
onCheckedChange={(checked) =>
|
|
504
|
-
setFormData({ ...formData, newsletter: !!checked })
|
|
505
|
-
}
|
|
506
|
-
/>
|
|
507
|
-
<Label htmlFor="newsletter" className="text-sm">
|
|
508
|
-
Subscribe to newsletter
|
|
509
|
-
</Label>
|
|
510
|
-
</div>
|
|
511
|
-
</form>
|
|
512
|
-
<DrawerFooter>
|
|
513
|
-
<Button
|
|
514
|
-
disabled={!formData.name || !formData.email || !formData.message}
|
|
515
|
-
onClick={handleSubmit}
|
|
516
|
-
>
|
|
517
|
-
Submit
|
|
518
|
-
</Button>
|
|
519
|
-
<DrawerClose asChild>
|
|
520
|
-
<Button variant="outline">Cancel</Button>
|
|
521
|
-
</DrawerClose>
|
|
522
|
-
</DrawerFooter>
|
|
523
|
-
</DrawerContent>
|
|
524
|
-
</Drawer>
|
|
525
|
-
)
|
|
526
|
-
},
|
|
527
|
-
parameters: {
|
|
528
|
-
docs: {
|
|
529
|
-
description: {
|
|
530
|
-
story:
|
|
531
|
-
"Form drawer with select components instead of native select tags, demonstrating proper form handling and validation.",
|
|
532
|
-
},
|
|
533
|
-
},
|
|
534
|
-
},
|
|
535
|
-
}
|
|
396
|
+
<div className="border-fm-divider-secondary border-t pt-4" />
|
|
536
397
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
398
|
+
<div className="space-y-2">
|
|
399
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
400
|
+
Variant
|
|
401
|
+
</p>
|
|
402
|
+
<div className="flex flex-wrap gap-1">
|
|
403
|
+
{variants.map((v) => (
|
|
404
|
+
<button
|
|
405
|
+
key={v}
|
|
406
|
+
onClick={() => setVariant(v)}
|
|
407
|
+
className={btnCls(variant === v)}
|
|
408
|
+
>
|
|
409
|
+
{v}
|
|
410
|
+
</button>
|
|
411
|
+
))}
|
|
412
|
+
</div>
|
|
413
|
+
</div>
|
|
546
414
|
|
|
547
|
-
|
|
548
|
-
<Drawer>
|
|
549
|
-
<DrawerTrigger asChild>
|
|
550
|
-
<Button>Open Settings</Button>
|
|
551
|
-
</DrawerTrigger>
|
|
552
|
-
<DrawerContent>
|
|
553
|
-
<DrawerHeader>
|
|
554
|
-
<DrawerTitle>Settings</DrawerTitle>
|
|
555
|
-
<DrawerDescription>
|
|
556
|
-
Configure your application preferences.
|
|
557
|
-
</DrawerDescription>
|
|
558
|
-
</DrawerHeader>
|
|
559
|
-
<div className="space-y-6 overflow-auto p-4">
|
|
560
|
-
<div className="space-y-4">
|
|
561
|
-
<h3 className="text-sm font-medium">Appearance</h3>
|
|
562
|
-
<div className="space-y-2">
|
|
563
|
-
<Label htmlFor="theme">Theme</Label>
|
|
564
|
-
<Select
|
|
565
|
-
value={settings.theme}
|
|
566
|
-
onValueChange={(value) =>
|
|
567
|
-
setSettings({ ...settings, theme: value })
|
|
568
|
-
}
|
|
569
|
-
>
|
|
570
|
-
<SelectTrigger>
|
|
571
|
-
<SelectValue />
|
|
572
|
-
</SelectTrigger>
|
|
573
|
-
<SelectContent>
|
|
574
|
-
<SelectItem value="light">Light</SelectItem>
|
|
575
|
-
<SelectItem value="dark">Dark</SelectItem>
|
|
576
|
-
<SelectItem value="system">System</SelectItem>
|
|
577
|
-
</SelectContent>
|
|
578
|
-
</Select>
|
|
579
|
-
</div>
|
|
580
|
-
</div>
|
|
581
|
-
<div className="space-y-4">
|
|
582
|
-
<h3 className="text-sm font-medium">Notifications</h3>
|
|
583
|
-
<div className="space-y-2">
|
|
584
|
-
<Label htmlFor="notifications">Email Notifications</Label>
|
|
585
|
-
<Select
|
|
586
|
-
value={settings.notifications}
|
|
587
|
-
onValueChange={(value) =>
|
|
588
|
-
setSettings({ ...settings, notifications: value })
|
|
589
|
-
}
|
|
590
|
-
>
|
|
591
|
-
<SelectTrigger>
|
|
592
|
-
<SelectValue />
|
|
593
|
-
</SelectTrigger>
|
|
594
|
-
<SelectContent>
|
|
595
|
-
<SelectItem value="all">All notifications</SelectItem>
|
|
596
|
-
<SelectItem value="important">Important only</SelectItem>
|
|
597
|
-
<SelectItem value="none">None</SelectItem>
|
|
598
|
-
</SelectContent>
|
|
599
|
-
</Select>
|
|
600
|
-
</div>
|
|
601
|
-
</div>
|
|
602
|
-
<div className="space-y-4">
|
|
603
|
-
<h3 className="text-sm font-medium">Regional</h3>
|
|
604
|
-
<div className="space-y-2">
|
|
605
|
-
<Label htmlFor="language">Language</Label>
|
|
606
|
-
<Select
|
|
607
|
-
value={settings.language}
|
|
608
|
-
onValueChange={(value) =>
|
|
609
|
-
setSettings({ ...settings, language: value })
|
|
610
|
-
}
|
|
611
|
-
>
|
|
612
|
-
<SelectTrigger>
|
|
613
|
-
<SelectValue />
|
|
614
|
-
</SelectTrigger>
|
|
615
|
-
<SelectContent>
|
|
616
|
-
<SelectItem value="en">English</SelectItem>
|
|
617
|
-
<SelectItem value="es">Spanish</SelectItem>
|
|
618
|
-
<SelectItem value="fr">French</SelectItem>
|
|
619
|
-
<SelectItem value="de">German</SelectItem>
|
|
620
|
-
</SelectContent>
|
|
621
|
-
</Select>
|
|
622
|
-
</div>
|
|
623
|
-
<div className="space-y-2">
|
|
624
|
-
<Label htmlFor="timezone">Timezone</Label>
|
|
625
|
-
<Select
|
|
626
|
-
value={settings.timezone}
|
|
627
|
-
onValueChange={(value) =>
|
|
628
|
-
setSettings({ ...settings, timezone: value })
|
|
629
|
-
}
|
|
630
|
-
>
|
|
631
|
-
<SelectTrigger>
|
|
632
|
-
<SelectValue />
|
|
633
|
-
</SelectTrigger>
|
|
634
|
-
<SelectContent>
|
|
635
|
-
<SelectItem value="utc">UTC</SelectItem>
|
|
636
|
-
<SelectItem value="est">Eastern Time</SelectItem>
|
|
637
|
-
<SelectItem value="pst">Pacific Time</SelectItem>
|
|
638
|
-
<SelectItem value="gmt">GMT</SelectItem>
|
|
639
|
-
</SelectContent>
|
|
640
|
-
</Select>
|
|
641
|
-
</div>
|
|
642
|
-
</div>
|
|
643
|
-
</div>
|
|
644
|
-
<DrawerFooter>
|
|
645
|
-
<Button onClick={() => console.log("Settings saved:", settings)}>
|
|
646
|
-
Save Settings
|
|
647
|
-
</Button>
|
|
648
|
-
<DrawerClose asChild>
|
|
649
|
-
<Button variant="outline">Cancel</Button>
|
|
650
|
-
</DrawerClose>
|
|
651
|
-
</DrawerFooter>
|
|
652
|
-
</DrawerContent>
|
|
653
|
-
</Drawer>
|
|
654
|
-
)
|
|
655
|
-
},
|
|
656
|
-
parameters: {
|
|
657
|
-
docs: {
|
|
658
|
-
description: {
|
|
659
|
-
story:
|
|
660
|
-
"Settings drawer showcasing select components for configuration options with proper state management.",
|
|
661
|
-
},
|
|
662
|
-
},
|
|
663
|
-
},
|
|
664
|
-
}
|
|
415
|
+
<div className="border-fm-divider-secondary border-t pt-4" />
|
|
665
416
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
417
|
+
<div className="space-y-2">
|
|
418
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
419
|
+
Opacity
|
|
420
|
+
</p>
|
|
421
|
+
<div className="flex flex-wrap gap-1">
|
|
422
|
+
{levels.map((l) => (
|
|
423
|
+
<button
|
|
424
|
+
key={l}
|
|
425
|
+
onClick={() => setOpacity(l)}
|
|
426
|
+
className={btnCls(opacity === l)}
|
|
427
|
+
>
|
|
428
|
+
{l}
|
|
429
|
+
</button>
|
|
430
|
+
))}
|
|
431
|
+
</div>
|
|
432
|
+
</div>
|
|
670
433
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
<DrawerContent>
|
|
692
|
-
<DrawerHeader>
|
|
693
|
-
<DrawerTitle>Nested Drawer</DrawerTitle>
|
|
694
|
-
<DrawerDescription>
|
|
695
|
-
This is a nested drawer within the parent drawer.
|
|
696
|
-
</DrawerDescription>
|
|
697
|
-
</DrawerHeader>
|
|
698
|
-
<div className="p-4">
|
|
699
|
-
<p className="text-muted-foreground text-sm">
|
|
700
|
-
Nested drawer content goes here.
|
|
434
|
+
<div className="space-y-2">
|
|
435
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
436
|
+
Glass
|
|
437
|
+
</p>
|
|
438
|
+
<div className="flex flex-wrap gap-1">
|
|
439
|
+
{levels.map((l) => (
|
|
440
|
+
<button
|
|
441
|
+
key={l}
|
|
442
|
+
onClick={() => setGlass(l)}
|
|
443
|
+
className={btnCls(glass === l)}
|
|
444
|
+
>
|
|
445
|
+
{l}
|
|
446
|
+
</button>
|
|
447
|
+
))}
|
|
448
|
+
</div>
|
|
449
|
+
</div>
|
|
450
|
+
|
|
451
|
+
<div className="space-y-2">
|
|
452
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
453
|
+
Noise
|
|
701
454
|
</p>
|
|
455
|
+
<div className="flex flex-wrap gap-1">
|
|
456
|
+
{levels.map((l) => (
|
|
457
|
+
<button
|
|
458
|
+
key={l}
|
|
459
|
+
onClick={() => setNoise(l)}
|
|
460
|
+
className={btnCls(noise === l)}
|
|
461
|
+
>
|
|
462
|
+
{l}
|
|
463
|
+
</button>
|
|
464
|
+
))}
|
|
465
|
+
</div>
|
|
702
466
|
</div>
|
|
703
|
-
<DrawerFooter>
|
|
704
|
-
<Button onClick={() => setIsNestedOpen(false)}>
|
|
705
|
-
Close Nested
|
|
706
|
-
</Button>
|
|
707
|
-
<DrawerClose asChild>
|
|
708
|
-
<Button variant="outline">Cancel</Button>
|
|
709
|
-
</DrawerClose>
|
|
710
|
-
</DrawerFooter>
|
|
711
|
-
</DrawerContent>
|
|
712
|
-
</Drawer>
|
|
713
|
-
</div>
|
|
714
|
-
<DrawerFooter>
|
|
715
|
-
<Button>Save</Button>
|
|
716
|
-
<DrawerClose asChild>
|
|
717
|
-
<Button variant="outline">Close Parent</Button>
|
|
718
|
-
</DrawerClose>
|
|
719
|
-
</DrawerFooter>
|
|
720
|
-
</DrawerContent>
|
|
721
|
-
</Drawer>
|
|
722
|
-
)
|
|
723
|
-
},
|
|
724
|
-
parameters: {
|
|
725
|
-
docs: {
|
|
726
|
-
description: {
|
|
727
|
-
story:
|
|
728
|
-
"Nested drawer example demonstrating proper modal stacking and z-index management.",
|
|
729
|
-
},
|
|
730
|
-
},
|
|
731
|
-
},
|
|
732
|
-
}
|
|
733
467
|
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
468
|
+
<div className="border-fm-divider-secondary border-t pt-4" />
|
|
469
|
+
|
|
470
|
+
<div className="flex items-center gap-2">
|
|
471
|
+
<Checkbox
|
|
472
|
+
id="swipe-btn"
|
|
473
|
+
checked={showSwipeButton}
|
|
474
|
+
onCheckedChange={(c) => setShowSwipeButton(!!c)}
|
|
475
|
+
/>
|
|
476
|
+
<Label
|
|
477
|
+
htmlFor="swipe-btn"
|
|
478
|
+
className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm"
|
|
479
|
+
>
|
|
480
|
+
Swipe handle
|
|
481
|
+
</Label>
|
|
482
|
+
</div>
|
|
483
|
+
</div>
|
|
484
|
+
|
|
485
|
+
{/* Preview stage */}
|
|
486
|
+
<div className="flex flex-col gap-3 lg:col-span-2">
|
|
487
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary flex min-h-48 flex-col items-center justify-center gap-4 rounded-xl border p-8">
|
|
488
|
+
{submitted && (
|
|
489
|
+
<div className="border-fm-divider-positive bg-fm-surface-positive-sec rounded-lg border px-4 py-2">
|
|
490
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
491
|
+
Form submitted for{" "}
|
|
492
|
+
<span className="text-fm-primary font-medium">
|
|
493
|
+
{name}
|
|
494
|
+
</span>
|
|
495
|
+
</p>
|
|
496
|
+
</div>
|
|
497
|
+
)}
|
|
498
|
+
|
|
499
|
+
<Drawer direction={direction}>
|
|
500
|
+
<DrawerTrigger asChild>
|
|
501
|
+
<Button onClick={() => setSubmitted(false)}>
|
|
502
|
+
Open Drawer
|
|
503
|
+
</Button>
|
|
504
|
+
</DrawerTrigger>
|
|
505
|
+
<DrawerContent
|
|
506
|
+
variant={variant}
|
|
507
|
+
opacity={opacity}
|
|
508
|
+
glass={glass}
|
|
509
|
+
noise={noise}
|
|
510
|
+
showSwipeButton={showSwipeButton}
|
|
511
|
+
>
|
|
512
|
+
<DrawerHeader>
|
|
513
|
+
<DrawerTitle>Quick Contact</DrawerTitle>
|
|
514
|
+
<DrawerDescription>
|
|
515
|
+
Fill out the form to send a message.
|
|
516
|
+
</DrawerDescription>
|
|
517
|
+
</DrawerHeader>
|
|
518
|
+
|
|
519
|
+
<div className="space-y-4 p-4">
|
|
520
|
+
<div className="space-y-2">
|
|
521
|
+
<Label htmlFor="drawer-name">Name</Label>
|
|
522
|
+
<Input
|
|
523
|
+
id="drawer-name"
|
|
524
|
+
placeholder="Your name"
|
|
525
|
+
value={name}
|
|
526
|
+
onChange={(e) => setName(e.target.value)}
|
|
527
|
+
/>
|
|
528
|
+
</div>
|
|
529
|
+
<div className="space-y-2">
|
|
530
|
+
<Label htmlFor="drawer-email">Email</Label>
|
|
531
|
+
<Input
|
|
532
|
+
id="drawer-email"
|
|
533
|
+
type="email"
|
|
534
|
+
placeholder="your@email.com"
|
|
535
|
+
value={email}
|
|
536
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
537
|
+
/>
|
|
538
|
+
</div>
|
|
539
|
+
</div>
|
|
540
|
+
|
|
541
|
+
<DrawerFooter>
|
|
542
|
+
<DrawerClose asChild>
|
|
543
|
+
<Button
|
|
544
|
+
disabled={!name || !email}
|
|
545
|
+
onClick={() => setSubmitted(true)}
|
|
546
|
+
>
|
|
547
|
+
Submit
|
|
548
|
+
</Button>
|
|
549
|
+
</DrawerClose>
|
|
550
|
+
<DrawerClose asChild>
|
|
551
|
+
<Button variant="outline">Cancel</Button>
|
|
552
|
+
</DrawerClose>
|
|
553
|
+
</DrawerFooter>
|
|
554
|
+
</DrawerContent>
|
|
555
|
+
</Drawer>
|
|
556
|
+
</div>
|
|
557
|
+
|
|
558
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
559
|
+
<code className="text-fm-secondary text-fm-sm leading-fm-sm font-(--font-fm-mono)">
|
|
560
|
+
{`<Drawer direction="${direction}"><DrawerContent variant="${variant}" opacity="${opacity}" glass="${glass}" noise="${noise}" showSwipeButton={${showSwipeButton}} />`}
|
|
561
|
+
</code>
|
|
562
|
+
</div>
|
|
563
|
+
</div>
|
|
749
564
|
</div>
|
|
750
|
-
<DrawerClose asChild>
|
|
751
|
-
<Button variant="text" size="sm" className="ml-4">
|
|
752
|
-
<CrossIcon className="h-4 w-4" />
|
|
753
|
-
</Button>
|
|
754
|
-
</DrawerClose>
|
|
755
565
|
</div>
|
|
756
|
-
</
|
|
566
|
+
</div>
|
|
567
|
+
)
|
|
568
|
+
}
|
|
757
569
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
<DrawerClose asChild>
|
|
761
|
-
<Button variant="outline">Cancel</Button>
|
|
762
|
-
</DrawerClose>
|
|
763
|
-
</DrawerFooter>
|
|
764
|
-
</DrawerContent>
|
|
765
|
-
</Drawer>
|
|
766
|
-
),
|
|
570
|
+
return <InteractiveDemo />
|
|
571
|
+
},
|
|
767
572
|
parameters: {
|
|
768
573
|
docs: {
|
|
769
574
|
description: {
|
|
770
575
|
story:
|
|
771
|
-
"
|
|
576
|
+
"Live configurator — select direction, variant, overlay settings, and swipe handle, then open the drawer and submit the form inside to see state feedback.",
|
|
772
577
|
},
|
|
773
578
|
},
|
|
774
579
|
},
|
|
775
580
|
}
|
|
776
581
|
|
|
777
|
-
//
|
|
778
|
-
|
|
582
|
+
// ─── UseCases ─────────────────────────────────────────────────────────────────
|
|
583
|
+
|
|
584
|
+
export const UseCases: Story = {
|
|
779
585
|
render: () => {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
</DrawerTrigger>
|
|
785
|
-
<DrawerContent>
|
|
786
|
-
<DrawerHeader>
|
|
787
|
-
<DrawerTitle>Accessibility Features</DrawerTitle>
|
|
788
|
-
<DrawerDescription>
|
|
789
|
-
This drawer demonstrates proper accessibility implementation.
|
|
790
|
-
</DrawerDescription>
|
|
791
|
-
</DrawerHeader>
|
|
586
|
+
// Track actions bottom drawer
|
|
587
|
+
const TrackActionsDrawer = () => {
|
|
588
|
+
const [liked, setLiked] = useState(false)
|
|
589
|
+
const [queued, setQueued] = useState(false)
|
|
792
590
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
Close drawer
|
|
806
|
-
</li>
|
|
807
|
-
<li>
|
|
808
|
-
• <kbd className="rounded bg-white/10 px-1">Enter</kbd> -
|
|
809
|
-
Activate buttons
|
|
810
|
-
</li>
|
|
811
|
-
<li>
|
|
812
|
-
• <kbd className="rounded bg-white/10 px-1">Space</kbd> -
|
|
813
|
-
Activate buttons
|
|
814
|
-
</li>
|
|
815
|
-
</ul>
|
|
816
|
-
</div>
|
|
591
|
+
return (
|
|
592
|
+
<Drawer direction="bottom">
|
|
593
|
+
<DrawerTrigger asChild>
|
|
594
|
+
<Button variant="outline" size="sm">
|
|
595
|
+
Track actions
|
|
596
|
+
</Button>
|
|
597
|
+
</DrawerTrigger>
|
|
598
|
+
<DrawerContent showSwipeButton>
|
|
599
|
+
<DrawerHeader>
|
|
600
|
+
<DrawerTitle>Midnight Drive</DrawerTitle>
|
|
601
|
+
<DrawerDescription>Lo-fi Chill · 3:42</DrawerDescription>
|
|
602
|
+
</DrawerHeader>
|
|
817
603
|
|
|
818
|
-
<div className="
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
604
|
+
<div className="space-y-1 p-4">
|
|
605
|
+
{[
|
|
606
|
+
{
|
|
607
|
+
label: liked ? "Remove from Liked" : "Like this track",
|
|
608
|
+
icon: TickCircleIcon,
|
|
609
|
+
action: () => setLiked((v) => !v),
|
|
610
|
+
active: liked,
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
label: queued ? "Remove from queue" : "Add to queue",
|
|
614
|
+
icon: MusicalNoteIcon,
|
|
615
|
+
action: () => setQueued((v) => !v),
|
|
616
|
+
active: queued,
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
label: "Go to artist",
|
|
620
|
+
icon: ChevronRightIcon,
|
|
621
|
+
action: () => {},
|
|
622
|
+
active: false,
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
label: "Share",
|
|
626
|
+
icon: SearchIcon,
|
|
627
|
+
action: () => {},
|
|
628
|
+
active: false,
|
|
629
|
+
},
|
|
630
|
+
].map((item) => (
|
|
631
|
+
<button
|
|
632
|
+
key={item.label}
|
|
633
|
+
onClick={item.action}
|
|
634
|
+
className={`flex w-full items-center gap-3 rounded-lg px-3 py-3 text-left transition-colors ${
|
|
635
|
+
item.active
|
|
636
|
+
? "bg-fm-surface-positive-sec text-fm-primary"
|
|
637
|
+
: "text-fm-primary hover:bg-fm-surface-secondary"
|
|
638
|
+
}`}
|
|
639
|
+
>
|
|
640
|
+
<item.icon className="text-fm-secondary h-5 w-5 shrink-0" />
|
|
641
|
+
<span className="font-fm-text text-fm-md leading-fm-md">
|
|
642
|
+
{item.label}
|
|
643
|
+
</span>
|
|
644
|
+
</button>
|
|
645
|
+
))}
|
|
826
646
|
</div>
|
|
827
647
|
|
|
828
|
-
<
|
|
829
|
-
<
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
</div>
|
|
648
|
+
<DrawerFooter>
|
|
649
|
+
<DrawerClose asChild>
|
|
650
|
+
<Button variant="outline">Close</Button>
|
|
651
|
+
</DrawerClose>
|
|
652
|
+
</DrawerFooter>
|
|
653
|
+
</DrawerContent>
|
|
654
|
+
</Drawer>
|
|
655
|
+
)
|
|
656
|
+
}
|
|
838
657
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
parameters: {
|
|
849
|
-
docs: {
|
|
850
|
-
description: {
|
|
851
|
-
story:
|
|
852
|
-
"Comprehensive accessibility example showcasing keyboard navigation, focus management, and drag support features.",
|
|
853
|
-
},
|
|
854
|
-
},
|
|
855
|
-
},
|
|
856
|
-
}
|
|
658
|
+
// Side navigation drawer
|
|
659
|
+
const NavDrawer = () => {
|
|
660
|
+
const [active, setActive] = useState("Home")
|
|
661
|
+
const items = [
|
|
662
|
+
{ label: "Home", icon: SiteLogoIcon },
|
|
663
|
+
{ label: "Search", icon: SearchIcon },
|
|
664
|
+
{ label: "Library", icon: MusicalNoteIcon },
|
|
665
|
+
{ label: "Settings", icon: MaintenanceIcon },
|
|
666
|
+
]
|
|
857
667
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
668
|
+
return (
|
|
669
|
+
<Drawer direction="left">
|
|
670
|
+
<DrawerTrigger asChild>
|
|
671
|
+
<Button variant="outline" size="sm">
|
|
672
|
+
Side navigation
|
|
673
|
+
</Button>
|
|
674
|
+
</DrawerTrigger>
|
|
675
|
+
<DrawerContent>
|
|
676
|
+
<DrawerHeader>
|
|
677
|
+
<DrawerTitle>Navigation</DrawerTitle>
|
|
678
|
+
<DrawerDescription>Main app navigation</DrawerDescription>
|
|
679
|
+
</DrawerHeader>
|
|
680
|
+
|
|
681
|
+
<nav className="space-y-1 p-4">
|
|
682
|
+
{items.map((item) => (
|
|
683
|
+
<button
|
|
684
|
+
key={item.label}
|
|
685
|
+
onClick={() => setActive(item.label)}
|
|
686
|
+
className={`flex w-full items-center gap-3 rounded-lg px-3 py-3 text-left transition-colors ${
|
|
687
|
+
active === item.label
|
|
688
|
+
? "bg-fm-surface-info-sec text-fm-primary"
|
|
689
|
+
: "text-fm-primary hover:bg-fm-surface-secondary"
|
|
690
|
+
}`}
|
|
691
|
+
>
|
|
692
|
+
<item.icon className="text-fm-secondary h-5 w-5 shrink-0" />
|
|
693
|
+
<span className="font-fm-text text-fm-md leading-fm-md">
|
|
694
|
+
{item.label}
|
|
695
|
+
</span>
|
|
696
|
+
</button>
|
|
697
|
+
))}
|
|
698
|
+
</nav>
|
|
699
|
+
|
|
700
|
+
<DrawerFooter>
|
|
701
|
+
<DrawerClose asChild>
|
|
702
|
+
<Button variant="outline">Close</Button>
|
|
703
|
+
</DrawerClose>
|
|
704
|
+
</DrawerFooter>
|
|
705
|
+
</DrawerContent>
|
|
706
|
+
</Drawer>
|
|
707
|
+
)
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// Settings panel drawer
|
|
711
|
+
const SettingsDrawer = () => {
|
|
712
|
+
const [autoplay, setAutoplay] = useState(true)
|
|
713
|
+
const [notifications, setNotifications] = useState(false)
|
|
714
|
+
const [hq, setHq] = useState(true)
|
|
893
715
|
|
|
894
|
-
// 8. Overlay Variations
|
|
895
|
-
export const OverlayVariations: Story = {
|
|
896
|
-
render: () => {
|
|
897
|
-
const OverlayDrawer = ({
|
|
898
|
-
opacity,
|
|
899
|
-
glass,
|
|
900
|
-
noise,
|
|
901
|
-
title,
|
|
902
|
-
description,
|
|
903
|
-
}: any) => {
|
|
904
716
|
return (
|
|
905
|
-
<Drawer>
|
|
717
|
+
<Drawer direction="right">
|
|
906
718
|
<DrawerTrigger asChild>
|
|
907
719
|
<Button variant="outline" size="sm">
|
|
908
|
-
|
|
720
|
+
Settings panel
|
|
909
721
|
</Button>
|
|
910
722
|
</DrawerTrigger>
|
|
911
|
-
<DrawerContent
|
|
912
|
-
opacity={opacity}
|
|
913
|
-
glass={glass}
|
|
914
|
-
noise={noise}
|
|
915
|
-
variant="neutral"
|
|
916
|
-
>
|
|
723
|
+
<DrawerContent>
|
|
917
724
|
<DrawerHeader>
|
|
918
|
-
<DrawerTitle>
|
|
919
|
-
<DrawerDescription>
|
|
725
|
+
<DrawerTitle>Playback Settings</DrawerTitle>
|
|
726
|
+
<DrawerDescription>
|
|
727
|
+
Configure your listening experience
|
|
728
|
+
</DrawerDescription>
|
|
920
729
|
</DrawerHeader>
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
</
|
|
927
|
-
<div>
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
730
|
+
|
|
731
|
+
<div className="space-y-5 p-4">
|
|
732
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
733
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm mb-3 font-semibold tracking-widest uppercase">
|
|
734
|
+
Playback
|
|
735
|
+
</p>
|
|
736
|
+
<div className="space-y-3">
|
|
737
|
+
{[
|
|
738
|
+
{ label: "Autoplay", value: autoplay, set: setAutoplay },
|
|
739
|
+
{ label: "High quality audio", value: hq, set: setHq },
|
|
740
|
+
].map((s) => (
|
|
741
|
+
<div
|
|
742
|
+
key={s.label}
|
|
743
|
+
className="flex items-center justify-between"
|
|
744
|
+
>
|
|
745
|
+
<span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
746
|
+
{s.label}
|
|
747
|
+
</span>
|
|
748
|
+
<Checkbox
|
|
749
|
+
checked={s.value}
|
|
750
|
+
onCheckedChange={(c) => s.set(!!c)}
|
|
751
|
+
/>
|
|
752
|
+
</div>
|
|
753
|
+
))}
|
|
933
754
|
</div>
|
|
934
|
-
|
|
935
|
-
|
|
755
|
+
</div>
|
|
756
|
+
|
|
757
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
758
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm mb-3 font-semibold tracking-widest uppercase">
|
|
759
|
+
Notifications
|
|
760
|
+
</p>
|
|
761
|
+
<div className="flex items-center justify-between">
|
|
762
|
+
<span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
763
|
+
Push notifications
|
|
764
|
+
</span>
|
|
765
|
+
<Checkbox
|
|
766
|
+
checked={notifications}
|
|
767
|
+
onCheckedChange={(c) => setNotifications(!!c)}
|
|
768
|
+
/>
|
|
936
769
|
</div>
|
|
937
770
|
</div>
|
|
938
771
|
</div>
|
|
772
|
+
|
|
939
773
|
<DrawerFooter>
|
|
940
774
|
<DrawerClose asChild>
|
|
941
|
-
<Button>
|
|
775
|
+
<Button>Save</Button>
|
|
776
|
+
</DrawerClose>
|
|
777
|
+
<DrawerClose asChild>
|
|
778
|
+
<Button variant="outline">Cancel</Button>
|
|
942
779
|
</DrawerClose>
|
|
943
780
|
</DrawerFooter>
|
|
944
781
|
</DrawerContent>
|
|
@@ -947,174 +784,39 @@ export const OverlayVariations: Story = {
|
|
|
947
784
|
}
|
|
948
785
|
|
|
949
786
|
return (
|
|
950
|
-
<div className="space-y-8">
|
|
951
|
-
<div className="
|
|
952
|
-
<
|
|
953
|
-
|
|
954
|
-
|
|
787
|
+
<div className="mx-auto max-w-3xl space-y-8 p-8">
|
|
788
|
+
<div className="space-y-3">
|
|
789
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
790
|
+
Mobile Bottom Drawer — Track Actions
|
|
791
|
+
</h4>
|
|
792
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
|
|
793
|
+
A bottom sheet presenting contextual actions for the currently
|
|
794
|
+
playing track. Includes a swipe handle and stateful like/queue
|
|
795
|
+
toggles.
|
|
955
796
|
</p>
|
|
797
|
+
<TrackActionsDrawer />
|
|
956
798
|
</div>
|
|
957
799
|
|
|
958
|
-
<div className="
|
|
959
|
-
<
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
opacity="medium"
|
|
966
|
-
title="Medium Opacity"
|
|
967
|
-
description="Balanced background dimming (60%)"
|
|
968
|
-
/>
|
|
969
|
-
<OverlayDrawer
|
|
970
|
-
opacity="high"
|
|
971
|
-
title="High Opacity"
|
|
972
|
-
description="Strong background dimming (80%)"
|
|
973
|
-
/>
|
|
974
|
-
<OverlayDrawer
|
|
975
|
-
opacity="none"
|
|
976
|
-
title="Full Opacity"
|
|
977
|
-
description="Complete background coverage (100%)"
|
|
978
|
-
/>
|
|
979
|
-
<OverlayDrawer
|
|
980
|
-
glass="low"
|
|
981
|
-
title="Low Glass"
|
|
982
|
-
description="Subtle backdrop blur effect"
|
|
983
|
-
/>
|
|
984
|
-
<OverlayDrawer
|
|
985
|
-
glass="medium"
|
|
986
|
-
title="Medium Glass"
|
|
987
|
-
description="Balanced backdrop blur effect"
|
|
988
|
-
/>
|
|
989
|
-
<OverlayDrawer
|
|
990
|
-
glass="high"
|
|
991
|
-
title="High Glass"
|
|
992
|
-
description="Strong backdrop blur effect"
|
|
993
|
-
/>
|
|
994
|
-
<OverlayDrawer
|
|
995
|
-
noise="low"
|
|
996
|
-
title="Low Noise"
|
|
997
|
-
description="Subtle texture pattern"
|
|
998
|
-
/>
|
|
999
|
-
<OverlayDrawer
|
|
1000
|
-
noise="medium"
|
|
1001
|
-
title="Medium Noise"
|
|
1002
|
-
description="Balanced texture pattern"
|
|
1003
|
-
/>
|
|
1004
|
-
<OverlayDrawer
|
|
1005
|
-
noise="high"
|
|
1006
|
-
title="High Noise"
|
|
1007
|
-
description="Strong texture pattern"
|
|
1008
|
-
/>
|
|
1009
|
-
<OverlayDrawer
|
|
1010
|
-
opacity="medium"
|
|
1011
|
-
glass="medium"
|
|
1012
|
-
noise="medium"
|
|
1013
|
-
title="Balanced"
|
|
1014
|
-
description="All effects at medium level"
|
|
1015
|
-
/>
|
|
1016
|
-
</div>
|
|
1017
|
-
</div>
|
|
1018
|
-
)
|
|
1019
|
-
},
|
|
1020
|
-
parameters: {
|
|
1021
|
-
docs: {
|
|
1022
|
-
description: {
|
|
1023
|
-
story:
|
|
1024
|
-
"Showcase of different overlay configurations demonstrating various opacity, glass, and noise effects.",
|
|
1025
|
-
},
|
|
1026
|
-
},
|
|
1027
|
-
},
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
// 9. Variant Examples
|
|
1031
|
-
export const VariantExamples: Story = {
|
|
1032
|
-
render: () => {
|
|
1033
|
-
return (
|
|
1034
|
-
<div className="space-y-8">
|
|
1035
|
-
<div className="text-center">
|
|
1036
|
-
<h3 className="mb-2 font-medium text-white">Drawer Variants</h3>
|
|
1037
|
-
<p className="text-sm text-white/60">
|
|
1038
|
-
Compare the neutral (default) and gradient variants
|
|
800
|
+
<div className="space-y-3">
|
|
801
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
802
|
+
Side Navigation Drawer
|
|
803
|
+
</h4>
|
|
804
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
|
|
805
|
+
A left-side navigation drawer for switching between primary app
|
|
806
|
+
sections. Active item is highlighted.
|
|
1039
807
|
</p>
|
|
808
|
+
<NavDrawer />
|
|
1040
809
|
</div>
|
|
1041
810
|
|
|
1042
|
-
<div className="
|
|
1043
|
-
<
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
</Button>
|
|
1052
|
-
</DrawerTrigger>
|
|
1053
|
-
<DrawerContent variant="neutral">
|
|
1054
|
-
<DrawerHeader>
|
|
1055
|
-
<DrawerTitle>Neutral Variant</DrawerTitle>
|
|
1056
|
-
<DrawerDescription>
|
|
1057
|
-
This is the default neutral variant with frosted glass
|
|
1058
|
-
background and border.
|
|
1059
|
-
</DrawerDescription>
|
|
1060
|
-
</DrawerHeader>
|
|
1061
|
-
<div className="py-4">
|
|
1062
|
-
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
1063
|
-
<h5 className="mb-2 font-medium text-white">Features:</h5>
|
|
1064
|
-
<ul className="space-y-1 text-sm text-white/70">
|
|
1065
|
-
<li>• Frosted glass background</li>
|
|
1066
|
-
<li>• Subtle border</li>
|
|
1067
|
-
<li>• Backdrop blur effect</li>
|
|
1068
|
-
<li>• Semi-transparent appearance</li>
|
|
1069
|
-
</ul>
|
|
1070
|
-
</div>
|
|
1071
|
-
</div>
|
|
1072
|
-
<DrawerFooter>
|
|
1073
|
-
<DrawerClose asChild>
|
|
1074
|
-
<Button>Close</Button>
|
|
1075
|
-
</DrawerClose>
|
|
1076
|
-
</DrawerFooter>
|
|
1077
|
-
</DrawerContent>
|
|
1078
|
-
</Drawer>
|
|
1079
|
-
</div>
|
|
1080
|
-
|
|
1081
|
-
<div className="space-y-4">
|
|
1082
|
-
<h4 className="text-center font-medium text-white">
|
|
1083
|
-
Gradient Variant
|
|
1084
|
-
</h4>
|
|
1085
|
-
<Drawer>
|
|
1086
|
-
<DrawerTrigger asChild>
|
|
1087
|
-
<Button variant="outline" className="w-full">
|
|
1088
|
-
Open Gradient Drawer
|
|
1089
|
-
</Button>
|
|
1090
|
-
</DrawerTrigger>
|
|
1091
|
-
<DrawerContent variant="gradient">
|
|
1092
|
-
<DrawerHeader>
|
|
1093
|
-
<DrawerTitle>Gradient Variant</DrawerTitle>
|
|
1094
|
-
<DrawerDescription>
|
|
1095
|
-
This is the gradient variant with white gradient background
|
|
1096
|
-
and no border.
|
|
1097
|
-
</DrawerDescription>
|
|
1098
|
-
</DrawerHeader>
|
|
1099
|
-
<div className="py-4">
|
|
1100
|
-
<div className="rounded-lg border border-white/10 bg-white/5 p-4">
|
|
1101
|
-
<h5 className="mb-2 font-medium text-white">Features:</h5>
|
|
1102
|
-
<ul className="space-y-1 text-sm text-white/70">
|
|
1103
|
-
<li>• White gradient background</li>
|
|
1104
|
-
<li>• No border</li>
|
|
1105
|
-
<li>• Clean, modern appearance</li>
|
|
1106
|
-
<li>• Solid background effect</li>
|
|
1107
|
-
</ul>
|
|
1108
|
-
</div>
|
|
1109
|
-
</div>
|
|
1110
|
-
<DrawerFooter>
|
|
1111
|
-
<DrawerClose asChild>
|
|
1112
|
-
<Button>Close</Button>
|
|
1113
|
-
</DrawerClose>
|
|
1114
|
-
</DrawerFooter>
|
|
1115
|
-
</DrawerContent>
|
|
1116
|
-
</Drawer>
|
|
1117
|
-
</div>
|
|
811
|
+
<div className="space-y-3">
|
|
812
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
813
|
+
Settings Panel Drawer
|
|
814
|
+
</h4>
|
|
815
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
|
|
816
|
+
A right-side settings panel that groups playback and notification
|
|
817
|
+
preferences with interactive checkboxes.
|
|
818
|
+
</p>
|
|
819
|
+
<SettingsDrawer />
|
|
1118
820
|
</div>
|
|
1119
821
|
</div>
|
|
1120
822
|
)
|
|
@@ -1123,43 +825,7 @@ export const VariantExamples: Story = {
|
|
|
1123
825
|
docs: {
|
|
1124
826
|
description: {
|
|
1125
827
|
story:
|
|
1126
|
-
"
|
|
1127
|
-
},
|
|
1128
|
-
},
|
|
1129
|
-
},
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
export const DrawerWithSwipeButton: Story = {
|
|
1133
|
-
render: () => (
|
|
1134
|
-
<div>
|
|
1135
|
-
<Drawer>
|
|
1136
|
-
<DrawerTrigger asChild>
|
|
1137
|
-
<Button className="relative z-10">
|
|
1138
|
-
Open Drawer (With Swipe button)
|
|
1139
|
-
</Button>
|
|
1140
|
-
</DrawerTrigger>
|
|
1141
|
-
<DrawerContent showSwipeButton={true}>
|
|
1142
|
-
<DrawerHeader>
|
|
1143
|
-
<DrawerTitle>Drawer with Swipe button</DrawerTitle>
|
|
1144
|
-
<DrawerDescription>
|
|
1145
|
-
This drawer opens with a swipe button.
|
|
1146
|
-
</DrawerDescription>
|
|
1147
|
-
</DrawerHeader>
|
|
1148
|
-
<DrawerFooter>
|
|
1149
|
-
<Button>Apply Changes</Button>
|
|
1150
|
-
<DrawerClose asChild>
|
|
1151
|
-
<Button variant="outline">Cancel</Button>
|
|
1152
|
-
</DrawerClose>
|
|
1153
|
-
</DrawerFooter>
|
|
1154
|
-
</DrawerContent>
|
|
1155
|
-
</Drawer>
|
|
1156
|
-
</div>
|
|
1157
|
-
),
|
|
1158
|
-
parameters: {
|
|
1159
|
-
docs: {
|
|
1160
|
-
description: {
|
|
1161
|
-
story:
|
|
1162
|
-
"Drawer example with `showSwipeButton={true}` showing a swipe indicator button",
|
|
828
|
+
"Three realistic product scenarios: a mobile bottom track-actions sheet, a left-side app navigation drawer, and a right-side settings panel.",
|
|
1163
829
|
},
|
|
1164
830
|
},
|
|
1165
831
|
},
|