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,216 +1,395 @@
|
|
|
1
1
|
import React, { useState } from "react"
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
3
3
|
|
|
4
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
5
|
+
|
|
4
6
|
import { Case, Default, SwitchCase } from "."
|
|
5
7
|
|
|
6
|
-
const meta = {
|
|
8
|
+
const meta: Meta<typeof SwitchCase> = {
|
|
7
9
|
title: "Components/Logical/SwitchCase",
|
|
8
10
|
component: SwitchCase,
|
|
9
11
|
parameters: {
|
|
10
12
|
layout: "centered",
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component:
|
|
16
|
+
"A utility component for switch/case-like conditional rendering. Accepts a `value` prop and renders the matching `<Case value={…}>` child. Falls back to a `<Default>` sub-component or the `default` prop when no case matches. Eliminates verbose ternary chains for multi-branch conditional UI.",
|
|
17
|
+
},
|
|
18
|
+
page: () => (
|
|
19
|
+
<AuralComponentDocsPage
|
|
20
|
+
features={[
|
|
21
|
+
{
|
|
22
|
+
title: "Case Matching",
|
|
23
|
+
description: "Renders matched Case child",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
title: "Default Fallback",
|
|
27
|
+
description: "Default or default prop",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
title: "Zero DOM Node",
|
|
31
|
+
description: "No wrapper element",
|
|
32
|
+
},
|
|
33
|
+
]}
|
|
34
|
+
/>
|
|
35
|
+
),
|
|
17
36
|
},
|
|
18
37
|
},
|
|
19
38
|
tags: ["autodocs"],
|
|
20
|
-
}
|
|
39
|
+
}
|
|
21
40
|
|
|
22
41
|
export default meta
|
|
23
42
|
type Story = StoryObj<typeof meta>
|
|
24
43
|
|
|
25
|
-
//
|
|
26
|
-
export const BasicExample: Story = {
|
|
27
|
-
args: {
|
|
28
|
-
value: "success",
|
|
29
|
-
children: [
|
|
30
|
-
<Case key="loading" value="loading">
|
|
31
|
-
Loading...
|
|
32
|
-
</Case>,
|
|
33
|
-
<Case key="error" value="error">
|
|
34
|
-
An error occurred!
|
|
35
|
-
</Case>,
|
|
36
|
-
<Case key="success" value="success">
|
|
37
|
-
Data loaded successfully!
|
|
38
|
-
</Case>,
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Example with default prop
|
|
44
|
-
export const WithDefaultProp: Story = {
|
|
45
|
-
args: {
|
|
46
|
-
value: "other",
|
|
47
|
-
default: <div style={{ color: "gray" }}>Unknown value selected</div>,
|
|
48
|
-
children: [
|
|
49
|
-
<Case key="one" value="one">
|
|
50
|
-
Option One
|
|
51
|
-
</Case>,
|
|
52
|
-
<Case key="two" value="two">
|
|
53
|
-
Option Two
|
|
54
|
-
</Case>,
|
|
55
|
-
<Case key="three" value="three">
|
|
56
|
-
Option Three
|
|
57
|
-
</Case>,
|
|
58
|
-
],
|
|
59
|
-
},
|
|
60
|
-
}
|
|
44
|
+
// ─── 1. Configurations ────────────────────────────────────────────────────────
|
|
61
45
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
</
|
|
46
|
+
export const Configurations: Story = {
|
|
47
|
+
render: () => (
|
|
48
|
+
<div className="space-y-8">
|
|
49
|
+
{/* Matching case */}
|
|
50
|
+
<div className="space-y-4">
|
|
51
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
52
|
+
Matching case renders
|
|
53
|
+
</h4>
|
|
54
|
+
<div className="flex flex-wrap gap-6">
|
|
55
|
+
{(["loading", "success", "error"] as const).map((status) => (
|
|
56
|
+
<div key={status} className="space-y-2 text-center">
|
|
57
|
+
<SwitchCase value={status}>
|
|
58
|
+
<Case value="loading">
|
|
59
|
+
<div className="bg-fm-surface-info-sec rounded-lg px-4 py-3">
|
|
60
|
+
<p className="text-fm-info-sec font-fm-text text-fm-md leading-fm-md">
|
|
61
|
+
Loading…
|
|
62
|
+
</p>
|
|
63
|
+
</div>
|
|
64
|
+
</Case>
|
|
65
|
+
<Case value="success">
|
|
66
|
+
<div className="bg-fm-surface-positive-sec rounded-lg px-4 py-3">
|
|
67
|
+
<p className="text-fm-positive-sec font-fm-text text-fm-md leading-fm-md">
|
|
68
|
+
Success
|
|
69
|
+
</p>
|
|
70
|
+
</div>
|
|
71
|
+
</Case>
|
|
72
|
+
<Case value="error">
|
|
73
|
+
<div className="bg-fm-surface-negative-sec rounded-lg px-4 py-3">
|
|
74
|
+
<p className="text-fm-negative-sec font-fm-text text-fm-md leading-fm-md">
|
|
75
|
+
Error
|
|
76
|
+
</p>
|
|
77
|
+
</div>
|
|
78
|
+
</Case>
|
|
79
|
+
</SwitchCase>
|
|
80
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
81
|
+
value="{status}"
|
|
82
|
+
</p>
|
|
83
|
+
</div>
|
|
84
|
+
))}
|
|
85
|
+
</div>
|
|
102
86
|
</div>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
87
|
+
|
|
88
|
+
{/* No match — default prop fallback */}
|
|
89
|
+
<div className="space-y-4">
|
|
90
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
91
|
+
No match — default prop fallback
|
|
92
|
+
</h4>
|
|
93
|
+
<div className="flex flex-wrap gap-4">
|
|
94
|
+
<div className="space-y-2 text-center">
|
|
95
|
+
<SwitchCase
|
|
96
|
+
value="unknown"
|
|
97
|
+
default={
|
|
98
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg px-4 py-3">
|
|
99
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-md">
|
|
100
|
+
Unknown value — default prop used
|
|
101
|
+
</p>
|
|
102
|
+
</div>
|
|
103
|
+
}
|
|
104
|
+
>
|
|
105
|
+
<Case value="one">Option One</Case>
|
|
106
|
+
<Case value="two">Option Two</Case>
|
|
107
|
+
</SwitchCase>
|
|
108
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
109
|
+
value="unknown" → default prop
|
|
110
|
+
</p>
|
|
111
|
+
</div>
|
|
112
112
|
</div>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
{/* No match — Default sub-component fallback */}
|
|
116
|
+
<div className="space-y-4">
|
|
117
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
118
|
+
No match — <Default> sub-component fallback
|
|
119
|
+
</h4>
|
|
120
|
+
<div className="flex flex-wrap gap-4">
|
|
121
|
+
<div className="space-y-2 text-center">
|
|
122
|
+
<SwitchCase value="other">
|
|
123
|
+
<Case value="apple">
|
|
124
|
+
<div className="bg-fm-surface-positive-sec rounded-lg px-4 py-3">
|
|
125
|
+
<p className="text-fm-positive-sec font-fm-text text-fm-md leading-fm-md">
|
|
126
|
+
Apple selected
|
|
127
|
+
</p>
|
|
128
|
+
</div>
|
|
129
|
+
</Case>
|
|
130
|
+
<Case value="banana">
|
|
131
|
+
<div className="bg-fm-surface-warning-sec rounded-lg px-4 py-3">
|
|
132
|
+
<p className="text-fm-warning-sec font-fm-text text-fm-md leading-fm-md">
|
|
133
|
+
Banana selected
|
|
134
|
+
</p>
|
|
135
|
+
</div>
|
|
136
|
+
</Case>
|
|
137
|
+
<Default>
|
|
138
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg px-4 py-3">
|
|
139
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-md">
|
|
140
|
+
No matching case — <Default> renders
|
|
141
|
+
</p>
|
|
142
|
+
</div>
|
|
143
|
+
</Default>
|
|
144
|
+
</SwitchCase>
|
|
145
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
146
|
+
value="other" → <Default> sub-component
|
|
147
|
+
</p>
|
|
148
|
+
</div>
|
|
136
149
|
</div>
|
|
137
150
|
</div>
|
|
151
|
+
|
|
152
|
+
{/* Code reference */}
|
|
153
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
|
|
154
|
+
<code className="text-fm-secondary text-fm-md leading-fm-md font-(--font-fm-mono) whitespace-pre">{`// Matching case
|
|
155
|
+
<SwitchCase value={status}>
|
|
156
|
+
<Case value="loading"><Spinner /></Case>
|
|
157
|
+
<Case value="success"><SuccessView /></Case>
|
|
158
|
+
<Case value="error"><ErrorView /></Case>
|
|
159
|
+
</SwitchCase>
|
|
160
|
+
|
|
161
|
+
// With Default fallback
|
|
162
|
+
<SwitchCase value={role}>
|
|
163
|
+
<Case value="admin"><AdminPanel /></Case>
|
|
164
|
+
<Case value="editor"><EditorPanel /></Case>
|
|
165
|
+
<Default><ReadOnlyView /></Default>
|
|
166
|
+
</SwitchCase>`}</code>
|
|
167
|
+
</div>
|
|
138
168
|
</div>
|
|
139
|
-
)
|
|
169
|
+
),
|
|
170
|
+
parameters: {
|
|
171
|
+
docs: {
|
|
172
|
+
description: {
|
|
173
|
+
story:
|
|
174
|
+
"Three configuration modes: a matching case renders its children, an unmatched value falls back to the `default` prop, and an unmatched value falls back to the `<Default>` sub-component.",
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
},
|
|
140
178
|
}
|
|
141
179
|
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
180
|
+
// ─── 2. Use Cases ─────────────────────────────────────────────────────────────
|
|
181
|
+
|
|
182
|
+
export const UseCases: Story = {
|
|
183
|
+
render: () => {
|
|
184
|
+
const [status, setStatus] = useState<
|
|
185
|
+
"idle" | "loading" | "success" | "error"
|
|
186
|
+
>("idle")
|
|
187
|
+
|
|
188
|
+
const [role, setRole] = useState<"admin" | "editor" | "viewer">("viewer")
|
|
189
|
+
|
|
190
|
+
const [plan, setPlan] = useState<"free" | "pro" | "enterprise">("free")
|
|
191
|
+
|
|
192
|
+
return (
|
|
193
|
+
<div className="mx-auto max-w-3xl space-y-8 p-8">
|
|
194
|
+
{/* Async operation status */}
|
|
195
|
+
<div className="space-y-4">
|
|
196
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
197
|
+
Async operation status
|
|
198
|
+
</h4>
|
|
199
|
+
<div className="mx-auto max-w-md space-y-3">
|
|
200
|
+
<div className="flex flex-wrap gap-2">
|
|
201
|
+
{(["idle", "loading", "success", "error"] as const).map((s) => (
|
|
202
|
+
<button
|
|
203
|
+
key={s}
|
|
204
|
+
onClick={() => setStatus(s)}
|
|
205
|
+
className={[
|
|
206
|
+
"font-fm-text text-fm-sm leading-fm-sm cursor-pointer rounded-lg border px-3 py-1.5 capitalize transition-opacity hover:opacity-80",
|
|
207
|
+
status === s
|
|
208
|
+
? "border-fm-divider-primary text-fm-primary bg-fm-surface-secondary"
|
|
209
|
+
: "border-fm-divider-secondary text-fm-tertiary bg-fm-surface-primary",
|
|
210
|
+
].join(" ")}
|
|
211
|
+
>
|
|
212
|
+
{s}
|
|
213
|
+
</button>
|
|
214
|
+
))}
|
|
215
|
+
</div>
|
|
216
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-xl border p-4">
|
|
217
|
+
<p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm mb-3">
|
|
218
|
+
Current status:{" "}
|
|
219
|
+
<span className="text-fm-primary font-medium">{status}</span>
|
|
220
|
+
</p>
|
|
221
|
+
<SwitchCase value={status}>
|
|
222
|
+
<Case value="idle">
|
|
223
|
+
<div className="border-fm-divider-secondary rounded-lg border px-4 py-3">
|
|
224
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-md">
|
|
225
|
+
Waiting for you to start the upload…
|
|
226
|
+
</p>
|
|
227
|
+
</div>
|
|
228
|
+
</Case>
|
|
229
|
+
<Case value="loading">
|
|
230
|
+
<div className="bg-fm-surface-info-sec rounded-lg px-4 py-3">
|
|
231
|
+
<p className="text-fm-info-sec font-fm-text text-fm-md leading-fm-md">
|
|
232
|
+
Uploading your track, please wait…
|
|
233
|
+
</p>
|
|
234
|
+
</div>
|
|
235
|
+
</Case>
|
|
236
|
+
<Case value="success">
|
|
237
|
+
<div className="bg-fm-surface-positive-sec rounded-lg px-4 py-3">
|
|
238
|
+
<p className="text-fm-positive-sec font-fm-text text-fm-md leading-fm-md font-medium">
|
|
239
|
+
Track uploaded successfully!
|
|
240
|
+
</p>
|
|
241
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm mt-1">
|
|
242
|
+
Your track is now processing and will be live shortly.
|
|
243
|
+
</p>
|
|
244
|
+
</div>
|
|
245
|
+
</Case>
|
|
246
|
+
<Case value="error">
|
|
247
|
+
<div className="bg-fm-surface-negative-sec rounded-lg px-4 py-3">
|
|
248
|
+
<p className="text-fm-negative-sec font-fm-text text-fm-md leading-fm-md font-medium">
|
|
249
|
+
Upload failed
|
|
250
|
+
</p>
|
|
251
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm mt-1">
|
|
252
|
+
Something went wrong. Please check your file and try
|
|
253
|
+
again.
|
|
254
|
+
</p>
|
|
255
|
+
</div>
|
|
256
|
+
</Case>
|
|
257
|
+
</SwitchCase>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
192
260
|
</div>
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
261
|
+
|
|
262
|
+
{/* Role-based UI */}
|
|
263
|
+
<div className="space-y-4">
|
|
264
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
265
|
+
Role-based UI
|
|
266
|
+
</h4>
|
|
267
|
+
<div className="mx-auto max-w-md space-y-3">
|
|
268
|
+
<div className="flex flex-wrap gap-2">
|
|
269
|
+
{(["admin", "editor", "viewer"] as const).map((r) => (
|
|
270
|
+
<button
|
|
271
|
+
key={r}
|
|
272
|
+
onClick={() => setRole(r)}
|
|
273
|
+
className={[
|
|
274
|
+
"font-fm-text text-fm-sm leading-fm-sm cursor-pointer rounded-lg border px-3 py-1.5 capitalize transition-opacity hover:opacity-80",
|
|
275
|
+
role === r
|
|
276
|
+
? "border-fm-divider-primary text-fm-primary bg-fm-surface-secondary"
|
|
277
|
+
: "border-fm-divider-secondary text-fm-tertiary bg-fm-surface-primary",
|
|
278
|
+
].join(" ")}
|
|
279
|
+
>
|
|
280
|
+
{r}
|
|
281
|
+
</button>
|
|
282
|
+
))}
|
|
283
|
+
</div>
|
|
284
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-3 rounded-xl border p-4">
|
|
285
|
+
<p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
|
|
286
|
+
Signed in as:{" "}
|
|
287
|
+
<span className="text-fm-primary font-medium capitalize">
|
|
288
|
+
{role}
|
|
289
|
+
</span>
|
|
290
|
+
</p>
|
|
291
|
+
<SwitchCase value={role}>
|
|
292
|
+
<Case value="admin">
|
|
293
|
+
<div className="bg-fm-surface-negative-sec space-y-1 rounded-lg px-4 py-3">
|
|
294
|
+
<p className="text-fm-negative-sec font-fm-brand text-fm-md leading-fm-md font-semibold">
|
|
295
|
+
Admin panel
|
|
296
|
+
</p>
|
|
297
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
298
|
+
Full access: manage users, content, and billing.
|
|
299
|
+
</p>
|
|
300
|
+
</div>
|
|
301
|
+
</Case>
|
|
302
|
+
<Case value="editor">
|
|
303
|
+
<div className="bg-fm-surface-info-sec space-y-1 rounded-lg px-4 py-3">
|
|
304
|
+
<p className="text-fm-info-sec font-fm-brand text-fm-md leading-fm-md font-semibold">
|
|
305
|
+
Editor panel
|
|
306
|
+
</p>
|
|
307
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
308
|
+
Create and publish tracks. Cannot manage users.
|
|
309
|
+
</p>
|
|
310
|
+
</div>
|
|
311
|
+
</Case>
|
|
312
|
+
<Case value="viewer">
|
|
313
|
+
<div className="border-fm-divider-secondary space-y-1 rounded-lg border px-4 py-3">
|
|
314
|
+
<p className="text-fm-primary font-fm-brand text-fm-md leading-fm-md font-semibold">
|
|
315
|
+
Read-only view
|
|
316
|
+
</p>
|
|
317
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
318
|
+
Browse and stream content. No edit permissions.
|
|
319
|
+
</p>
|
|
320
|
+
</div>
|
|
321
|
+
</Case>
|
|
322
|
+
</SwitchCase>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
|
|
327
|
+
{/* Subscription plan */}
|
|
328
|
+
<div className="space-y-4">
|
|
329
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
330
|
+
Subscription plan display
|
|
331
|
+
</h4>
|
|
332
|
+
<div className="mx-auto max-w-md space-y-3">
|
|
333
|
+
<div className="flex flex-wrap gap-2">
|
|
334
|
+
{(["free", "pro", "enterprise"] as const).map((p) => (
|
|
335
|
+
<button
|
|
336
|
+
key={p}
|
|
337
|
+
onClick={() => setPlan(p)}
|
|
338
|
+
className={[
|
|
339
|
+
"font-fm-text text-fm-sm leading-fm-sm cursor-pointer rounded-lg border px-3 py-1.5 capitalize transition-opacity hover:opacity-80",
|
|
340
|
+
plan === p
|
|
341
|
+
? "border-fm-divider-primary text-fm-primary bg-fm-surface-secondary"
|
|
342
|
+
: "border-fm-divider-secondary text-fm-tertiary bg-fm-surface-primary",
|
|
343
|
+
].join(" ")}
|
|
344
|
+
>
|
|
345
|
+
{p}
|
|
346
|
+
</button>
|
|
347
|
+
))}
|
|
348
|
+
</div>
|
|
349
|
+
<SwitchCase value={plan}>
|
|
350
|
+
<Case value="free">
|
|
351
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-1 rounded-xl border p-4">
|
|
352
|
+
<p className="text-fm-primary font-fm-brand text-fm-lg leading-fm-lg font-semibold">
|
|
353
|
+
Free plan
|
|
354
|
+
</p>
|
|
355
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
356
|
+
5 uploads per month · Standard quality · Community support
|
|
357
|
+
</p>
|
|
358
|
+
</div>
|
|
359
|
+
</Case>
|
|
360
|
+
<Case value="pro">
|
|
361
|
+
<div className="bg-fm-surface-positive-sec space-y-1 rounded-xl p-4">
|
|
362
|
+
<p className="text-fm-positive-sec font-fm-brand text-fm-lg leading-fm-lg font-semibold">
|
|
363
|
+
Pro plan
|
|
364
|
+
</p>
|
|
365
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
366
|
+
Unlimited uploads · Lossless quality · Priority support
|
|
367
|
+
</p>
|
|
368
|
+
</div>
|
|
369
|
+
</Case>
|
|
370
|
+
<Case value="enterprise">
|
|
371
|
+
<div className="bg-fm-surface-info-sec space-y-1 rounded-xl p-4">
|
|
372
|
+
<p className="text-fm-info-sec font-fm-brand text-fm-lg leading-fm-lg font-semibold">
|
|
373
|
+
Enterprise plan
|
|
374
|
+
</p>
|
|
375
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
376
|
+
Unlimited everything · Dedicated support · Custom SLA
|
|
377
|
+
</p>
|
|
378
|
+
</div>
|
|
379
|
+
</Case>
|
|
380
|
+
</SwitchCase>
|
|
381
|
+
</div>
|
|
212
382
|
</div>
|
|
213
383
|
</div>
|
|
214
|
-
|
|
215
|
-
|
|
384
|
+
)
|
|
385
|
+
},
|
|
386
|
+
parameters: {
|
|
387
|
+
layout: "fullscreen",
|
|
388
|
+
docs: {
|
|
389
|
+
description: {
|
|
390
|
+
story:
|
|
391
|
+
"Real-world scenarios: async upload status feedback, role-based UI panels (admin / editor / viewer), and subscription plan display. Toggle the buttons to switch between cases.",
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
},
|
|
216
395
|
}
|