aural-ui 4.0.1 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1228
- package/dist/components/avatar/Avatar.stories.tsx +219 -235
- 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/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 -636
- 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 +530 -867
- package/dist/components/dialog/Dialog.stories.tsx +501 -950
- package/dist/components/divider/Divider.stories.tsx +264 -527
- package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
- package/dist/components/drawer/Drawer.stories.tsx +659 -1023
- package/dist/components/dropdown/Dropdown.stories.tsx +643 -1028
- 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 -1254
- 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 +484 -835
- package/dist/components/marquee/Marquee.stories.tsx +356 -712
- package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -422
- package/dist/components/overlay/Overlay.stories.tsx +452 -824
- package/dist/components/pagination/Pagination.stories.tsx +721 -210
- package/dist/components/popover/Popover.stories.tsx +481 -896
- package/dist/components/radio/Radio.stories.tsx +432 -124
- package/dist/components/resizable/Resizable.stories.tsx +495 -799
- package/dist/components/scroll-area/ScrollArea.stories.tsx +383 -1059
- package/dist/components/search/Search.stories.tsx +312 -595
- package/dist/components/select/Select.stories.tsx +684 -789
- package/dist/components/sheet/Sheet.stories.tsx +671 -950
- package/dist/components/skelton/Skelton.stories.tsx +230 -764
- package/dist/components/slider/Slider.stories.tsx +383 -760
- 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 -916
- package/dist/components/tabs/Tabs.stories.tsx +458 -1455
- 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 -154
- package/dist/components/toast/Toast.stories.tsx +452 -1339
- package/dist/components/toggle/Toggle.stories.tsx +488 -931
- package/dist/components/tooltip/Tooltip.stories.tsx +344 -1388
- 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 +223 -1060
- package/dist/icons/alert-icon/AlertIcon.stories.tsx +106 -968
- package/dist/icons/all-icons.tsx +37 -16
- package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +137 -1010
- package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +145 -935
- package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +132 -1046
- package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +134 -986
- package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +135 -1028
- package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +133 -971
- package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +145 -1123
- package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +143 -1252
- package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +123 -632
- package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +141 -1223
- package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +164 -1018
- package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +121 -1236
- package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +121 -1213
- package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +116 -893
- package/dist/icons/camera-icon/CameraIcon.stories.tsx +109 -1254
- package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +114 -975
- package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +157 -994
- package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +160 -992
- package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +140 -970
- package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +126 -993
- package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +144 -987
- package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +141 -1007
- package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +147 -1187
- package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +110 -476
- package/dist/icons/coin-icon/CoinIcon.stories.tsx +120 -1364
- package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +113 -1360
- package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +111 -942
- package/dist/icons/command-icon/CommandIcon.stories.tsx +124 -1087
- package/dist/icons/copy-icon/CopyIcon.stories.tsx +119 -996
- package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +144 -1046
- package/dist/icons/cross-icon/CrossIcon.stories.tsx +136 -999
- package/dist/icons/download-icon/DownloadIcon.stories.tsx +123 -857
- package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +121 -1080
- package/dist/icons/email-icon/EmailIcon.stories.tsx +112 -979
- package/dist/icons/expand-icon/ExpandIcon.stories.tsx +109 -1146
- package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +141 -1068
- package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +140 -1081
- package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +124 -1050
- package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +123 -1091
- package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +122 -633
- package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +116 -1087
- package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +166 -1020
- package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +112 -1182
- package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +112 -1155
- package/dist/icons/globe-icon/GlobeIcon.stories.tsx +127 -325
- package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +142 -985
- package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +116 -1217
- package/dist/icons/head-icon/HeadIcon.stories.tsx +108 -953
- package/dist/icons/heart-icon/HeartIcon.stories.tsx +117 -1060
- package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +116 -716
- package/dist/icons/image-icon/ImageIcon.stories.tsx +102 -1164
- package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +108 -1233
- package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +133 -1289
- package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +155 -1012
- package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +158 -1438
- package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +121 -1011
- package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +116 -981
- package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +116 -979
- package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +105 -1252
- package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +151 -1554
- package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +107 -1227
- package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +116 -707
- package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +119 -1226
- package/dist/icons/message-icon/MessageIcon.stories.tsx +111 -557
- package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +112 -1198
- package/dist/icons/moon-icon/MoonIcon.stories.tsx +117 -557
- package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +106 -1235
- package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +112 -1185
- package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +116 -1012
- package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +108 -1137
- package/dist/icons/notes-icon/NotesIcon.stories.tsx +116 -1138
- package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +106 -1146
- package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +119 -719
- package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +110 -999
- package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +109 -912
- package/dist/icons/pause-icon/PauseIcon.stories.tsx +110 -1041
- package/dist/icons/pencil-icon/PencilIcon.stories.tsx +112 -1109
- package/dist/icons/phone-icon/PhoneIcon.stories.tsx +112 -1023
- package/dist/icons/plus-icon/PlusIcon.stories.tsx +103 -1132
- package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +104 -870
- package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +99 -476
- package/dist/icons/search-icon/SearchIcon.stories.tsx +108 -1161
- package/dist/icons/setting-icon/SettingIcon.stories.tsx +104 -1009
- package/dist/icons/share-icon/ShareIcon.stories.tsx +117 -1064
- package/dist/icons/shield-icon/ShieldIcon.stories.tsx +114 -974
- package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +134 -1160
- package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +169 -1017
- package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +161 -1016
- package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +102 -1001
- package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +155 -593
- package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +155 -608
- package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +142 -712
- package/dist/icons/star-icon/StarIcon.stories.tsx +120 -946
- package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +109 -1013
- package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +113 -891
- package/dist/icons/sun-icon/SunIcon.stories.tsx +117 -864
- package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +113 -989
- package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +120 -1027
- package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +153 -1476
- package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +143 -1187
- package/dist/icons/tick-icon/TickIcon.stories.tsx +142 -1322
- package/dist/icons/trash-icon/TrashIcon.stories.tsx +105 -970
- package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +154 -1457
- package/dist/icons/upload-icon/UploadIcon.stories.tsx +112 -930
- package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +115 -1019
- package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +122 -1092
- package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +120 -1401
- package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +107 -1212
- package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +109 -1122
- package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +112 -1124
- package/dist/icons/warning-icon/WarningIcon.stories.tsx +119 -1083
- package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +158 -983
- package/dist/index.cjs +90 -90
- package/dist/index.js +90 -90
- package/package.json +8 -3
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React from "react"
|
|
1
|
+
import React, { useState } from "react"
|
|
2
2
|
import { AngleDownIcon } from "@icons/angle-down-icon"
|
|
3
3
|
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
6
|
+
|
|
6
7
|
import {
|
|
7
8
|
Collapsible,
|
|
8
9
|
CollapsibleContent,
|
|
@@ -16,18 +17,29 @@ const meta: Meta<typeof Collapsible> = {
|
|
|
16
17
|
component: Collapsible,
|
|
17
18
|
parameters: {
|
|
18
19
|
layout: "centered",
|
|
19
|
-
backgrounds: {
|
|
20
|
-
default: "dark",
|
|
21
|
-
values: [
|
|
22
|
-
{ name: "dark", value: "#0a0a0a" },
|
|
23
|
-
{ name: "light", value: "#ffffff" },
|
|
24
|
-
],
|
|
25
|
-
},
|
|
26
20
|
docs: {
|
|
27
21
|
description: {
|
|
28
22
|
component:
|
|
29
|
-
"A collapsible component built on Radix UI
|
|
23
|
+
"A compound collapsible component built on Radix UI. Composed of CollapsibleHeader, CollapsibleTrigger, CollapsibleTitle, and CollapsibleContent for building expandable sections with defaultOpen and disabled states.",
|
|
30
24
|
},
|
|
25
|
+
page: () => (
|
|
26
|
+
<AuralComponentDocsPage
|
|
27
|
+
features={[
|
|
28
|
+
{
|
|
29
|
+
title: "Compound Structure",
|
|
30
|
+
description: "Header, trigger, content",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
title: "Stateful by Design",
|
|
34
|
+
description: "Open, closed, disabled",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
title: "Expandable Content",
|
|
38
|
+
description: "Smooth reveal pattern",
|
|
39
|
+
},
|
|
40
|
+
]}
|
|
41
|
+
/>
|
|
42
|
+
),
|
|
31
43
|
},
|
|
32
44
|
},
|
|
33
45
|
tags: ["autodocs"],
|
|
@@ -46,281 +58,408 @@ const meta: Meta<typeof Collapsible> = {
|
|
|
46
58
|
export default meta
|
|
47
59
|
type Story = StoryObj<typeof Collapsible>
|
|
48
60
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<div className="
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
<div className="pt-4">
|
|
56
|
-
<p>
|
|
57
|
-
This is the collapsible content area. You can put any content here
|
|
58
|
-
including text, images, forms, or other components. The content
|
|
59
|
-
will smoothly animate when the collapsible is opened or closed.
|
|
60
|
-
</p>
|
|
61
|
-
</div>
|
|
62
|
-
</CollapsibleContent>
|
|
63
|
-
</Collapsible>
|
|
61
|
+
function InfoBox({ children }: { children: React.ReactNode }) {
|
|
62
|
+
return (
|
|
63
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
64
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
65
|
+
{children}
|
|
66
|
+
</p>
|
|
64
67
|
</div>
|
|
65
|
-
)
|
|
66
|
-
args: {
|
|
67
|
-
defaultOpen: false,
|
|
68
|
-
},
|
|
68
|
+
)
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
</div>
|
|
90
|
-
</div>
|
|
91
|
-
</CollapsibleContent>
|
|
92
|
-
</Collapsible>
|
|
71
|
+
function PartCard({
|
|
72
|
+
title,
|
|
73
|
+
example,
|
|
74
|
+
description,
|
|
75
|
+
}: {
|
|
76
|
+
title: string
|
|
77
|
+
example: React.ReactNode
|
|
78
|
+
description: React.ReactNode
|
|
79
|
+
}) {
|
|
80
|
+
return (
|
|
81
|
+
<div className="space-y-3">
|
|
82
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
83
|
+
{title}
|
|
84
|
+
</h4>
|
|
85
|
+
<div className="border-fm-divider-secondary bg-fm-surface-primary rounded-xl border p-4">
|
|
86
|
+
{example}
|
|
87
|
+
</div>
|
|
88
|
+
<InfoBox>{description}</InfoBox>
|
|
93
89
|
</div>
|
|
94
|
-
)
|
|
90
|
+
)
|
|
95
91
|
}
|
|
96
92
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
<div className="
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
disabled.
|
|
107
|
-
</p>
|
|
108
|
-
</div>
|
|
109
|
-
</CollapsibleContent>
|
|
110
|
-
</Collapsible>
|
|
93
|
+
function TrackMeta() {
|
|
94
|
+
return (
|
|
95
|
+
<div className="space-y-1 pt-4">
|
|
96
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
97
|
+
Midnight Rain
|
|
98
|
+
</p>
|
|
99
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
100
|
+
Taylor Swift · Midnights · 2:53
|
|
101
|
+
</p>
|
|
111
102
|
</div>
|
|
112
|
-
)
|
|
103
|
+
)
|
|
113
104
|
}
|
|
114
105
|
|
|
115
|
-
|
|
116
|
-
render: () => (
|
|
117
|
-
<div className="w-[800px]">
|
|
118
|
-
<Collapsible>
|
|
119
|
-
<div className="flex items-center justify-between gap-2">
|
|
120
|
-
<CollapsibleTitle>Advanced Settings</CollapsibleTitle>
|
|
121
|
-
<CollapsibleTrigger asChild>
|
|
122
|
-
<IconButton
|
|
123
|
-
variant="ghost"
|
|
124
|
-
size="small"
|
|
125
|
-
icon={
|
|
126
|
-
<AngleDownIcon className="toggle-icon" height={32} width={32} />
|
|
127
|
-
}
|
|
128
|
-
label="Toggle Settings"
|
|
129
|
-
className="text-fm-icon-active disabled:text-fm-icon-inactive flex [&>.toggle-icon]:transition-transform [&>.toggle-icon]:duration-50 data-[state=open]:[&>.toggle-icon]:-rotate-180"
|
|
130
|
-
/>
|
|
131
|
-
</CollapsibleTrigger>
|
|
132
|
-
</div>
|
|
133
|
-
<CollapsibleContent>
|
|
134
|
-
<div className="pt-4">
|
|
135
|
-
<p>
|
|
136
|
-
Custom trigger button with settings icon that rotates 45 degrees
|
|
137
|
-
when opened.
|
|
138
|
-
</p>
|
|
139
|
-
</div>
|
|
140
|
-
</CollapsibleContent>
|
|
141
|
-
</Collapsible>
|
|
142
|
-
</div>
|
|
143
|
-
),
|
|
144
|
-
}
|
|
106
|
+
// ─── Parts ───────────────────────────────────────────────────────────────────
|
|
145
107
|
|
|
146
|
-
export const
|
|
108
|
+
export const Parts: Story = {
|
|
109
|
+
parameters: {
|
|
110
|
+
docs: {
|
|
111
|
+
description: {
|
|
112
|
+
story:
|
|
113
|
+
"The compound parts demonstrated in valid compositions so each piece is visible and interactive in context.",
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
147
117
|
render: () => (
|
|
148
|
-
<div className="
|
|
149
|
-
<
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
<div className="
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
118
|
+
<div className="space-y-10">
|
|
119
|
+
<PartCard
|
|
120
|
+
title="CollapsibleTitle"
|
|
121
|
+
example={
|
|
122
|
+
<div className="space-y-3">
|
|
123
|
+
<CollapsibleTitle>Track Information</CollapsibleTitle>
|
|
124
|
+
<p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
|
|
125
|
+
Standalone title styling for section headings.
|
|
156
126
|
</p>
|
|
157
127
|
</div>
|
|
158
|
-
|
|
159
|
-
|
|
128
|
+
}
|
|
129
|
+
description={
|
|
130
|
+
<>
|
|
131
|
+
Renders the heading text for a collapsible section. By default it
|
|
132
|
+
maps to <code><h2></code> and provides the large title
|
|
133
|
+
treatment used in the header row.
|
|
134
|
+
</>
|
|
135
|
+
}
|
|
136
|
+
/>
|
|
160
137
|
|
|
161
|
-
<
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
<
|
|
165
|
-
<
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
138
|
+
<PartCard
|
|
139
|
+
title="CollapsibleTrigger"
|
|
140
|
+
example={
|
|
141
|
+
<Collapsible className="border-0 pb-0" defaultOpen>
|
|
142
|
+
<div className="space-y-3">
|
|
143
|
+
<div className="flex items-center gap-3">
|
|
144
|
+
<CollapsibleTrigger asChild>
|
|
145
|
+
<button className="text-fm-primary border-fm-divider-secondary bg-fm-surface-secondary flex items-center gap-2 rounded-lg border px-3 py-2 [&>.toggle-icon]:transition-transform [&>.toggle-icon]:duration-150 data-[state=open]:[&>.toggle-icon]:-rotate-180">
|
|
146
|
+
<span className="font-fm-text text-fm-sm leading-fm-sm">
|
|
147
|
+
Toggle Details
|
|
148
|
+
</span>
|
|
149
|
+
<AngleDownIcon
|
|
150
|
+
className="toggle-icon text-fm-icon-active"
|
|
151
|
+
height={20}
|
|
152
|
+
width={20}
|
|
153
|
+
/>
|
|
154
|
+
</button>
|
|
155
|
+
</CollapsibleTrigger>
|
|
156
|
+
<p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
|
|
157
|
+
Custom trigger using <code>asChild</code>
|
|
158
|
+
</p>
|
|
159
|
+
</div>
|
|
160
|
+
<CollapsibleContent>
|
|
161
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-3">
|
|
162
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
163
|
+
Clicking the trigger collapses and reveals this panel.
|
|
164
|
+
</p>
|
|
165
|
+
</div>
|
|
166
|
+
</CollapsibleContent>
|
|
167
|
+
</div>
|
|
168
|
+
</Collapsible>
|
|
169
|
+
}
|
|
170
|
+
description={
|
|
171
|
+
<>
|
|
172
|
+
The trigger controls the open state. Here it is rendered with{" "}
|
|
173
|
+
<code>asChild</code> so the toggle state is visible on a custom
|
|
174
|
+
button while still using the same collapsible trigger primitive.
|
|
175
|
+
</>
|
|
176
|
+
}
|
|
177
|
+
/>
|
|
172
178
|
|
|
173
|
-
<
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
<
|
|
177
|
-
<
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
179
|
+
<PartCard
|
|
180
|
+
title="CollapsibleHeader"
|
|
181
|
+
example={
|
|
182
|
+
<Collapsible className="border-0 pb-0">
|
|
183
|
+
<CollapsibleHeader title="EQ Settings" />
|
|
184
|
+
<CollapsibleContent>
|
|
185
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-3">
|
|
186
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
187
|
+
The full header row acts as the trigger.
|
|
188
|
+
</p>
|
|
189
|
+
</div>
|
|
190
|
+
</CollapsibleContent>
|
|
191
|
+
</Collapsible>
|
|
192
|
+
}
|
|
193
|
+
description={
|
|
194
|
+
<>
|
|
195
|
+
A convenience wrapper that combines <code>CollapsibleTitle</code>{" "}
|
|
196
|
+
and <code>CollapsibleTrigger</code> into one clickable header row.
|
|
197
|
+
</>
|
|
198
|
+
}
|
|
199
|
+
/>
|
|
187
200
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
<p className="text-sm">Starting at $29/month for basic plan</p>
|
|
201
|
+
<PartCard
|
|
202
|
+
title="CollapsibleContent"
|
|
203
|
+
example={
|
|
204
|
+
<Collapsible defaultOpen className="border-0 pb-0">
|
|
205
|
+
<CollapsibleHeader title="Current EQ Preset" />
|
|
206
|
+
<CollapsibleContent>
|
|
207
|
+
<div className="space-y-2 pt-4">
|
|
208
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
209
|
+
Warm Vocal Boost
|
|
210
|
+
</p>
|
|
211
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
212
|
+
Bass 80 Hz · +3 dB
|
|
213
|
+
</p>
|
|
214
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
215
|
+
Mid 1 kHz · 0 dB
|
|
216
|
+
</p>
|
|
217
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
218
|
+
Treble 10 kHz · −2 dB
|
|
219
|
+
</p>
|
|
208
220
|
</div>
|
|
209
|
-
</
|
|
210
|
-
</
|
|
211
|
-
|
|
212
|
-
|
|
221
|
+
</CollapsibleContent>
|
|
222
|
+
</Collapsible>
|
|
223
|
+
}
|
|
224
|
+
description={
|
|
225
|
+
<>
|
|
226
|
+
The content region is the expandable body. It stays mounted within
|
|
227
|
+
the collapsible and becomes visible when the section is opened.
|
|
228
|
+
</>
|
|
229
|
+
}
|
|
230
|
+
/>
|
|
213
231
|
</div>
|
|
214
232
|
),
|
|
215
233
|
}
|
|
216
234
|
|
|
217
|
-
|
|
218
|
-
render: () => (
|
|
219
|
-
<div className="w-[800px]">
|
|
220
|
-
<Collapsible className="rounded-lg border-2 border-blue-200 bg-blue-50 p-4">
|
|
221
|
-
<div className="flex items-center justify-between gap-2">
|
|
222
|
-
<CollapsibleTitle className="font-bold text-blue-800">
|
|
223
|
-
Important Notice
|
|
224
|
-
</CollapsibleTitle>
|
|
225
|
-
<CollapsibleTrigger asChild>
|
|
226
|
-
<IconButton
|
|
227
|
-
variant="ghost"
|
|
228
|
-
size="small"
|
|
229
|
-
className="text-blue-600 hover:bg-blue-100"
|
|
230
|
-
icon={
|
|
231
|
-
<AngleDownIcon className="transition-transform duration-200 data-[state=open]:rotate-180" />
|
|
232
|
-
}
|
|
233
|
-
label="Toggle Notice"
|
|
234
|
-
/>
|
|
235
|
-
</CollapsibleTrigger>
|
|
236
|
-
</div>
|
|
237
|
-
<CollapsibleContent className="text-blue-700">
|
|
238
|
-
<div className="pt-4">
|
|
239
|
-
<p>
|
|
240
|
-
This is an important system notification with custom styling. The
|
|
241
|
-
entire collapsible has a blue theme to draw attention to critical
|
|
242
|
-
information.
|
|
243
|
-
</p>
|
|
244
|
-
</div>
|
|
245
|
-
</CollapsibleContent>
|
|
246
|
-
</Collapsible>
|
|
247
|
-
</div>
|
|
248
|
-
),
|
|
249
|
-
}
|
|
235
|
+
// ─── States ──────────────────────────────────────────────────────────────────
|
|
250
236
|
|
|
251
|
-
export const
|
|
237
|
+
export const States: Story = {
|
|
238
|
+
parameters: {
|
|
239
|
+
docs: {
|
|
240
|
+
description: {
|
|
241
|
+
story:
|
|
242
|
+
"Open, closed, and disabled states side by side, using realistic content so each state reads clearly.",
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
},
|
|
252
246
|
render: () => (
|
|
253
|
-
<div className="
|
|
254
|
-
<
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
voluptatem sequi nesciunt.
|
|
247
|
+
<div className="space-y-8">
|
|
248
|
+
<div className="space-y-3">
|
|
249
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
250
|
+
Open
|
|
251
|
+
</h4>
|
|
252
|
+
<Collapsible defaultOpen>
|
|
253
|
+
<CollapsibleHeader title="Now Playing" />
|
|
254
|
+
<CollapsibleContent>
|
|
255
|
+
<TrackMeta />
|
|
256
|
+
</CollapsibleContent>
|
|
257
|
+
</Collapsible>
|
|
258
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm text-center">
|
|
259
|
+
Default Open
|
|
260
|
+
</p>
|
|
261
|
+
</div>
|
|
262
|
+
|
|
263
|
+
<div className="space-y-3">
|
|
264
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
265
|
+
Closed
|
|
266
|
+
</h4>
|
|
267
|
+
<Collapsible>
|
|
268
|
+
<CollapsibleHeader title="Playlist Details" />
|
|
269
|
+
<CollapsibleContent>
|
|
270
|
+
<div className="pt-4">
|
|
271
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
272
|
+
Hidden until expanded
|
|
280
273
|
</p>
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
274
|
+
</div>
|
|
275
|
+
</CollapsibleContent>
|
|
276
|
+
</Collapsible>
|
|
277
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm text-center">
|
|
278
|
+
Default closed
|
|
279
|
+
</p>
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
<div className="space-y-3">
|
|
283
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
284
|
+
Disabled
|
|
285
|
+
</h4>
|
|
286
|
+
<Collapsible disabled>
|
|
287
|
+
<CollapsibleHeader title="Locked Section" />
|
|
288
|
+
<CollapsibleContent>
|
|
289
|
+
<div className="pt-4">
|
|
290
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
291
|
+
This content cannot be expanded while disabled.
|
|
286
292
|
</p>
|
|
287
293
|
</div>
|
|
288
|
-
</
|
|
289
|
-
</
|
|
290
|
-
|
|
294
|
+
</CollapsibleContent>
|
|
295
|
+
</Collapsible>
|
|
296
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm text-center">
|
|
297
|
+
Disabled trigger and title
|
|
298
|
+
</p>
|
|
299
|
+
</div>
|
|
291
300
|
</div>
|
|
292
301
|
),
|
|
293
302
|
}
|
|
294
303
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
304
|
+
// ─── Interactive ─────────────────────────────────────────────────────────────
|
|
305
|
+
|
|
306
|
+
export const Interactive: Story = {
|
|
307
|
+
parameters: {
|
|
308
|
+
docs: {
|
|
309
|
+
description: {
|
|
310
|
+
story:
|
|
311
|
+
"A multi-panel audio settings surface with local state controls for opening individual panels or expanding everything at once.",
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
render: () => {
|
|
316
|
+
const sections = [
|
|
317
|
+
{
|
|
318
|
+
id: "track",
|
|
319
|
+
title: "Track Info",
|
|
320
|
+
content: (
|
|
321
|
+
<div className="space-y-3 pt-4">
|
|
322
|
+
{[
|
|
323
|
+
["Title", "Midnight Rain"],
|
|
324
|
+
["Artist", "Taylor Swift"],
|
|
325
|
+
["Album", "Midnights"],
|
|
326
|
+
["Duration", "2:53"],
|
|
327
|
+
].map(([label, value]) => (
|
|
328
|
+
<div key={label} className="flex items-center justify-between">
|
|
329
|
+
<span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
330
|
+
{label}
|
|
331
|
+
</span>
|
|
332
|
+
<span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
333
|
+
{value}
|
|
334
|
+
</span>
|
|
335
|
+
</div>
|
|
336
|
+
))}
|
|
337
|
+
</div>
|
|
338
|
+
),
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
id: "eq",
|
|
342
|
+
title: "EQ Settings",
|
|
343
|
+
content: (
|
|
344
|
+
<div className="space-y-3 pt-4">
|
|
345
|
+
{[
|
|
346
|
+
["Sub-Bass", "60 Hz · +2 dB"],
|
|
347
|
+
["Bass", "250 Hz · +4 dB"],
|
|
348
|
+
["Mid", "1 kHz · 0 dB"],
|
|
349
|
+
["Presence", "4 kHz · −1 dB"],
|
|
350
|
+
["Treble", "10 kHz · −3 dB"],
|
|
351
|
+
].map(([label, value]) => (
|
|
352
|
+
<div key={label} className="flex items-center justify-between">
|
|
353
|
+
<span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
354
|
+
{label}
|
|
355
|
+
</span>
|
|
356
|
+
<span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
357
|
+
{value}
|
|
358
|
+
</span>
|
|
359
|
+
</div>
|
|
360
|
+
))}
|
|
361
|
+
</div>
|
|
362
|
+
),
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
id: "playlist",
|
|
366
|
+
title: "Playlist Details",
|
|
367
|
+
content: (
|
|
301
368
|
<div className="space-y-2 pt-4">
|
|
302
|
-
|
|
369
|
+
{[
|
|
370
|
+
"Anti-Hero",
|
|
371
|
+
"Lavender Haze",
|
|
372
|
+
"Midnight Rain",
|
|
373
|
+
"Question...?",
|
|
374
|
+
"Vigilante Shit",
|
|
375
|
+
].map((track, index) => (
|
|
376
|
+
<div key={track} className="flex items-center gap-3">
|
|
377
|
+
<span className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm w-5 text-right">
|
|
378
|
+
{index + 1}
|
|
379
|
+
</span>
|
|
380
|
+
<span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
381
|
+
{track}
|
|
382
|
+
</span>
|
|
383
|
+
</div>
|
|
384
|
+
))}
|
|
385
|
+
</div>
|
|
386
|
+
),
|
|
387
|
+
},
|
|
388
|
+
]
|
|
303
389
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
</CollapsibleContent>
|
|
311
|
-
</Collapsible>
|
|
390
|
+
const Demo = () => {
|
|
391
|
+
const [openMap, setOpenMap] = useState<Record<string, boolean>>({
|
|
392
|
+
track: true,
|
|
393
|
+
eq: false,
|
|
394
|
+
playlist: false,
|
|
395
|
+
})
|
|
312
396
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
397
|
+
const allOpen = Object.values(openMap).every(Boolean)
|
|
398
|
+
|
|
399
|
+
const togglePanel = (id: string) => {
|
|
400
|
+
setOpenMap((current) => ({ ...current, [id]: !current[id] }))
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const toggleAll = () => {
|
|
404
|
+
const nextValue = !allOpen
|
|
405
|
+
setOpenMap(
|
|
406
|
+
Object.fromEntries(sections.map(({ id }) => [id, nextValue]))
|
|
407
|
+
)
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return (
|
|
411
|
+
<div className="w-full p-8">
|
|
412
|
+
<div className="mx-auto max-w-3xl space-y-6">
|
|
413
|
+
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
|
414
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-5 rounded-xl border p-5">
|
|
415
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
|
|
416
|
+
Panels
|
|
417
|
+
</p>
|
|
418
|
+
{sections.map(({ id, title }) => (
|
|
419
|
+
<button
|
|
420
|
+
key={id}
|
|
421
|
+
onClick={() => togglePanel(id)}
|
|
422
|
+
className="border-fm-divider-secondary bg-fm-surface-primary text-fm-primary font-fm-text text-fm-sm leading-fm-sm hover:border-fm-divider-primary w-full rounded-lg border px-4 py-2 text-left transition-colors"
|
|
423
|
+
>
|
|
424
|
+
{openMap[id] ? "Close" : "Open"} {title}
|
|
425
|
+
</button>
|
|
426
|
+
))}
|
|
427
|
+
<div className="border-fm-divider-secondary border-t pt-4" />
|
|
428
|
+
<button
|
|
429
|
+
onClick={toggleAll}
|
|
430
|
+
className="border-fm-divider-primary text-fm-primary font-fm-text text-fm-sm leading-fm-sm hover:bg-fm-surface-primary w-full rounded-lg border px-4 py-2 transition-colors"
|
|
431
|
+
>
|
|
432
|
+
{allOpen ? "Collapse All" : "Expand All"}
|
|
433
|
+
</button>
|
|
434
|
+
</div>
|
|
435
|
+
|
|
436
|
+
<div className="flex flex-col gap-3 lg:col-span-2">
|
|
437
|
+
<div className="space-y-0">
|
|
438
|
+
{sections.map(({ id, title, content }) => (
|
|
439
|
+
<Collapsible
|
|
440
|
+
key={id}
|
|
441
|
+
open={openMap[id]}
|
|
442
|
+
onOpenChange={(open) =>
|
|
443
|
+
setOpenMap((current) => ({ ...current, [id]: open }))
|
|
444
|
+
}
|
|
445
|
+
>
|
|
446
|
+
<CollapsibleHeader title={title} />
|
|
447
|
+
<CollapsibleContent>{content}</CollapsibleContent>
|
|
448
|
+
</Collapsible>
|
|
449
|
+
))}
|
|
318
450
|
</div>
|
|
319
|
-
|
|
320
|
-
|
|
451
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
452
|
+
<code className="text-fm-secondary text-fm-md leading-fm-md font-[var(--font-fm-mono)]">
|
|
453
|
+
{`openMap = ${JSON.stringify(openMap)}`}
|
|
454
|
+
</code>
|
|
455
|
+
</div>
|
|
456
|
+
</div>
|
|
457
|
+
</div>
|
|
321
458
|
</div>
|
|
322
|
-
</
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
459
|
+
</div>
|
|
460
|
+
)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return <Demo />
|
|
464
|
+
},
|
|
326
465
|
}
|