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,16 +1,17 @@
|
|
|
1
1
|
import React from "react"
|
|
2
2
|
import {
|
|
3
3
|
AlertIcon,
|
|
4
|
-
CrossIcon,
|
|
5
|
-
EditBigIcon,
|
|
6
|
-
EyeOpenIcon,
|
|
7
4
|
FileChartIcon,
|
|
8
|
-
|
|
5
|
+
HeartIcon,
|
|
6
|
+
MusicalNoteIcon,
|
|
9
7
|
SearchIcon,
|
|
10
|
-
|
|
8
|
+
SettingIcon,
|
|
9
|
+
StarIcon,
|
|
11
10
|
} from "@icons/index"
|
|
12
11
|
import type { Meta, StoryObj } from "@storybook/react-vite"
|
|
13
12
|
|
|
13
|
+
import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
|
|
14
|
+
|
|
14
15
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "."
|
|
15
16
|
|
|
16
17
|
const meta: Meta<typeof Tabs> = {
|
|
@@ -27,168 +28,27 @@ const meta: Meta<typeof Tabs> = {
|
|
|
27
28
|
},
|
|
28
29
|
docs: {
|
|
29
30
|
description: {
|
|
30
|
-
component:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
A beautiful and accessible tabs component built on top of Radix UI's Tabs primitive with custom styling and animations. Features smooth tab transitions, hover effects, and a stunning gradient glow for active tabs.
|
|
34
|
-
|
|
35
|
-
## Components
|
|
36
|
-
|
|
37
|
-
### Core Components
|
|
38
|
-
- **Tabs**: Root container for the entire tabs system with size context
|
|
39
|
-
- **TabsList**: Container for all tab triggers
|
|
40
|
-
- **TabsTrigger**: Individual tab buttons with custom glow effects
|
|
41
|
-
- **TabsContent**: Content panels that display when tabs are active
|
|
42
|
-
|
|
43
|
-
## Features
|
|
44
|
-
|
|
45
|
-
- **Gradient Glow Effects**: Beautiful radial gradient with blur effects on active tabs
|
|
46
|
-
- **Smooth Animations**: Fade in/out transitions between active and inactive states
|
|
47
|
-
- **Size Variants**: Small, medium, and large tab sizes via context
|
|
48
|
-
- **Keyboard Accessible**: Full keyboard navigation support
|
|
49
|
-
- **Screen Reader Support**: Proper ARIA attributes and announcements
|
|
50
|
-
- **Custom Styling**: Tailored design system integration
|
|
51
|
-
- **Responsive Design**: Adapts to different screen sizes
|
|
52
|
-
- **Icon Support**: Built-in support for icons in tab labels
|
|
53
|
-
|
|
54
|
-
## Size Variants
|
|
55
|
-
|
|
56
|
-
### Small (sm)
|
|
57
|
-
- Font size: var(--text-fm-md)
|
|
58
|
-
- Padding: 8px (p-2)
|
|
59
|
-
- Ideal for: Compact interfaces, sidebars
|
|
60
|
-
|
|
61
|
-
### Medium (md) - Default
|
|
62
|
-
- Font size: var(--text-fm-xl)
|
|
63
|
-
- Padding: 12px horizontal, 16px top, 12px bottom
|
|
64
|
-
- Ideal for: Main navigation, content sections
|
|
65
|
-
|
|
66
|
-
### Large (lg)
|
|
67
|
-
- Font size: var(--text-fm-2xl)
|
|
68
|
-
- Padding: 12px horizontal, 16px top, 12px bottom
|
|
69
|
-
- Ideal for: Primary navigation, hero sections
|
|
70
|
-
|
|
71
|
-
## Visual Effects
|
|
72
|
-
|
|
73
|
-
### Active Tab Glow
|
|
74
|
-
The active tab features a stunning dual-layer gradient effect with configurable direction:
|
|
75
|
-
- **Glow Direction**: Choose between "bottom" (default) or "top" glow positioning
|
|
76
|
-
- **Bottom Layer**: Curved gradient line at the tab base
|
|
77
|
-
- **Top Layer**: Blurred elliptical glow with screen blend mode
|
|
78
|
-
- **Colors**: Red to purple to black gradient (#FF3E4C → #5200A3 → #0A0A0A)
|
|
79
|
-
|
|
80
|
-
### Animations
|
|
81
|
-
- **Fade In**: Active tabs fade in with animate-fm-fadeIn
|
|
82
|
-
- **Fade Out**: Inactive tabs fade out with animate-fm-fadeOut
|
|
83
|
-
- **Smooth Transitions**: Color and glow transitions
|
|
84
|
-
|
|
85
|
-
## Usage Examples
|
|
86
|
-
|
|
87
|
-
### Basic Tabs with Size
|
|
88
|
-
\`\`\`tsx
|
|
89
|
-
<Tabs defaultValue="tab1" size="lg">
|
|
90
|
-
<TabsList>
|
|
91
|
-
<TabsTrigger value="tab1">Tab 1</TabsTrigger>
|
|
92
|
-
<TabsTrigger value="tab2">Tab 2</TabsTrigger>
|
|
93
|
-
</TabsList>
|
|
94
|
-
<TabsContent value="tab1">Content 1</TabsContent>
|
|
95
|
-
<TabsContent value="tab2">Content 2</TabsContent>
|
|
96
|
-
</Tabs>
|
|
97
|
-
\`\`\`
|
|
98
|
-
|
|
99
|
-
### With Icons
|
|
100
|
-
\`\`\`tsx
|
|
101
|
-
<Tabs defaultValue="dashboard" size="md">
|
|
102
|
-
<TabsList>
|
|
103
|
-
<TabsTrigger value="dashboard">
|
|
104
|
-
<BarChart className="w-4 h-4" />
|
|
105
|
-
Dashboard
|
|
106
|
-
</TabsTrigger>
|
|
107
|
-
<TabsTrigger value="settings">
|
|
108
|
-
<Settings className="w-4 h-4" />
|
|
109
|
-
Settings
|
|
110
|
-
</TabsTrigger>
|
|
111
|
-
</TabsList>
|
|
112
|
-
<TabsContent value="dashboard">Dashboard content</TabsContent>
|
|
113
|
-
<TabsContent value="settings">Settings content</TabsContent>
|
|
114
|
-
</Tabs>
|
|
115
|
-
\`\`\`
|
|
116
|
-
|
|
117
|
-
### With Glow Direction
|
|
118
|
-
\`\`\`tsx
|
|
119
|
-
<Tabs defaultValue="overview" size="md">
|
|
120
|
-
<TabsList>
|
|
121
|
-
<TabsTrigger value="overview" glowDirection="bottom">Overview</TabsTrigger>
|
|
122
|
-
<TabsTrigger value="analytics" glowDirection="top">Analytics</TabsTrigger>
|
|
123
|
-
<TabsTrigger value="settings" glowDirection="bottom">Settings</TabsTrigger>
|
|
124
|
-
</TabsList>
|
|
125
|
-
<TabsContent value="overview">Overview content</TabsContent>
|
|
126
|
-
<TabsContent value="analytics">Analytics content</TabsContent>
|
|
127
|
-
<TabsContent value="settings">Settings content</TabsContent>
|
|
128
|
-
</Tabs>
|
|
129
|
-
\`\`\`
|
|
130
|
-
|
|
131
|
-
### Individual Size Override
|
|
132
|
-
\`\`\`tsx
|
|
133
|
-
<Tabs defaultValue="home" size="md">
|
|
134
|
-
<TabsList>
|
|
135
|
-
<TabsTrigger value="home">Home</TabsTrigger>
|
|
136
|
-
<TabsTrigger value="about" size="lg">About (Large)</TabsTrigger>
|
|
137
|
-
</TabsList>
|
|
138
|
-
<TabsContent value="home">Home content</TabsContent>
|
|
139
|
-
<TabsContent value="about">About content</TabsContent>
|
|
140
|
-
</Tabs>
|
|
141
|
-
\`\`\`
|
|
142
|
-
|
|
143
|
-
## Props
|
|
144
|
-
|
|
145
|
-
### Tabs Props
|
|
146
|
-
- **size**: "sm" | "md" | "lg" - Sets the size for all child TabsTrigger components
|
|
147
|
-
- **defaultValue**: string - The default active tab
|
|
148
|
-
- **value**: string - Controlled active tab value
|
|
149
|
-
- **onValueChange**: (value: string) => void - Callback when tab changes
|
|
150
|
-
|
|
151
|
-
### TabsTrigger Props
|
|
152
|
-
- **size**: "sm" | "md" | "lg" - Optional override for individual triggers
|
|
153
|
-
- **glowDirection**: "bottom" | "top" - Direction of the glow effect (default: "bottom")
|
|
154
|
-
- **value**: string - Unique identifier for the tab
|
|
155
|
-
- **disabled**: boolean - Disable the tab trigger
|
|
156
|
-
|
|
157
|
-
## Accessibility
|
|
158
|
-
|
|
159
|
-
- **Keyboard Navigation**: Arrow keys to move between tabs, Space/Enter to activate
|
|
160
|
-
- **Screen Reader Support**: Proper ARIA labels and announcements
|
|
161
|
-
- **Focus Management**: Clear focus indicators and logical tab order
|
|
162
|
-
- **Role Attributes**: Correct tab, tablist, and tabpanel roles
|
|
163
|
-
- **State Announcements**: Active/inactive states announced to screen readers
|
|
164
|
-
|
|
165
|
-
## Design System Integration
|
|
166
|
-
|
|
167
|
-
- **Color Tokens**: Uses design system color tokens (fm-primary, fm-tertiary, etc.)
|
|
168
|
-
- **Typography**: Integrated with font size and leading variables
|
|
169
|
-
- **Focus States**: Consistent focus ring styling
|
|
170
|
-
- **Transitions**: Smooth color and effect transitions
|
|
171
|
-
- **Border Styles**: Consistent with design system borders
|
|
172
|
-
|
|
173
|
-
## Best Practices
|
|
174
|
-
|
|
175
|
-
- Keep tab labels concise and descriptive
|
|
176
|
-
- Use icons to improve visual hierarchy
|
|
177
|
-
- Don't use more than 7-8 tabs in a single group
|
|
178
|
-
- Ensure tab content is substantial enough to warrant separation
|
|
179
|
-
- Test keyboard navigation thoroughly
|
|
180
|
-
- Consider mobile responsive behavior
|
|
181
|
-
- Use consistent sizing throughout your application
|
|
182
|
-
- Set size on Tabs component instead of individual triggers
|
|
183
|
-
|
|
184
|
-
## Performance
|
|
185
|
-
|
|
186
|
-
- **Lazy Loading**: Content panels only render when active
|
|
187
|
-
- **Efficient Re-renders**: Optimized state management with context
|
|
188
|
-
- **CSS Animations**: Hardware-accelerated animations
|
|
189
|
-
- **Minimal DOM**: Clean, semantic HTML structure
|
|
190
|
-
`,
|
|
31
|
+
component:
|
|
32
|
+
"A compound tabs component built on Radix UI Tabs with gradient glow effects on active triggers, smooth fade animations, and three size variants. Supports bottom and top glow directions and per-trigger size overrides via a shared size context.",
|
|
191
33
|
},
|
|
34
|
+
page: () => (
|
|
35
|
+
<AuralComponentDocsPage
|
|
36
|
+
features={[
|
|
37
|
+
{
|
|
38
|
+
title: "Gradient Glow",
|
|
39
|
+
description: "Active trigger effect",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
title: "3 Sizes",
|
|
43
|
+
description: "sm, md, lg via context",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
title: "Fade Animation",
|
|
47
|
+
description: "Smooth content switch",
|
|
48
|
+
},
|
|
49
|
+
]}
|
|
50
|
+
/>
|
|
51
|
+
),
|
|
192
52
|
},
|
|
193
53
|
},
|
|
194
54
|
tags: ["autodocs"],
|
|
@@ -196,658 +56,123 @@ The active tab features a stunning dual-layer gradient effect with configurable
|
|
|
196
56
|
size: {
|
|
197
57
|
control: "select",
|
|
198
58
|
options: ["sm", "md", "lg"],
|
|
199
|
-
description: "Size variant applied to all tab triggers",
|
|
59
|
+
description: "Size variant applied to all tab triggers via context",
|
|
200
60
|
},
|
|
201
61
|
defaultValue: {
|
|
202
62
|
control: "text",
|
|
203
63
|
description: "The default active tab value",
|
|
204
64
|
},
|
|
205
|
-
value: {
|
|
206
|
-
control: "text",
|
|
207
|
-
description: "The controlled active tab value",
|
|
208
|
-
},
|
|
209
|
-
onValueChange: {
|
|
210
|
-
action: "valueChanged",
|
|
211
|
-
description: "Callback when tab changes",
|
|
212
|
-
},
|
|
213
65
|
},
|
|
214
66
|
}
|
|
215
67
|
|
|
216
68
|
export default meta
|
|
217
69
|
type Story = StoryObj<typeof Tabs>
|
|
218
70
|
|
|
219
|
-
//
|
|
220
|
-
export const Basic: Story = {
|
|
221
|
-
render: () => (
|
|
222
|
-
<div className="w-full max-w-2xl">
|
|
223
|
-
<Tabs defaultValue="overview" className="w-full">
|
|
224
|
-
<TabsList className="grid w-full grid-cols-3">
|
|
225
|
-
<TabsTrigger value="overview">Overview</TabsTrigger>
|
|
226
|
-
<TabsTrigger value="analytics">Analytics</TabsTrigger>
|
|
227
|
-
<TabsTrigger value="reports">Reports</TabsTrigger>
|
|
228
|
-
</TabsList>
|
|
229
|
-
<TabsContent value="overview" className="mt-6">
|
|
230
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
231
|
-
<h3 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
232
|
-
Overview
|
|
233
|
-
</h3>
|
|
234
|
-
<p className="text-fm-secondary mb-4">
|
|
235
|
-
Get a comprehensive view of your project's key metrics and
|
|
236
|
-
performance indicators.
|
|
237
|
-
</p>
|
|
238
|
-
<div className="grid grid-cols-2 gap-4">
|
|
239
|
-
<div className="border-fm-divider-secondary bg-fm-surface-info-sec rounded-lg border p-4">
|
|
240
|
-
<div className="text-fm-info text-2xl font-bold">1,234</div>
|
|
241
|
-
<div className="text-fm-secondary text-sm">Total Users</div>
|
|
242
|
-
</div>
|
|
243
|
-
<div className="border-fm-divider-positive bg-fm-surface-positive-sec rounded-lg border p-4">
|
|
244
|
-
<div className="text-fm-positive text-2xl font-bold">98.5%</div>
|
|
245
|
-
<div className="text-fm-secondary text-sm">Uptime</div>
|
|
246
|
-
</div>
|
|
247
|
-
</div>
|
|
248
|
-
</div>
|
|
249
|
-
</TabsContent>
|
|
250
|
-
<TabsContent value="analytics" className="mt-6">
|
|
251
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
252
|
-
<h3 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
253
|
-
Analytics
|
|
254
|
-
</h3>
|
|
255
|
-
<p className="text-fm-secondary mb-4">
|
|
256
|
-
Deep dive into user behavior and engagement patterns across your
|
|
257
|
-
platform.
|
|
258
|
-
</p>
|
|
259
|
-
<div className="space-y-4">
|
|
260
|
-
<div className="bg-fm-surface-secondary flex items-center justify-between rounded-lg p-3">
|
|
261
|
-
<span className="text-fm-primary">Page Views</span>
|
|
262
|
-
<span className="text-fm-positive font-semibold">+12.5%</span>
|
|
263
|
-
</div>
|
|
264
|
-
<div className="bg-fm-surface-secondary flex items-center justify-between rounded-lg p-3">
|
|
265
|
-
<span className="text-fm-primary">Session Duration</span>
|
|
266
|
-
<span className="text-fm-info font-semibold">4:32 avg</span>
|
|
267
|
-
</div>
|
|
268
|
-
<div className="bg-fm-surface-secondary flex items-center justify-between rounded-lg p-3">
|
|
269
|
-
<span className="text-fm-primary">Bounce Rate</span>
|
|
270
|
-
<span className="font-semibold text-orange-400">32.1%</span>
|
|
271
|
-
</div>
|
|
272
|
-
</div>
|
|
273
|
-
</div>
|
|
274
|
-
</TabsContent>
|
|
275
|
-
<TabsContent value="reports" className="mt-6">
|
|
276
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
277
|
-
<h3 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
278
|
-
Reports
|
|
279
|
-
</h3>
|
|
280
|
-
<p className="text-fm-secondary mb-4">
|
|
281
|
-
Generate and download detailed reports for stakeholders and
|
|
282
|
-
analysis.
|
|
283
|
-
</p>
|
|
284
|
-
<div className="space-y-3">
|
|
285
|
-
<button className="bg-fm-surface-secondary hover:bg-fm-surface-tertiary w-full rounded-lg p-3 text-left transition-colors">
|
|
286
|
-
<div className="text-fm-primary font-medium">
|
|
287
|
-
Monthly Performance Report
|
|
288
|
-
</div>
|
|
289
|
-
<div className="text-fm-secondary text-sm">
|
|
290
|
-
Last generated: 2 days ago
|
|
291
|
-
</div>
|
|
292
|
-
</button>
|
|
293
|
-
<button className="bg-fm-surface-secondary hover:bg-fm-surface-tertiary w-full rounded-lg p-3 text-left transition-colors">
|
|
294
|
-
<div className="text-fm-primary font-medium">
|
|
295
|
-
User Engagement Analysis
|
|
296
|
-
</div>
|
|
297
|
-
<div className="text-fm-secondary text-sm">
|
|
298
|
-
Last generated: 1 week ago
|
|
299
|
-
</div>
|
|
300
|
-
</button>
|
|
301
|
-
<button className="bg-fm-surface-secondary hover:bg-fm-surface-tertiary w-full rounded-lg p-3 text-left transition-colors">
|
|
302
|
-
<div className="text-fm-primary font-medium">
|
|
303
|
-
Revenue Breakdown
|
|
304
|
-
</div>
|
|
305
|
-
<div className="text-fm-secondary text-sm">
|
|
306
|
-
Last generated: 3 days ago
|
|
307
|
-
</div>
|
|
308
|
-
</button>
|
|
309
|
-
</div>
|
|
310
|
-
</div>
|
|
311
|
-
</TabsContent>
|
|
312
|
-
</Tabs>
|
|
313
|
-
</div>
|
|
314
|
-
),
|
|
315
|
-
parameters: {
|
|
316
|
-
docs: {
|
|
317
|
-
description: {
|
|
318
|
-
story:
|
|
319
|
-
"Basic tabs implementation with three panels showing different types of content using default medium size.",
|
|
320
|
-
},
|
|
321
|
-
},
|
|
322
|
-
},
|
|
323
|
-
}
|
|
71
|
+
// ─── AllVariants ──────────────────────────────────────────────────────────────
|
|
324
72
|
|
|
325
|
-
|
|
326
|
-
export const WithIcons: Story = {
|
|
73
|
+
export const AllVariants: Story = {
|
|
327
74
|
render: () => (
|
|
328
|
-
<div className="
|
|
329
|
-
|
|
330
|
-
<TabsList className="grid w-full grid-cols-4">
|
|
331
|
-
<TabsTrigger value="dashboard" className="gap-2">
|
|
332
|
-
<FileChartIcon className="h-4 w-4" />
|
|
333
|
-
Dashboard
|
|
334
|
-
</TabsTrigger>
|
|
335
|
-
<TabsTrigger value="users" className="gap-2">
|
|
336
|
-
<EyeOpenIcon className="h-4 w-4" />
|
|
337
|
-
Users
|
|
338
|
-
</TabsTrigger>
|
|
339
|
-
<TabsTrigger value="settings" className="gap-2">
|
|
340
|
-
<EditBigIcon className="h-4 w-4" />
|
|
341
|
-
Settings
|
|
342
|
-
</TabsTrigger>
|
|
343
|
-
<TabsTrigger value="alerts" className="gap-2">
|
|
344
|
-
<AlertIcon className="h-4 w-4" />
|
|
345
|
-
Alerts
|
|
346
|
-
</TabsTrigger>
|
|
347
|
-
</TabsList>
|
|
348
|
-
|
|
349
|
-
<TabsContent value="dashboard" className="mt-6">
|
|
350
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
351
|
-
<div className="mb-4 flex items-center gap-3">
|
|
352
|
-
<FileChartIcon className="text-fm-info h-6 w-6" />
|
|
353
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
354
|
-
Dashboard
|
|
355
|
-
</h3>
|
|
356
|
-
</div>
|
|
357
|
-
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
|
|
358
|
-
<div className="rounded-lg border border-blue-500/30 bg-gradient-to-br from-blue-500/20 to-purple-500/20 p-4">
|
|
359
|
-
<div className="text-fm-primary text-2xl font-bold">847</div>
|
|
360
|
-
<div className="text-fm-secondary text-sm">Active Sessions</div>
|
|
361
|
-
<div className="text-fm-positive mt-1 text-xs">
|
|
362
|
-
↗ +15% from yesterday
|
|
363
|
-
</div>
|
|
364
|
-
</div>
|
|
365
|
-
<div className="rounded-lg border border-green-500/30 bg-gradient-to-br from-green-500/20 to-teal-500/20 p-4">
|
|
366
|
-
<div className="text-fm-primary text-2xl font-bold">
|
|
367
|
-
$12,847
|
|
368
|
-
</div>
|
|
369
|
-
<div className="text-fm-secondary text-sm">Revenue Today</div>
|
|
370
|
-
<div className="text-fm-positive mt-1 text-xs">
|
|
371
|
-
↗ +8% from yesterday
|
|
372
|
-
</div>
|
|
373
|
-
</div>
|
|
374
|
-
<div className="rounded-lg border border-orange-500/30 bg-gradient-to-br from-orange-500/20 to-red-500/20 p-4">
|
|
375
|
-
<div className="text-fm-primary text-2xl font-bold">23</div>
|
|
376
|
-
<div className="text-fm-secondary text-sm">Critical Issues</div>
|
|
377
|
-
<div className="text-fm-icon-negative mt-1 text-xs">
|
|
378
|
-
↗ +3 new issues
|
|
379
|
-
</div>
|
|
380
|
-
</div>
|
|
381
|
-
</div>
|
|
382
|
-
</div>
|
|
383
|
-
</TabsContent>
|
|
384
|
-
|
|
385
|
-
<TabsContent value="users" className="mt-6">
|
|
386
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
387
|
-
<div className="mb-4 flex items-center gap-3">
|
|
388
|
-
<EyeOpenIcon className="text-fm-positive h-6 w-6" />
|
|
389
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
390
|
-
User Management
|
|
391
|
-
</h3>
|
|
392
|
-
</div>
|
|
393
|
-
<div className="space-y-3">
|
|
394
|
-
{[
|
|
395
|
-
{
|
|
396
|
-
name: "Alice Johnson",
|
|
397
|
-
role: "Admin",
|
|
398
|
-
status: "online",
|
|
399
|
-
avatar: "AJ",
|
|
400
|
-
},
|
|
401
|
-
{
|
|
402
|
-
name: "Bob Smith",
|
|
403
|
-
role: "Editor",
|
|
404
|
-
status: "away",
|
|
405
|
-
avatar: "BS",
|
|
406
|
-
},
|
|
407
|
-
{
|
|
408
|
-
name: "Carol Davis",
|
|
409
|
-
role: "Viewer",
|
|
410
|
-
status: "offline",
|
|
411
|
-
avatar: "CD",
|
|
412
|
-
},
|
|
413
|
-
{
|
|
414
|
-
name: "David Wilson",
|
|
415
|
-
role: "Admin",
|
|
416
|
-
status: "online",
|
|
417
|
-
avatar: "DW",
|
|
418
|
-
},
|
|
419
|
-
].map((user, index) => (
|
|
420
|
-
<div
|
|
421
|
-
key={index}
|
|
422
|
-
className="bg-fm-surface-secondary hover:bg-fm-surface-tertiary flex items-center justify-between rounded-lg p-3 transition-colors"
|
|
423
|
-
>
|
|
424
|
-
<div className="flex items-center gap-3">
|
|
425
|
-
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-gradient-to-br from-purple-500 to-pink-500">
|
|
426
|
-
<span className="text-fm-primary text-sm font-semibold">
|
|
427
|
-
{user.avatar}
|
|
428
|
-
</span>
|
|
429
|
-
</div>
|
|
430
|
-
<div>
|
|
431
|
-
<div className="text-fm-primary font-medium">
|
|
432
|
-
{user.name}
|
|
433
|
-
</div>
|
|
434
|
-
<div className="text-fm-secondary text-sm">
|
|
435
|
-
{user.role}
|
|
436
|
-
</div>
|
|
437
|
-
</div>
|
|
438
|
-
</div>
|
|
439
|
-
<div className="flex items-center gap-2">
|
|
440
|
-
<div
|
|
441
|
-
className={`h-2 w-2 rounded-full ${
|
|
442
|
-
user.status === "online"
|
|
443
|
-
? "bg-fm-surface-positive"
|
|
444
|
-
: user.status === "away"
|
|
445
|
-
? "bg-yellow-500"
|
|
446
|
-
: "bg-fm-surface-tertiary"
|
|
447
|
-
}`}
|
|
448
|
-
/>
|
|
449
|
-
<span className="text-fm-secondary text-xs capitalize">
|
|
450
|
-
{user.status}
|
|
451
|
-
</span>
|
|
452
|
-
</div>
|
|
453
|
-
</div>
|
|
454
|
-
))}
|
|
455
|
-
</div>
|
|
456
|
-
</div>
|
|
457
|
-
</TabsContent>
|
|
458
|
-
|
|
459
|
-
<TabsContent value="settings" className="mt-6">
|
|
460
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
461
|
-
<div className="mb-4 flex items-center gap-3">
|
|
462
|
-
<EditBigIcon className="h-6 w-6 text-purple-400" />
|
|
463
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
464
|
-
Settings
|
|
465
|
-
</h3>
|
|
466
|
-
</div>
|
|
467
|
-
<div className="space-y-4">
|
|
468
|
-
<div className="bg-fm-surface-secondary flex items-center justify-between rounded-lg p-3">
|
|
469
|
-
<div>
|
|
470
|
-
<div className="text-fm-primary font-medium">
|
|
471
|
-
Email Notifications
|
|
472
|
-
</div>
|
|
473
|
-
<div className="text-fm-secondary text-sm">
|
|
474
|
-
Receive updates via email
|
|
475
|
-
</div>
|
|
476
|
-
</div>
|
|
477
|
-
<button className="bg-fm-surface-info relative h-6 w-12 rounded-full">
|
|
478
|
-
<div className="bg-fm-surface-primary absolute top-0.5 right-0.5 h-5 w-5 rounded-full transition-transform"></div>
|
|
479
|
-
</button>
|
|
480
|
-
</div>
|
|
481
|
-
<div className="bg-fm-surface-secondary flex items-center justify-between rounded-lg p-3">
|
|
482
|
-
<div>
|
|
483
|
-
<div className="text-fm-primary font-medium">Dark Mode</div>
|
|
484
|
-
<div className="text-fm-secondary text-sm">
|
|
485
|
-
Use dark theme
|
|
486
|
-
</div>
|
|
487
|
-
</div>
|
|
488
|
-
<button className="bg-fm-surface-info relative h-6 w-12 rounded-full">
|
|
489
|
-
<div className="bg-fm-surface-primary absolute top-0.5 right-0.5 h-5 w-5 rounded-full transition-transform"></div>
|
|
490
|
-
</button>
|
|
491
|
-
</div>
|
|
492
|
-
<div className="bg-fm-surface-secondary flex items-center justify-between rounded-lg p-3">
|
|
493
|
-
<div>
|
|
494
|
-
<div className="text-fm-primary font-medium">Auto-save</div>
|
|
495
|
-
<div className="text-fm-secondary text-sm">
|
|
496
|
-
Automatically save changes
|
|
497
|
-
</div>
|
|
498
|
-
</div>
|
|
499
|
-
<button className="bg-fm-surface-tertiary relative h-6 w-12 rounded-full">
|
|
500
|
-
<div className="bg-fm-surface-primary absolute top-0.5 left-0.5 h-5 w-5 rounded-full transition-transform"></div>
|
|
501
|
-
</button>
|
|
502
|
-
</div>
|
|
503
|
-
</div>
|
|
504
|
-
</div>
|
|
505
|
-
</TabsContent>
|
|
506
|
-
|
|
507
|
-
<TabsContent value="alerts" className="mt-6">
|
|
508
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
509
|
-
<div className="mb-4 flex items-center gap-3">
|
|
510
|
-
<AlertIcon className="text-fm-icon-negative h-6 w-6" />
|
|
511
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
512
|
-
System Alerts
|
|
513
|
-
</h3>
|
|
514
|
-
</div>
|
|
515
|
-
<div className="space-y-3">
|
|
516
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-start gap-3 rounded-lg border p-3">
|
|
517
|
-
<AlertIcon className="text-fm-icon-negative mt-0.5 h-5 w-5 flex-shrink-0" />
|
|
518
|
-
<div>
|
|
519
|
-
<div className="text-fm-primary font-medium">
|
|
520
|
-
High CPU Usage
|
|
521
|
-
</div>
|
|
522
|
-
<div className="text-fm-secondary text-sm">
|
|
523
|
-
Server load is above 90% threshold
|
|
524
|
-
</div>
|
|
525
|
-
<div className="text-fm-tertiary mt-1 text-xs">
|
|
526
|
-
2 minutes ago
|
|
527
|
-
</div>
|
|
528
|
-
</div>
|
|
529
|
-
</div>
|
|
530
|
-
<div className="flex items-start gap-3 rounded-lg border border-yellow-500/20 bg-yellow-500/10 p-3">
|
|
531
|
-
<AlertIcon className="mt-0.5 h-5 w-5 flex-shrink-0 text-yellow-400" />
|
|
532
|
-
<div>
|
|
533
|
-
<div className="text-fm-primary font-medium">
|
|
534
|
-
Database Connection
|
|
535
|
-
</div>
|
|
536
|
-
<div className="text-fm-secondary text-sm">
|
|
537
|
-
Intermittent connectivity issues detected
|
|
538
|
-
</div>
|
|
539
|
-
<div className="text-fm-tertiary mt-1 text-xs">
|
|
540
|
-
15 minutes ago
|
|
541
|
-
</div>
|
|
542
|
-
</div>
|
|
543
|
-
</div>
|
|
544
|
-
<div className="border-fm-divider-positive bg-fm-surface-positive-sec flex items-start gap-3 rounded-lg border p-3">
|
|
545
|
-
<TickCircleIcon className="text-fm-positive mt-0.5 h-5 w-5 flex-shrink-0" />
|
|
546
|
-
<div>
|
|
547
|
-
<div className="text-fm-primary font-medium">
|
|
548
|
-
Backup Completed
|
|
549
|
-
</div>
|
|
550
|
-
<div className="text-fm-secondary text-sm">
|
|
551
|
-
Daily backup finished successfully
|
|
552
|
-
</div>
|
|
553
|
-
<div className="text-fm-tertiary mt-1 text-xs">
|
|
554
|
-
1 hour ago
|
|
555
|
-
</div>
|
|
556
|
-
</div>
|
|
557
|
-
</div>
|
|
558
|
-
</div>
|
|
559
|
-
</div>
|
|
560
|
-
</TabsContent>
|
|
561
|
-
</Tabs>
|
|
562
|
-
</div>
|
|
563
|
-
),
|
|
564
|
-
parameters: {
|
|
565
|
-
docs: {
|
|
566
|
-
description: {
|
|
567
|
-
story:
|
|
568
|
-
"Tabs with icons showing a complete admin dashboard interface with different functional areas using default medium size.",
|
|
569
|
-
},
|
|
570
|
-
},
|
|
571
|
-
},
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// 3. Size Variations
|
|
575
|
-
export const SizeVariations: Story = {
|
|
576
|
-
render: () => (
|
|
577
|
-
<div className="w-full max-w-4xl space-y-8">
|
|
578
|
-
<div className="space-y-4">
|
|
579
|
-
<h3 className="text-fm-primary text-lg font-medium">Small Size</h3>
|
|
580
|
-
<Tabs defaultValue="tab1" size="sm" className="w-full">
|
|
581
|
-
<TabsList className="grid w-full grid-cols-3">
|
|
582
|
-
<TabsTrigger value="tab1">Compact</TabsTrigger>
|
|
583
|
-
<TabsTrigger value="tab2">Small</TabsTrigger>
|
|
584
|
-
<TabsTrigger value="tab3">Minimal</TabsTrigger>
|
|
585
|
-
</TabsList>
|
|
586
|
-
<TabsContent value="tab1" className="mt-4">
|
|
587
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
588
|
-
<p className="text-fm-secondary">
|
|
589
|
-
Small tabs are perfect for compact interfaces and secondary
|
|
590
|
-
navigation.
|
|
591
|
-
</p>
|
|
592
|
-
</div>
|
|
593
|
-
</TabsContent>
|
|
594
|
-
<TabsContent value="tab2" className="mt-4">
|
|
595
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
596
|
-
<p className="text-fm-secondary">
|
|
597
|
-
Ideal for sidebars, modal dialogs, and tight spaces.
|
|
598
|
-
</p>
|
|
599
|
-
</div>
|
|
600
|
-
</TabsContent>
|
|
601
|
-
<TabsContent value="tab3" className="mt-4">
|
|
602
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
603
|
-
<p className="text-fm-secondary">
|
|
604
|
-
Minimal design with efficient use of space.
|
|
605
|
-
</p>
|
|
606
|
-
</div>
|
|
607
|
-
</TabsContent>
|
|
608
|
-
</Tabs>
|
|
609
|
-
</div>
|
|
610
|
-
|
|
75
|
+
<div className="space-y-8">
|
|
76
|
+
{/* Size variants */}
|
|
611
77
|
<div className="space-y-4">
|
|
612
|
-
<
|
|
613
|
-
|
|
614
|
-
</
|
|
615
|
-
<
|
|
616
|
-
<
|
|
617
|
-
<
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
<
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
<TabsContent value="tab2" className="mt-4">
|
|
630
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
631
|
-
<p className="text-fm-secondary">
|
|
632
|
-
Great for main content areas and primary navigation.
|
|
633
|
-
</p>
|
|
634
|
-
</div>
|
|
635
|
-
</TabsContent>
|
|
636
|
-
<TabsContent value="tab3" className="mt-4">
|
|
637
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
638
|
-
<p className="text-fm-secondary">
|
|
639
|
-
The default choice for most tab implementations.
|
|
640
|
-
</p>
|
|
641
|
-
</div>
|
|
642
|
-
</TabsContent>
|
|
643
|
-
</Tabs>
|
|
644
|
-
</div>
|
|
645
|
-
|
|
646
|
-
<div className="space-y-4">
|
|
647
|
-
<h3 className="text-fm-primary text-lg font-medium">Large Size</h3>
|
|
648
|
-
<Tabs defaultValue="tab1" size="lg" className="w-full">
|
|
649
|
-
<TabsList className="grid w-full grid-cols-3">
|
|
650
|
-
<TabsTrigger value="tab1">Prominent</TabsTrigger>
|
|
651
|
-
<TabsTrigger value="tab2">Large</TabsTrigger>
|
|
652
|
-
<TabsTrigger value="tab3">Bold</TabsTrigger>
|
|
653
|
-
</TabsList>
|
|
654
|
-
<TabsContent value="tab1" className="mt-4">
|
|
655
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-8">
|
|
656
|
-
<p className="text-fm-secondary">
|
|
657
|
-
Large tabs make a statement and are perfect for hero sections
|
|
658
|
-
and primary interfaces.
|
|
659
|
-
</p>
|
|
660
|
-
</div>
|
|
661
|
-
</TabsContent>
|
|
662
|
-
<TabsContent value="tab2" className="mt-4">
|
|
663
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-8">
|
|
664
|
-
<p className="text-fm-secondary">
|
|
665
|
-
Enhanced visibility and improved touch targets for mobile
|
|
666
|
-
interfaces.
|
|
667
|
-
</p>
|
|
668
|
-
</div>
|
|
669
|
-
</TabsContent>
|
|
670
|
-
<TabsContent value="tab3" className="mt-4">
|
|
671
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-8">
|
|
672
|
-
<p className="text-fm-secondary">
|
|
673
|
-
Bold design that commands attention and improves user
|
|
674
|
-
experience.
|
|
675
|
-
</p>
|
|
676
|
-
</div>
|
|
677
|
-
</TabsContent>
|
|
678
|
-
</Tabs>
|
|
679
|
-
</div>
|
|
680
|
-
</div>
|
|
681
|
-
),
|
|
682
|
-
parameters: {
|
|
683
|
-
docs: {
|
|
684
|
-
description: {
|
|
685
|
-
story:
|
|
686
|
-
"All three size variants (small, medium, large) showing different use cases and visual hierarchy. Notice how the size is set once on the Tabs component instead of each individual trigger.",
|
|
687
|
-
},
|
|
688
|
-
},
|
|
689
|
-
},
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
// 4. Individual Size Override
|
|
693
|
-
export const IndividualSizeOverride: Story = {
|
|
694
|
-
render: () => (
|
|
695
|
-
<div className="w-full max-w-3xl space-y-6">
|
|
696
|
-
<div className="text-center">
|
|
697
|
-
<h3 className="text-fm-primary mb-2 text-lg font-medium">
|
|
698
|
-
Individual Size Override
|
|
699
|
-
</h3>
|
|
700
|
-
<p className="text-fm-secondary text-sm">
|
|
701
|
-
Tabs component has size="md" set, but individual triggers can override
|
|
702
|
-
with their own size prop
|
|
703
|
-
</p>
|
|
704
|
-
</div>
|
|
705
|
-
|
|
706
|
-
<Tabs defaultValue="normal" size="md" className="w-full">
|
|
707
|
-
<TabsList className="grid w-full grid-cols-4">
|
|
708
|
-
<TabsTrigger value="small" size="sm">
|
|
709
|
-
Small Override
|
|
710
|
-
</TabsTrigger>
|
|
711
|
-
<TabsTrigger value="normal">Normal (md)</TabsTrigger>
|
|
712
|
-
<TabsTrigger value="normal2">Normal (md)</TabsTrigger>
|
|
713
|
-
<TabsTrigger value="large" size="lg">
|
|
714
|
-
Large Override
|
|
715
|
-
</TabsTrigger>
|
|
716
|
-
</TabsList>
|
|
717
|
-
|
|
718
|
-
<TabsContent value="small" className="mt-6">
|
|
719
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
720
|
-
<h3 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
721
|
-
Small Override
|
|
722
|
-
</h3>
|
|
723
|
-
<p className="text-fm-secondary">
|
|
724
|
-
This tab trigger has{" "}
|
|
725
|
-
<code className="bg-fm-surface-secondary rounded px-2 py-1 text-sm">
|
|
726
|
-
size="sm"
|
|
727
|
-
</code>{" "}
|
|
728
|
-
which overrides the parent Tabs component's{" "}
|
|
729
|
-
<code className="bg-fm-surface-secondary rounded px-2 py-1 text-sm">
|
|
730
|
-
size="md"
|
|
731
|
-
</code>{" "}
|
|
732
|
-
setting.
|
|
78
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
79
|
+
Size Variants
|
|
80
|
+
</h4>
|
|
81
|
+
<div className="space-y-6">
|
|
82
|
+
<div className="space-y-2 text-center">
|
|
83
|
+
<Tabs defaultValue="a" size="sm">
|
|
84
|
+
<TabsList>
|
|
85
|
+
<TabsTrigger value="a">Songs</TabsTrigger>
|
|
86
|
+
<TabsTrigger value="b">Albums</TabsTrigger>
|
|
87
|
+
<TabsTrigger value="c">Artists</TabsTrigger>
|
|
88
|
+
</TabsList>
|
|
89
|
+
<TabsContent value="a" />
|
|
90
|
+
<TabsContent value="b" />
|
|
91
|
+
<TabsContent value="c" />
|
|
92
|
+
</Tabs>
|
|
93
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
94
|
+
Small (sm)
|
|
733
95
|
</p>
|
|
734
|
-
<div className="border-fm-divider-secondary bg-fm-surface-info-sec mt-4 rounded-lg border p-3">
|
|
735
|
-
<div className="text-fm-info text-sm">
|
|
736
|
-
<strong>Use case:</strong> When you need most tabs to be medium
|
|
737
|
-
size but want to emphasize or de-emphasize specific tabs.
|
|
738
|
-
</div>
|
|
739
|
-
</div>
|
|
740
96
|
</div>
|
|
741
|
-
</TabsContent>
|
|
742
97
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
<
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
98
|
+
<div className="space-y-2 text-center">
|
|
99
|
+
<Tabs defaultValue="a" size="md">
|
|
100
|
+
<TabsList>
|
|
101
|
+
<TabsTrigger value="a">Songs</TabsTrigger>
|
|
102
|
+
<TabsTrigger value="b">Albums</TabsTrigger>
|
|
103
|
+
<TabsTrigger value="c">Artists</TabsTrigger>
|
|
104
|
+
</TabsList>
|
|
105
|
+
<TabsContent value="a" />
|
|
106
|
+
<TabsContent value="b" />
|
|
107
|
+
<TabsContent value="c" />
|
|
108
|
+
</Tabs>
|
|
109
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
110
|
+
Medium (md) — default
|
|
755
111
|
</p>
|
|
756
|
-
<div className="mt-4 grid grid-cols-2 gap-4">
|
|
757
|
-
<div className="border-fm-divider-positive bg-fm-surface-positive-sec rounded-lg border p-3">
|
|
758
|
-
<div className="text-fm-positive text-sm">
|
|
759
|
-
Consistent sizing across most tabs
|
|
760
|
-
</div>
|
|
761
|
-
</div>
|
|
762
|
-
<div className="rounded-lg border border-purple-500/20 bg-purple-500/10 p-3">
|
|
763
|
-
<div className="text-sm text-purple-200">
|
|
764
|
-
Clean, unified appearance
|
|
765
|
-
</div>
|
|
766
|
-
</div>
|
|
767
|
-
</div>
|
|
768
112
|
</div>
|
|
769
|
-
</TabsContent>
|
|
770
113
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
114
|
+
<div className="space-y-2 text-center">
|
|
115
|
+
<Tabs defaultValue="a" size="lg">
|
|
116
|
+
<TabsList>
|
|
117
|
+
<TabsTrigger value="a">Songs</TabsTrigger>
|
|
118
|
+
<TabsTrigger value="b">Albums</TabsTrigger>
|
|
119
|
+
<TabsTrigger value="c">Artists</TabsTrigger>
|
|
120
|
+
</TabsList>
|
|
121
|
+
<TabsContent value="a" />
|
|
122
|
+
<TabsContent value="b" />
|
|
123
|
+
<TabsContent value="c" />
|
|
124
|
+
</Tabs>
|
|
125
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
126
|
+
Large (lg)
|
|
779
127
|
</p>
|
|
780
|
-
<div className="mt-4 space-y-3">
|
|
781
|
-
<div className="bg-fm-surface-secondary flex items-center gap-3 rounded-lg p-3">
|
|
782
|
-
<TickCircleIcon className="text-fm-positive h-5 w-5" />
|
|
783
|
-
<span className="text-fm-secondary">
|
|
784
|
-
Inherits parent size automatically
|
|
785
|
-
</span>
|
|
786
|
-
</div>
|
|
787
|
-
<div className="bg-fm-surface-secondary flex items-center gap-3 rounded-lg p-3">
|
|
788
|
-
<TickCircleIcon className="text-fm-positive h-5 w-5" />
|
|
789
|
-
<span className="text-fm-secondary">
|
|
790
|
-
No need to specify size prop
|
|
791
|
-
</span>
|
|
792
|
-
</div>
|
|
793
|
-
<div className="bg-fm-surface-secondary flex items-center gap-3 rounded-lg p-3">
|
|
794
|
-
<TickCircleIcon className="text-fm-positive h-5 w-5" />
|
|
795
|
-
<span className="text-fm-secondary">
|
|
796
|
-
Maintains consistent appearance
|
|
797
|
-
</span>
|
|
798
|
-
</div>
|
|
799
|
-
</div>
|
|
800
128
|
</div>
|
|
801
|
-
</
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
802
131
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
132
|
+
{/* Glow direction variants */}
|
|
133
|
+
<div className="space-y-4">
|
|
134
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
135
|
+
Glow Direction Variants
|
|
136
|
+
</h4>
|
|
137
|
+
<div className="flex flex-wrap gap-8">
|
|
138
|
+
<div className="space-y-2 text-center">
|
|
139
|
+
<Tabs defaultValue="active" size="md">
|
|
140
|
+
<TabsList>
|
|
141
|
+
<TabsTrigger value="active" glowDirection="bottom">
|
|
142
|
+
Active
|
|
143
|
+
</TabsTrigger>
|
|
144
|
+
<TabsTrigger value="other" glowDirection="bottom">
|
|
145
|
+
Inactive
|
|
146
|
+
</TabsTrigger>
|
|
147
|
+
</TabsList>
|
|
148
|
+
<TabsContent value="active" />
|
|
149
|
+
<TabsContent value="other" />
|
|
150
|
+
</Tabs>
|
|
151
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
152
|
+
Glow Bottom (default)
|
|
815
153
|
</p>
|
|
816
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary mt-4 rounded-lg border p-3">
|
|
817
|
-
<div className="text-fm-warning text-sm">
|
|
818
|
-
<strong>Use case:</strong> Call-to-action tabs, primary
|
|
819
|
-
navigation items, or tabs that need extra visual emphasis in
|
|
820
|
-
your interface.
|
|
821
|
-
</div>
|
|
822
|
-
</div>
|
|
823
|
-
<div className="mt-4 grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
824
|
-
<div className="rounded-lg border border-blue-500/30 bg-gradient-to-br from-blue-500/20 to-purple-500/20 p-4">
|
|
825
|
-
<div className="text-fm-primary text-lg font-semibold">
|
|
826
|
-
Enhanced
|
|
827
|
-
</div>
|
|
828
|
-
<div className="text-fm-secondary text-sm">
|
|
829
|
-
Better visibility
|
|
830
|
-
</div>
|
|
831
|
-
</div>
|
|
832
|
-
<div className="rounded-lg border border-green-500/30 bg-gradient-to-br from-green-500/20 to-teal-500/20 p-4">
|
|
833
|
-
<div className="text-fm-primary text-lg font-semibold">
|
|
834
|
-
Prominent
|
|
835
|
-
</div>
|
|
836
|
-
<div className="text-fm-secondary text-sm">Draws attention</div>
|
|
837
|
-
</div>
|
|
838
|
-
</div>
|
|
839
154
|
</div>
|
|
840
|
-
</TabsContent>
|
|
841
|
-
</Tabs>
|
|
842
155
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
156
|
+
<div className="space-y-2 text-center">
|
|
157
|
+
<div className="pt-8">
|
|
158
|
+
<Tabs defaultValue="active" size="md">
|
|
159
|
+
<TabsList>
|
|
160
|
+
<TabsTrigger value="active" glowDirection="top">
|
|
161
|
+
Active
|
|
162
|
+
</TabsTrigger>
|
|
163
|
+
<TabsTrigger value="other" glowDirection="top">
|
|
164
|
+
Inactive
|
|
165
|
+
</TabsTrigger>
|
|
166
|
+
</TabsList>
|
|
167
|
+
<TabsContent value="active" />
|
|
168
|
+
<TabsContent value="other" />
|
|
169
|
+
</Tabs>
|
|
170
|
+
</div>
|
|
171
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
172
|
+
Glow Top
|
|
173
|
+
</p>
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
851
176
|
</div>
|
|
852
177
|
</div>
|
|
853
178
|
),
|
|
@@ -855,746 +180,424 @@ export const IndividualSizeOverride: Story = {
|
|
|
855
180
|
docs: {
|
|
856
181
|
description: {
|
|
857
182
|
story:
|
|
858
|
-
"
|
|
183
|
+
"All three size variants (sm, md, lg) and both glow direction options (bottom, top) shown as labeled item cards.",
|
|
859
184
|
},
|
|
860
185
|
},
|
|
861
186
|
},
|
|
862
187
|
}
|
|
863
188
|
|
|
864
|
-
//
|
|
865
|
-
export const ComplexContent: Story = {
|
|
866
|
-
render: () => (
|
|
867
|
-
<div className="w-full max-w-4xl">
|
|
868
|
-
<Tabs defaultValue="products" size="md" className="w-full">
|
|
869
|
-
<TabsList className="grid w-full grid-cols-4">
|
|
870
|
-
<TabsTrigger value="products" className="gap-2">
|
|
871
|
-
<SearchIcon className="h-4 w-4" />
|
|
872
|
-
Products
|
|
873
|
-
</TabsTrigger>
|
|
874
|
-
<TabsTrigger value="customers" className="gap-2">
|
|
875
|
-
<EyeOpenIcon className="h-4 w-4" />
|
|
876
|
-
Customers
|
|
877
|
-
</TabsTrigger>
|
|
878
|
-
<TabsTrigger value="orders" className="gap-2">
|
|
879
|
-
<FileChartIcon className="h-4 w-4" />
|
|
880
|
-
Orders
|
|
881
|
-
</TabsTrigger>
|
|
882
|
-
<TabsTrigger value="analytics" className="gap-2" size="lg">
|
|
883
|
-
<TickCircleIcon className="h-4 w-4" />
|
|
884
|
-
Analytics
|
|
885
|
-
</TabsTrigger>
|
|
886
|
-
</TabsList>
|
|
887
|
-
|
|
888
|
-
<TabsContent value="products" className="mt-6">
|
|
889
|
-
<div className="space-y-4">
|
|
890
|
-
<div className="flex items-center justify-between">
|
|
891
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
892
|
-
Product Catalog
|
|
893
|
-
</h3>
|
|
894
|
-
<button className="bg-fm-surface-info text-fm-surface-primary hover:bg-fm-surface-info flex items-center gap-2 rounded-lg px-4 py-2 transition-colors">
|
|
895
|
-
<PlusIcon className="h-4 w-4" />
|
|
896
|
-
Add Product
|
|
897
|
-
</button>
|
|
898
|
-
</div>
|
|
189
|
+
// ─── Configurations ───────────────────────────────────────────────────────────
|
|
899
190
|
|
|
900
|
-
|
|
901
|
-
{[
|
|
902
|
-
{
|
|
903
|
-
name: "Wireless Headphones",
|
|
904
|
-
price: "$199",
|
|
905
|
-
category: "Electronics",
|
|
906
|
-
stock: 45,
|
|
907
|
-
},
|
|
908
|
-
{
|
|
909
|
-
name: "Smart Watch",
|
|
910
|
-
price: "$299",
|
|
911
|
-
category: "Wearables",
|
|
912
|
-
stock: 23,
|
|
913
|
-
},
|
|
914
|
-
{
|
|
915
|
-
name: "Laptop Stand",
|
|
916
|
-
price: "$49",
|
|
917
|
-
category: "Accessories",
|
|
918
|
-
stock: 67,
|
|
919
|
-
},
|
|
920
|
-
{
|
|
921
|
-
name: "USB-C Cable",
|
|
922
|
-
price: "$29",
|
|
923
|
-
category: "Cables",
|
|
924
|
-
stock: 156,
|
|
925
|
-
},
|
|
926
|
-
{
|
|
927
|
-
name: "Wireless Mouse",
|
|
928
|
-
price: "$79",
|
|
929
|
-
category: "Electronics",
|
|
930
|
-
stock: 34,
|
|
931
|
-
},
|
|
932
|
-
{
|
|
933
|
-
name: "Keyboard",
|
|
934
|
-
price: "$149",
|
|
935
|
-
category: "Electronics",
|
|
936
|
-
stock: 28,
|
|
937
|
-
},
|
|
938
|
-
].map((product, index) => (
|
|
939
|
-
<div
|
|
940
|
-
key={index}
|
|
941
|
-
className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary rounded-lg border p-4 transition-colors"
|
|
942
|
-
>
|
|
943
|
-
<div className="mb-3 flex aspect-square items-center justify-center rounded-lg bg-gradient-to-br from-purple-500/20 to-pink-500/20">
|
|
944
|
-
<SearchIcon className="text-fm-tertiary h-8 w-8" />
|
|
945
|
-
</div>
|
|
946
|
-
<h4 className="text-fm-primary mb-1 font-medium">
|
|
947
|
-
{product.name}
|
|
948
|
-
</h4>
|
|
949
|
-
<p className="text-fm-secondary mb-2 text-sm">
|
|
950
|
-
{product.category}
|
|
951
|
-
</p>
|
|
952
|
-
<div className="flex items-center justify-between">
|
|
953
|
-
<span className="text-fm-primary font-semibold">
|
|
954
|
-
{product.price}
|
|
955
|
-
</span>
|
|
956
|
-
<span className="text-fm-secondary text-xs">
|
|
957
|
-
{product.stock} in stock
|
|
958
|
-
</span>
|
|
959
|
-
</div>
|
|
960
|
-
</div>
|
|
961
|
-
))}
|
|
962
|
-
</div>
|
|
963
|
-
</div>
|
|
964
|
-
</TabsContent>
|
|
965
|
-
|
|
966
|
-
<TabsContent value="customers" className="mt-6">
|
|
967
|
-
<div className="space-y-4">
|
|
968
|
-
<div className="flex items-center justify-between">
|
|
969
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
970
|
-
Customer Directory
|
|
971
|
-
</h3>
|
|
972
|
-
<div className="flex gap-2">
|
|
973
|
-
<button className="bg-fm-surface-secondary text-fm-primary hover:bg-fm-surface-tertiary rounded px-3 py-1 text-sm transition-colors">
|
|
974
|
-
Export
|
|
975
|
-
</button>
|
|
976
|
-
<button className="bg-fm-surface-info text-fm-surface-primary hover:bg-fm-surface-info rounded px-3 py-1 text-sm transition-colors">
|
|
977
|
-
Add Customer
|
|
978
|
-
</button>
|
|
979
|
-
</div>
|
|
980
|
-
</div>
|
|
981
|
-
|
|
982
|
-
<div className="space-y-2">
|
|
983
|
-
{[
|
|
984
|
-
{
|
|
985
|
-
name: "Alice Cooper",
|
|
986
|
-
email: "alice@example.com",
|
|
987
|
-
orders: 12,
|
|
988
|
-
value: "$2,847",
|
|
989
|
-
},
|
|
990
|
-
{
|
|
991
|
-
name: "Bob Martinez",
|
|
992
|
-
email: "bob@example.com",
|
|
993
|
-
orders: 8,
|
|
994
|
-
value: "$1,923",
|
|
995
|
-
},
|
|
996
|
-
{
|
|
997
|
-
name: "Carol Johnson",
|
|
998
|
-
email: "carol@example.com",
|
|
999
|
-
orders: 15,
|
|
1000
|
-
value: "$3,456",
|
|
1001
|
-
},
|
|
1002
|
-
{
|
|
1003
|
-
name: "David Kim",
|
|
1004
|
-
email: "david@example.com",
|
|
1005
|
-
orders: 6,
|
|
1006
|
-
value: "$1,234",
|
|
1007
|
-
},
|
|
1008
|
-
{
|
|
1009
|
-
name: "Eva Rodriguez",
|
|
1010
|
-
email: "eva@example.com",
|
|
1011
|
-
orders: 22,
|
|
1012
|
-
value: "$4,567",
|
|
1013
|
-
},
|
|
1014
|
-
].map((customer, index) => (
|
|
1015
|
-
<div
|
|
1016
|
-
key={index}
|
|
1017
|
-
className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary flex items-center justify-between rounded-lg border p-4 transition-colors"
|
|
1018
|
-
>
|
|
1019
|
-
<div className="flex items-center gap-3">
|
|
1020
|
-
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-gradient-to-br from-blue-500 to-purple-500">
|
|
1021
|
-
<span className="text-fm-primary text-sm font-semibold">
|
|
1022
|
-
{customer.name
|
|
1023
|
-
.split(" ")
|
|
1024
|
-
.map((n) => n[0])
|
|
1025
|
-
.join("")}
|
|
1026
|
-
</span>
|
|
1027
|
-
</div>
|
|
1028
|
-
<div>
|
|
1029
|
-
<div className="text-fm-primary font-medium">
|
|
1030
|
-
{customer.name}
|
|
1031
|
-
</div>
|
|
1032
|
-
<div className="text-fm-secondary text-sm">
|
|
1033
|
-
{customer.email}
|
|
1034
|
-
</div>
|
|
1035
|
-
</div>
|
|
1036
|
-
</div>
|
|
1037
|
-
<div className="text-right">
|
|
1038
|
-
<div className="text-fm-primary font-medium">
|
|
1039
|
-
{customer.value}
|
|
1040
|
-
</div>
|
|
1041
|
-
<div className="text-fm-secondary text-sm">
|
|
1042
|
-
{customer.orders} orders
|
|
1043
|
-
</div>
|
|
1044
|
-
</div>
|
|
1045
|
-
</div>
|
|
1046
|
-
))}
|
|
1047
|
-
</div>
|
|
1048
|
-
</div>
|
|
1049
|
-
</TabsContent>
|
|
1050
|
-
|
|
1051
|
-
<TabsContent value="orders" className="mt-6">
|
|
1052
|
-
<div className="space-y-4">
|
|
1053
|
-
<div className="flex items-center justify-between">
|
|
1054
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
1055
|
-
Recent Orders
|
|
1056
|
-
</h3>
|
|
1057
|
-
<div className="flex gap-2">
|
|
1058
|
-
<select className="border-fm-divider-secondary bg-fm-surface-secondary text-fm-primary rounded border px-3 py-1 text-sm">
|
|
1059
|
-
<option>All Status</option>
|
|
1060
|
-
<option>Pending</option>
|
|
1061
|
-
<option>Processing</option>
|
|
1062
|
-
<option>Shipped</option>
|
|
1063
|
-
<option>Delivered</option>
|
|
1064
|
-
</select>
|
|
1065
|
-
</div>
|
|
1066
|
-
</div>
|
|
1067
|
-
|
|
1068
|
-
<div className="space-y-3">
|
|
1069
|
-
{[
|
|
1070
|
-
{
|
|
1071
|
-
id: "#ORD-001",
|
|
1072
|
-
customer: "Alice Cooper",
|
|
1073
|
-
total: "$247.99",
|
|
1074
|
-
status: "delivered",
|
|
1075
|
-
date: "2 hours ago",
|
|
1076
|
-
},
|
|
1077
|
-
{
|
|
1078
|
-
id: "#ORD-002",
|
|
1079
|
-
customer: "Bob Martinez",
|
|
1080
|
-
total: "$89.50",
|
|
1081
|
-
status: "shipped",
|
|
1082
|
-
date: "4 hours ago",
|
|
1083
|
-
},
|
|
1084
|
-
{
|
|
1085
|
-
id: "#ORD-003",
|
|
1086
|
-
customer: "Carol Johnson",
|
|
1087
|
-
total: "$156.75",
|
|
1088
|
-
status: "processing",
|
|
1089
|
-
date: "6 hours ago",
|
|
1090
|
-
},
|
|
1091
|
-
{
|
|
1092
|
-
id: "#ORD-004",
|
|
1093
|
-
customer: "David Kim",
|
|
1094
|
-
total: "$324.00",
|
|
1095
|
-
status: "pending",
|
|
1096
|
-
date: "8 hours ago",
|
|
1097
|
-
},
|
|
1098
|
-
{
|
|
1099
|
-
id: "#ORD-005",
|
|
1100
|
-
customer: "Eva Rodriguez",
|
|
1101
|
-
total: "$78.25",
|
|
1102
|
-
status: "delivered",
|
|
1103
|
-
date: "1 day ago",
|
|
1104
|
-
},
|
|
1105
|
-
].map((order, index) => (
|
|
1106
|
-
<div
|
|
1107
|
-
key={index}
|
|
1108
|
-
className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary flex items-center justify-between rounded-lg border p-4 transition-colors"
|
|
1109
|
-
>
|
|
1110
|
-
<div className="flex items-center gap-4">
|
|
1111
|
-
<div>
|
|
1112
|
-
<div className="text-fm-primary font-medium">
|
|
1113
|
-
{order.id}
|
|
1114
|
-
</div>
|
|
1115
|
-
<div className="text-fm-secondary text-sm">
|
|
1116
|
-
{order.customer}
|
|
1117
|
-
</div>
|
|
1118
|
-
</div>
|
|
1119
|
-
</div>
|
|
1120
|
-
<div className="flex items-center gap-4">
|
|
1121
|
-
<div className="text-right">
|
|
1122
|
-
<div className="text-fm-primary font-medium">
|
|
1123
|
-
{order.total}
|
|
1124
|
-
</div>
|
|
1125
|
-
<div className="text-fm-secondary text-sm">
|
|
1126
|
-
{order.date}
|
|
1127
|
-
</div>
|
|
1128
|
-
</div>
|
|
1129
|
-
<span
|
|
1130
|
-
className={`rounded-full px-2 py-1 text-xs ${
|
|
1131
|
-
order.status === "delivered"
|
|
1132
|
-
? "text-fm-positive bg-green-500/20"
|
|
1133
|
-
: order.status === "shipped"
|
|
1134
|
-
? "text-fm-info bg-blue-500/20"
|
|
1135
|
-
: order.status === "processing"
|
|
1136
|
-
? "bg-yellow-500/20 text-yellow-400"
|
|
1137
|
-
: "bg-fm-surface-secondary text-fm-tertiary"
|
|
1138
|
-
}`}
|
|
1139
|
-
>
|
|
1140
|
-
{order.status}
|
|
1141
|
-
</span>
|
|
1142
|
-
</div>
|
|
1143
|
-
</div>
|
|
1144
|
-
))}
|
|
1145
|
-
</div>
|
|
1146
|
-
</div>
|
|
1147
|
-
</TabsContent>
|
|
1148
|
-
|
|
1149
|
-
<TabsContent value="analytics" className="mt-6">
|
|
1150
|
-
<div className="space-y-6">
|
|
1151
|
-
<div className="flex items-center gap-3">
|
|
1152
|
-
<TickCircleIcon className="text-fm-positive h-6 w-6" />
|
|
1153
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
1154
|
-
Sales Analytics
|
|
1155
|
-
</h3>
|
|
1156
|
-
<span className="text-fm-positive rounded-full bg-green-500/20 px-3 py-1 text-xs">
|
|
1157
|
-
Large Tab
|
|
1158
|
-
</span>
|
|
1159
|
-
</div>
|
|
1160
|
-
|
|
1161
|
-
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
|
|
1162
|
-
<div className="rounded-lg border border-blue-500/30 bg-gradient-to-br from-blue-500/20 to-cyan-500/20 p-4">
|
|
1163
|
-
<div className="text-fm-primary text-2xl font-bold">
|
|
1164
|
-
$45,231
|
|
1165
|
-
</div>
|
|
1166
|
-
<div className="text-fm-secondary text-sm">
|
|
1167
|
-
Revenue This Month
|
|
1168
|
-
</div>
|
|
1169
|
-
<div className="text-fm-positive mt-1 text-xs">
|
|
1170
|
-
↗ +12% vs last month
|
|
1171
|
-
</div>
|
|
1172
|
-
</div>
|
|
1173
|
-
<div className="rounded-lg border border-green-500/30 bg-gradient-to-br from-green-500/20 to-emerald-500/20 p-4">
|
|
1174
|
-
<div className="text-fm-primary text-2xl font-bold">1,847</div>
|
|
1175
|
-
<div className="text-fm-secondary text-sm">
|
|
1176
|
-
Orders This Month
|
|
1177
|
-
</div>
|
|
1178
|
-
<div className="text-fm-positive mt-1 text-xs">
|
|
1179
|
-
↗ +8% vs last month
|
|
1180
|
-
</div>
|
|
1181
|
-
</div>
|
|
1182
|
-
<div className="rounded-lg border border-purple-500/30 bg-gradient-to-br from-purple-500/20 to-pink-500/20 p-4">
|
|
1183
|
-
<div className="text-fm-primary text-2xl font-bold">324</div>
|
|
1184
|
-
<div className="text-fm-secondary text-sm">New Customers</div>
|
|
1185
|
-
<div className="text-fm-positive mt-1 text-xs">
|
|
1186
|
-
↗ +15% vs last month
|
|
1187
|
-
</div>
|
|
1188
|
-
</div>
|
|
1189
|
-
<div className="rounded-lg border border-orange-500/30 bg-gradient-to-br from-orange-500/20 to-red-500/20 p-4">
|
|
1190
|
-
<div className="text-fm-primary text-2xl font-bold">$24.50</div>
|
|
1191
|
-
<div className="text-fm-secondary text-sm">Avg Order Value</div>
|
|
1192
|
-
<div className="text-fm-icon-negative mt-1 text-xs">
|
|
1193
|
-
↘ -3% vs last month
|
|
1194
|
-
</div>
|
|
1195
|
-
</div>
|
|
1196
|
-
</div>
|
|
1197
|
-
|
|
1198
|
-
<div className="border-fm-divider-warning bg-fm-surface-warning-sec rounded-lg border p-4">
|
|
1199
|
-
<div className="text-fm-warning text-sm">
|
|
1200
|
-
<strong>Note:</strong> The Analytics tab uses{" "}
|
|
1201
|
-
<code className="bg-fm-surface-secondary rounded px-2 py-1">
|
|
1202
|
-
size="lg"
|
|
1203
|
-
</code>
|
|
1204
|
-
to emphasize its importance as the primary data view, while
|
|
1205
|
-
other tabs inherit the default medium size.
|
|
1206
|
-
</div>
|
|
1207
|
-
</div>
|
|
1208
|
-
</div>
|
|
1209
|
-
</TabsContent>
|
|
1210
|
-
</Tabs>
|
|
1211
|
-
</div>
|
|
1212
|
-
),
|
|
1213
|
-
parameters: {
|
|
1214
|
-
docs: {
|
|
1215
|
-
description: {
|
|
1216
|
-
story:
|
|
1217
|
-
"Complex e-commerce admin interface demonstrating the new size prop functionality. The parent Tabs has size='md' but the Analytics tab uses size='lg' to emphasize its importance.",
|
|
1218
|
-
},
|
|
1219
|
-
},
|
|
1220
|
-
},
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
// 6. Glow Direction Variations
|
|
1224
|
-
export const GlowDirectionVariations: Story = {
|
|
191
|
+
export const Configurations: Story = {
|
|
1225
192
|
render: () => (
|
|
1226
|
-
<div className="
|
|
193
|
+
<div className="space-y-8">
|
|
194
|
+
{/* With icons */}
|
|
1227
195
|
<div className="space-y-4">
|
|
1228
|
-
<
|
|
1229
|
-
|
|
1230
|
-
</
|
|
1231
|
-
<Tabs defaultValue="
|
|
1232
|
-
<TabsList
|
|
1233
|
-
<TabsTrigger value="
|
|
1234
|
-
|
|
196
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
197
|
+
With Icons
|
|
198
|
+
</h4>
|
|
199
|
+
<Tabs defaultValue="songs" size="md" className="w-full max-w-lg">
|
|
200
|
+
<TabsList>
|
|
201
|
+
<TabsTrigger value="songs" className="gap-2">
|
|
202
|
+
<MusicalNoteIcon className="h-4 w-4" />
|
|
203
|
+
Songs
|
|
1235
204
|
</TabsTrigger>
|
|
1236
|
-
<TabsTrigger value="
|
|
1237
|
-
|
|
205
|
+
<TabsTrigger value="favorites" className="gap-2">
|
|
206
|
+
<HeartIcon className="h-4 w-4" />
|
|
207
|
+
Favorites
|
|
1238
208
|
</TabsTrigger>
|
|
1239
|
-
<TabsTrigger value="
|
|
1240
|
-
|
|
209
|
+
<TabsTrigger value="discover" className="gap-2">
|
|
210
|
+
<SearchIcon className="h-4 w-4" />
|
|
211
|
+
Discover
|
|
1241
212
|
</TabsTrigger>
|
|
1242
213
|
</TabsList>
|
|
1243
|
-
<TabsContent value="
|
|
1244
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-
|
|
1245
|
-
<p className="text-fm-secondary">
|
|
1246
|
-
|
|
1247
|
-
|
|
214
|
+
<TabsContent value="songs" className="mt-4">
|
|
215
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
216
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
217
|
+
Your full song library lives here — browse by title, artist, or
|
|
218
|
+
recently played.
|
|
1248
219
|
</p>
|
|
1249
220
|
</div>
|
|
1250
221
|
</TabsContent>
|
|
1251
|
-
<TabsContent value="
|
|
1252
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-
|
|
1253
|
-
<p className="text-fm-secondary">
|
|
1254
|
-
|
|
1255
|
-
content area.
|
|
222
|
+
<TabsContent value="favorites" className="mt-4">
|
|
223
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
224
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
225
|
+
Songs you've hearted appear here for quick access.
|
|
1256
226
|
</p>
|
|
1257
227
|
</div>
|
|
1258
228
|
</TabsContent>
|
|
1259
|
-
<TabsContent value="
|
|
1260
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-
|
|
1261
|
-
<p className="text-fm-secondary">
|
|
1262
|
-
|
|
1263
|
-
associated content.
|
|
229
|
+
<TabsContent value="discover" className="mt-4">
|
|
230
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
231
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
232
|
+
Personalized recommendations based on your listening habits.
|
|
1264
233
|
</p>
|
|
1265
234
|
</div>
|
|
1266
235
|
</TabsContent>
|
|
1267
236
|
</Tabs>
|
|
1268
237
|
</div>
|
|
1269
238
|
|
|
239
|
+
{/* Individual size override */}
|
|
1270
240
|
<div className="space-y-4">
|
|
1271
|
-
<
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
</TabsTrigger>
|
|
1277
|
-
<TabsTrigger value="
|
|
1278
|
-
|
|
241
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
242
|
+
Individual Size Override
|
|
243
|
+
</h4>
|
|
244
|
+
<Tabs defaultValue="featured" size="sm" className="w-full max-w-lg">
|
|
245
|
+
<TabsList>
|
|
246
|
+
<TabsTrigger value="featured">Featured</TabsTrigger>
|
|
247
|
+
<TabsTrigger value="trending" size="md">
|
|
248
|
+
Trending (md)
|
|
1279
249
|
</TabsTrigger>
|
|
1280
|
-
<TabsTrigger value="
|
|
1281
|
-
|
|
250
|
+
<TabsTrigger value="new" size="lg">
|
|
251
|
+
New (lg)
|
|
1282
252
|
</TabsTrigger>
|
|
1283
253
|
</TabsList>
|
|
1284
|
-
<TabsContent value="
|
|
1285
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-
|
|
1286
|
-
<p className="text-fm-secondary">
|
|
1287
|
-
|
|
1288
|
-
|
|
254
|
+
<TabsContent value="featured" className="mt-4">
|
|
255
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
256
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
257
|
+
The first trigger inherits the parent{" "}
|
|
258
|
+
<code className="text-fm-primary font-(--font-fm-mono)">
|
|
259
|
+
size="sm"
|
|
260
|
+
</code>
|
|
261
|
+
. The other two override to md and lg respectively.
|
|
1289
262
|
</p>
|
|
1290
263
|
</div>
|
|
1291
264
|
</TabsContent>
|
|
1292
|
-
<TabsContent value="
|
|
1293
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-
|
|
1294
|
-
<p className="text-fm-secondary">
|
|
1295
|
-
|
|
265
|
+
<TabsContent value="trending" className="mt-4">
|
|
266
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
267
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
268
|
+
This trigger uses{" "}
|
|
269
|
+
<code className="text-fm-primary font-(--font-fm-mono)">
|
|
270
|
+
size="md"
|
|
271
|
+
</code>{" "}
|
|
272
|
+
directly on the trigger, overriding the parent context.
|
|
1296
273
|
</p>
|
|
1297
274
|
</div>
|
|
1298
275
|
</TabsContent>
|
|
1299
|
-
<TabsContent value="
|
|
1300
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-
|
|
1301
|
-
<p className="text-fm-secondary">
|
|
1302
|
-
|
|
276
|
+
<TabsContent value="new" className="mt-4">
|
|
277
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
|
|
278
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
279
|
+
This trigger uses{" "}
|
|
280
|
+
<code className="text-fm-primary font-(--font-fm-mono)">
|
|
281
|
+
size="lg"
|
|
282
|
+
</code>{" "}
|
|
283
|
+
for a prominent call-to-action feel.
|
|
1303
284
|
</p>
|
|
1304
285
|
</div>
|
|
1305
286
|
</TabsContent>
|
|
1306
287
|
</Tabs>
|
|
1307
288
|
</div>
|
|
1308
289
|
|
|
290
|
+
{/* Different content panels */}
|
|
1309
291
|
<div className="space-y-4">
|
|
1310
|
-
<
|
|
1311
|
-
|
|
1312
|
-
</
|
|
1313
|
-
<Tabs defaultValue="
|
|
1314
|
-
<TabsList
|
|
1315
|
-
<TabsTrigger value="
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
<TabsTrigger value="tab2" glowDirection="top">
|
|
1319
|
-
Top Glow
|
|
292
|
+
<h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
|
|
293
|
+
Rich Content Panels
|
|
294
|
+
</h4>
|
|
295
|
+
<Tabs defaultValue="stats" size="md" className="w-full max-w-lg">
|
|
296
|
+
<TabsList>
|
|
297
|
+
<TabsTrigger value="stats" className="gap-2">
|
|
298
|
+
<FileChartIcon className="h-4 w-4" />
|
|
299
|
+
Stats
|
|
1320
300
|
</TabsTrigger>
|
|
1321
|
-
<TabsTrigger value="
|
|
1322
|
-
|
|
301
|
+
<TabsTrigger value="top" className="gap-2">
|
|
302
|
+
<StarIcon className="h-4 w-4" />
|
|
303
|
+
Top Tracks
|
|
1323
304
|
</TabsTrigger>
|
|
1324
|
-
<TabsTrigger value="
|
|
1325
|
-
|
|
305
|
+
<TabsTrigger value="settings" className="gap-2">
|
|
306
|
+
<SettingIcon className="h-4 w-4" />
|
|
307
|
+
Settings
|
|
1326
308
|
</TabsTrigger>
|
|
1327
309
|
</TabsList>
|
|
1328
|
-
<TabsContent value="
|
|
1329
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-
|
|
1330
|
-
<
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
<
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
310
|
+
<TabsContent value="stats" className="mt-4">
|
|
311
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-3 rounded-lg border p-4">
|
|
312
|
+
<div className="flex items-center justify-between">
|
|
313
|
+
<span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
314
|
+
Listening time this week
|
|
315
|
+
</span>
|
|
316
|
+
<span className="text-fm-primary font-fm-brand text-fm-md leading-fm-md font-semibold">
|
|
317
|
+
14h 32m
|
|
318
|
+
</span>
|
|
319
|
+
</div>
|
|
320
|
+
<div className="flex items-center justify-between">
|
|
321
|
+
<span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
322
|
+
Songs played
|
|
323
|
+
</span>
|
|
324
|
+
<span className="text-fm-primary font-fm-brand text-fm-md leading-fm-md font-semibold">
|
|
325
|
+
312
|
|
326
|
+
</span>
|
|
327
|
+
</div>
|
|
328
|
+
<div className="flex items-center justify-between">
|
|
329
|
+
<span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
330
|
+
Artists explored
|
|
331
|
+
</span>
|
|
332
|
+
<span className="text-fm-primary font-fm-brand text-fm-md leading-fm-md font-semibold">
|
|
333
|
+
47
|
|
334
|
+
</span>
|
|
335
|
+
</div>
|
|
1342
336
|
</div>
|
|
1343
337
|
</TabsContent>
|
|
1344
|
-
<TabsContent value="
|
|
1345
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
338
|
+
<TabsContent value="top" className="mt-4">
|
|
339
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-2 rounded-lg border p-4">
|
|
340
|
+
{["Midnight Drive", "Electric Haze", "Neon Pulse"].map(
|
|
341
|
+
(track, i) => (
|
|
342
|
+
<div
|
|
343
|
+
key={track}
|
|
344
|
+
className="flex items-center gap-3 rounded-md px-2 py-2"
|
|
345
|
+
>
|
|
346
|
+
<span className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm w-4">
|
|
347
|
+
{i + 1}
|
|
348
|
+
</span>
|
|
349
|
+
<div className="bg-fm-surface-secondary border-fm-divider-secondary flex h-8 w-8 items-center justify-center rounded-md border">
|
|
350
|
+
<MusicalNoteIcon className="text-fm-secondary h-4 w-4" />
|
|
351
|
+
</div>
|
|
352
|
+
<span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
353
|
+
{track}
|
|
354
|
+
</span>
|
|
355
|
+
</div>
|
|
356
|
+
)
|
|
357
|
+
)}
|
|
1350
358
|
</div>
|
|
1351
359
|
</TabsContent>
|
|
1352
|
-
<TabsContent value="
|
|
1353
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-
|
|
1354
|
-
<
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
360
|
+
<TabsContent value="settings" className="mt-4">
|
|
361
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-3 rounded-lg border p-4">
|
|
362
|
+
<div className="flex items-center justify-between">
|
|
363
|
+
<span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
364
|
+
Crossfade
|
|
365
|
+
</span>
|
|
366
|
+
<span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
367
|
+
3s
|
|
368
|
+
</span>
|
|
369
|
+
</div>
|
|
370
|
+
<div className="flex items-center justify-between">
|
|
371
|
+
<span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
372
|
+
Normalize volume
|
|
373
|
+
</span>
|
|
374
|
+
<span className="text-fm-positive font-fm-text text-fm-sm leading-fm-sm">
|
|
375
|
+
On
|
|
376
|
+
</span>
|
|
377
|
+
</div>
|
|
378
|
+
<div className="flex items-center justify-between">
|
|
379
|
+
<span className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
380
|
+
Download quality
|
|
381
|
+
</span>
|
|
382
|
+
<span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
383
|
+
High
|
|
384
|
+
</span>
|
|
385
|
+
</div>
|
|
1358
386
|
</div>
|
|
1359
387
|
</TabsContent>
|
|
1360
388
|
</Tabs>
|
|
1361
389
|
</div>
|
|
1362
|
-
|
|
1363
|
-
<div className="border-fm-divider-secondary bg-fm-surface-info-sec rounded-lg border p-4">
|
|
1364
|
-
<div className="text-fm-info text-sm">
|
|
1365
|
-
<strong>Note:</strong> The glowDirection prop allows you to customize
|
|
1366
|
-
the visual effect of active tabs. Use "bottom" (default) for an
|
|
1367
|
-
underline-style glow or "top" for a subtle highlight effect. You can
|
|
1368
|
-
mix different directions within the same tab group for creative
|
|
1369
|
-
designs.
|
|
1370
|
-
</div>
|
|
1371
|
-
</div>
|
|
1372
390
|
</div>
|
|
1373
391
|
),
|
|
1374
392
|
parameters: {
|
|
1375
393
|
docs: {
|
|
1376
394
|
description: {
|
|
1377
395
|
story:
|
|
1378
|
-
"
|
|
396
|
+
"Configuration axes: tabs with icons, individual per-trigger size overrides against a parent size context, and tabs with rich differentiated content panels.",
|
|
1379
397
|
},
|
|
1380
398
|
},
|
|
1381
399
|
},
|
|
1382
400
|
}
|
|
1383
401
|
|
|
1384
|
-
//
|
|
1385
|
-
export const InteractiveStates: Story = {
|
|
1386
|
-
render: () => {
|
|
1387
|
-
const [activeTab, setActiveTab] = React.useState("normal")
|
|
1388
|
-
const [isLoading, setIsLoading] = React.useState(false)
|
|
1389
|
-
|
|
1390
|
-
const handleTabChange = (value: string) => {
|
|
1391
|
-
setIsLoading(true)
|
|
1392
|
-
setActiveTab(value)
|
|
402
|
+
// ─── Interactive ──────────────────────────────────────────────────────────────
|
|
1393
403
|
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
404
|
+
export const Interactive: Story = {
|
|
405
|
+
render: () => {
|
|
406
|
+
const [activeTab, setActiveTab] = React.useState("songs")
|
|
407
|
+
|
|
408
|
+
const tabs = [
|
|
409
|
+
{ value: "songs", label: "Songs", icon: MusicalNoteIcon },
|
|
410
|
+
{ value: "albums", label: "Albums", icon: StarIcon },
|
|
411
|
+
{ value: "artists", label: "Artists", icon: HeartIcon },
|
|
412
|
+
{ value: "about", label: "About", icon: AlertIcon },
|
|
413
|
+
]
|
|
414
|
+
|
|
415
|
+
const songs = [
|
|
416
|
+
{ title: "Midnight Drive", artist: "Nova Wave", duration: "3:42" },
|
|
417
|
+
{ title: "Electric Haze", artist: "The Circuits", duration: "4:15" },
|
|
418
|
+
{ title: "Neon Pulse", artist: "Synthcore", duration: "3:58" },
|
|
419
|
+
{ title: "Deep Current", artist: "Ocean Mind", duration: "5:02" },
|
|
420
|
+
]
|
|
421
|
+
|
|
422
|
+
const albums = [
|
|
423
|
+
{ title: "Chromatic", artist: "Nova Wave", tracks: 12, year: 2024 },
|
|
424
|
+
{ title: "Static Dreams", artist: "The Circuits", tracks: 9, year: 2023 },
|
|
425
|
+
{ title: "Parallax", artist: "Synthcore", tracks: 14, year: 2024 },
|
|
426
|
+
]
|
|
427
|
+
|
|
428
|
+
const artists = [
|
|
429
|
+
{ name: "Nova Wave", genre: "Synthpop", listeners: "1.2M" },
|
|
430
|
+
{ name: "The Circuits", genre: "Electronic", listeners: "840K" },
|
|
431
|
+
{ name: "Synthcore", genre: "Ambient", listeners: "620K" },
|
|
432
|
+
{ name: "Ocean Mind", genre: "Chill", listeners: "390K" },
|
|
433
|
+
]
|
|
1399
434
|
|
|
1400
435
|
return (
|
|
1401
|
-
<div className="w-full
|
|
1402
|
-
<div className="
|
|
1403
|
-
<
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
</p>
|
|
1409
|
-
</div>
|
|
1410
|
-
|
|
1411
|
-
<Tabs
|
|
1412
|
-
value={activeTab}
|
|
1413
|
-
onValueChange={handleTabChange}
|
|
1414
|
-
size="md"
|
|
1415
|
-
className="w-full"
|
|
1416
|
-
>
|
|
1417
|
-
<TabsList className="grid w-full grid-cols-4">
|
|
1418
|
-
<TabsTrigger value="normal" className="gap-2">
|
|
1419
|
-
<TickCircleIcon className="h-4 w-4" />
|
|
1420
|
-
Normal
|
|
1421
|
-
</TabsTrigger>
|
|
1422
|
-
<TabsTrigger value="loading" className="gap-2" disabled={isLoading}>
|
|
1423
|
-
{isLoading && activeTab === "loading" ? (
|
|
1424
|
-
<div className="border-fm-divider-secondary border-t-fm-primary h-4 w-4 animate-spin rounded-full border-2" />
|
|
1425
|
-
) : (
|
|
1426
|
-
<AlertIcon className="h-4 w-4" />
|
|
1427
|
-
)}
|
|
1428
|
-
Loading
|
|
1429
|
-
</TabsTrigger>
|
|
1430
|
-
<TabsTrigger value="error" className="gap-2">
|
|
1431
|
-
<CrossIcon className="h-4 w-4" />
|
|
1432
|
-
Error
|
|
1433
|
-
</TabsTrigger>
|
|
1434
|
-
<TabsTrigger value="success" className="gap-2">
|
|
1435
|
-
<TickCircleIcon className="h-4 w-4" />
|
|
1436
|
-
Success
|
|
1437
|
-
</TabsTrigger>
|
|
1438
|
-
</TabsList>
|
|
1439
|
-
|
|
1440
|
-
<TabsContent value="normal" className="mt-6">
|
|
1441
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
1442
|
-
<h3 className="text-fm-primary mb-4 text-lg font-semibold">
|
|
1443
|
-
Normal State
|
|
1444
|
-
</h3>
|
|
1445
|
-
<p className="text-fm-secondary mb-4">
|
|
1446
|
-
This is the default state of the component with all
|
|
1447
|
-
functionality working normally.
|
|
436
|
+
<div className="w-full p-8">
|
|
437
|
+
<div className="mx-auto max-w-3xl space-y-6">
|
|
438
|
+
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
|
439
|
+
{/* Controls panel */}
|
|
440
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-5 rounded-xl border p-5">
|
|
441
|
+
<p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold tracking-widest uppercase">
|
|
442
|
+
Active Tab
|
|
1448
443
|
</p>
|
|
1449
|
-
<div className="
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
444
|
+
<div className="space-y-2">
|
|
445
|
+
{tabs.map((tab) => {
|
|
446
|
+
const Icon = tab.icon
|
|
447
|
+
return (
|
|
448
|
+
<button
|
|
449
|
+
key={tab.value}
|
|
450
|
+
onClick={() => setActiveTab(tab.value)}
|
|
451
|
+
className={`font-fm-text text-fm-sm leading-fm-sm flex w-full items-center gap-2 rounded-lg px-3 py-2 text-left transition-colors ${
|
|
452
|
+
activeTab === tab.value
|
|
453
|
+
? "bg-fm-surface-primary text-fm-primary"
|
|
454
|
+
: "text-fm-secondary hover:text-fm-primary"
|
|
455
|
+
}`}
|
|
456
|
+
>
|
|
457
|
+
<Icon className="h-4 w-4 shrink-0" />
|
|
458
|
+
{tab.label}
|
|
459
|
+
</button>
|
|
460
|
+
)
|
|
461
|
+
})}
|
|
462
|
+
</div>
|
|
463
|
+
<div className="border-fm-divider-secondary border-t pt-4" />
|
|
464
|
+
<div className="border-fm-divider-secondary bg-fm-surface-primary rounded-lg border px-4 py-3">
|
|
465
|
+
<code className="text-fm-secondary text-fm-md leading-fm-md font-(--font-fm-mono)">
|
|
466
|
+
value="{activeTab}"
|
|
467
|
+
</code>
|
|
1462
468
|
</div>
|
|
1463
469
|
</div>
|
|
1464
|
-
</TabsContent>
|
|
1465
470
|
|
|
1466
|
-
|
|
1467
|
-
<div className="
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
471
|
+
{/* Preview stage */}
|
|
472
|
+
<div className="flex flex-col gap-3 lg:col-span-2">
|
|
473
|
+
<Tabs
|
|
474
|
+
value={activeTab}
|
|
475
|
+
onValueChange={setActiveTab}
|
|
476
|
+
size="md"
|
|
477
|
+
className="w-full"
|
|
478
|
+
>
|
|
479
|
+
<TabsList>
|
|
480
|
+
{tabs.map((tab) => {
|
|
481
|
+
const Icon = tab.icon
|
|
482
|
+
return (
|
|
483
|
+
<TabsTrigger
|
|
484
|
+
key={tab.value}
|
|
485
|
+
value={tab.value}
|
|
486
|
+
className="gap-2"
|
|
487
|
+
>
|
|
488
|
+
<Icon className="h-4 w-4" />
|
|
489
|
+
{tab.label}
|
|
490
|
+
</TabsTrigger>
|
|
491
|
+
)
|
|
492
|
+
})}
|
|
493
|
+
</TabsList>
|
|
494
|
+
|
|
495
|
+
<TabsContent value="songs" className="mt-4">
|
|
496
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-2 rounded-lg border p-4">
|
|
497
|
+
{songs.map((song) => (
|
|
498
|
+
<div
|
|
499
|
+
key={song.title}
|
|
500
|
+
className="hover:bg-fm-surface-primary flex items-center justify-between rounded-md px-2 py-2 transition-colors"
|
|
501
|
+
>
|
|
502
|
+
<div className="flex items-center gap-3">
|
|
503
|
+
<div className="bg-fm-surface-primary border-fm-divider-secondary flex h-9 w-9 shrink-0 items-center justify-center rounded-md border">
|
|
504
|
+
<MusicalNoteIcon className="text-fm-secondary h-4 w-4" />
|
|
505
|
+
</div>
|
|
506
|
+
<div>
|
|
507
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
508
|
+
{song.title}
|
|
509
|
+
</p>
|
|
510
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
511
|
+
{song.artist}
|
|
512
|
+
</p>
|
|
513
|
+
</div>
|
|
514
|
+
</div>
|
|
515
|
+
<span className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
|
|
516
|
+
{song.duration}
|
|
517
|
+
</span>
|
|
1499
518
|
</div>
|
|
1500
|
-
|
|
1501
|
-
Data synchronized with server
|
|
1502
|
-
</span>
|
|
1503
|
-
</div>
|
|
1504
|
-
</div>
|
|
1505
|
-
</>
|
|
1506
|
-
)}
|
|
1507
|
-
</div>
|
|
1508
|
-
</TabsContent>
|
|
1509
|
-
|
|
1510
|
-
<TabsContent value="error" className="mt-6">
|
|
1511
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
|
|
1512
|
-
<div className="mb-4 flex items-start gap-3">
|
|
1513
|
-
<CrossIcon className="text-fm-icon-negative mt-0.5 h-6 w-6 flex-shrink-0" />
|
|
1514
|
-
<div>
|
|
1515
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
1516
|
-
Error State
|
|
1517
|
-
</h3>
|
|
1518
|
-
<p className="text-fm-secondary">
|
|
1519
|
-
Something went wrong while loading the content.
|
|
1520
|
-
</p>
|
|
1521
|
-
</div>
|
|
1522
|
-
</div>
|
|
1523
|
-
|
|
1524
|
-
<div className="border-fm-divider-secondary bg-fm-surface-secondary mb-4 rounded-lg border p-4">
|
|
1525
|
-
<div className="text-fm-secondary text-sm">
|
|
1526
|
-
<strong>Error:</strong> Failed to fetch data from the server.
|
|
1527
|
-
Please check your connection and try again.
|
|
1528
|
-
</div>
|
|
1529
|
-
</div>
|
|
1530
|
-
|
|
1531
|
-
<div className="flex gap-2">
|
|
1532
|
-
<button className="bg-fm-surface-negative text-fm-surface-primary hover:bg-fm-surface-negative rounded-lg px-4 py-2 transition-colors">
|
|
1533
|
-
Retry
|
|
1534
|
-
</button>
|
|
1535
|
-
<button className="bg-fm-surface-secondary text-fm-primary hover:bg-fm-surface-tertiary rounded-lg px-4 py-2 transition-colors">
|
|
1536
|
-
Report Issue
|
|
1537
|
-
</button>
|
|
1538
|
-
</div>
|
|
1539
|
-
</div>
|
|
1540
|
-
</TabsContent>
|
|
1541
|
-
|
|
1542
|
-
<TabsContent value="success" className="mt-6">
|
|
1543
|
-
<div className="border-fm-divider-positive bg-fm-surface-positive-sec rounded-lg border p-6">
|
|
1544
|
-
<div className="mb-4 flex items-start gap-3">
|
|
1545
|
-
<TickCircleIcon className="text-fm-positive mt-0.5 h-6 w-6 flex-shrink-0" />
|
|
1546
|
-
<div>
|
|
1547
|
-
<h3 className="text-fm-primary text-lg font-semibold">
|
|
1548
|
-
Success State
|
|
1549
|
-
</h3>
|
|
1550
|
-
<p className="text-fm-secondary">
|
|
1551
|
-
Operation completed successfully!
|
|
1552
|
-
</p>
|
|
1553
|
-
</div>
|
|
1554
|
-
</div>
|
|
1555
|
-
|
|
1556
|
-
<div className="space-y-3">
|
|
1557
|
-
<div className="border-fm-divider-positive bg-fm-surface-positive-sec rounded-lg border p-4">
|
|
1558
|
-
<div className="text-fm-positive text-sm">
|
|
1559
|
-
✅ All systems are operational and running smoothly.
|
|
519
|
+
))}
|
|
1560
520
|
</div>
|
|
1561
|
-
</
|
|
1562
|
-
|
|
1563
|
-
<
|
|
1564
|
-
<div className="bg-fm-surface-secondary rounded-lg p-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
521
|
+
</TabsContent>
|
|
522
|
+
|
|
523
|
+
<TabsContent value="albums" className="mt-4">
|
|
524
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-2 rounded-lg border p-4">
|
|
525
|
+
{albums.map((album) => (
|
|
526
|
+
<div
|
|
527
|
+
key={album.title}
|
|
528
|
+
className="hover:bg-fm-surface-primary flex items-center justify-between rounded-md px-2 py-2 transition-colors"
|
|
529
|
+
>
|
|
530
|
+
<div className="flex items-center gap-3">
|
|
531
|
+
<div className="bg-fm-surface-primary border-fm-divider-secondary flex h-12 w-12 shrink-0 items-center justify-center rounded-md border">
|
|
532
|
+
<StarIcon className="text-fm-secondary h-5 w-5" />
|
|
533
|
+
</div>
|
|
534
|
+
<div>
|
|
535
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
536
|
+
{album.title}
|
|
537
|
+
</p>
|
|
538
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
539
|
+
{album.artist}
|
|
540
|
+
</p>
|
|
541
|
+
</div>
|
|
542
|
+
</div>
|
|
543
|
+
<div className="text-right">
|
|
544
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
545
|
+
{album.tracks} tracks
|
|
546
|
+
</p>
|
|
547
|
+
<p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
|
|
548
|
+
{album.year}
|
|
549
|
+
</p>
|
|
550
|
+
</div>
|
|
551
|
+
</div>
|
|
552
|
+
))}
|
|
1571
553
|
</div>
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
554
|
+
</TabsContent>
|
|
555
|
+
|
|
556
|
+
<TabsContent value="artists" className="mt-4">
|
|
557
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-2 rounded-lg border p-4">
|
|
558
|
+
{artists.map((artist) => (
|
|
559
|
+
<div
|
|
560
|
+
key={artist.name}
|
|
561
|
+
className="hover:bg-fm-surface-primary flex items-center justify-between rounded-md px-2 py-2 transition-colors"
|
|
562
|
+
>
|
|
563
|
+
<div className="flex items-center gap-3">
|
|
564
|
+
<div className="bg-fm-surface-primary border-fm-divider-secondary flex h-10 w-10 shrink-0 items-center justify-center rounded-full border">
|
|
565
|
+
<HeartIcon className="text-fm-secondary h-4 w-4" />
|
|
566
|
+
</div>
|
|
567
|
+
<div>
|
|
568
|
+
<p className="text-fm-primary font-fm-text text-fm-md leading-fm-md">
|
|
569
|
+
{artist.name}
|
|
570
|
+
</p>
|
|
571
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
|
|
572
|
+
{artist.genre}
|
|
573
|
+
</p>
|
|
574
|
+
</div>
|
|
575
|
+
</div>
|
|
576
|
+
<span className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
|
|
577
|
+
{artist.listeners}
|
|
578
|
+
</span>
|
|
579
|
+
</div>
|
|
580
|
+
))}
|
|
1577
581
|
</div>
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
582
|
+
</TabsContent>
|
|
583
|
+
|
|
584
|
+
<TabsContent value="about" className="mt-4">
|
|
585
|
+
<div className="border-fm-divider-secondary bg-fm-surface-secondary space-y-4 rounded-lg border p-4">
|
|
586
|
+
<p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
|
|
587
|
+
Aural is a music streaming platform designed for deep
|
|
588
|
+
listeners. Discover new artists, curate playlists, and
|
|
589
|
+
explore lossless audio quality.
|
|
590
|
+
</p>
|
|
591
|
+
<div className="border-fm-divider-secondary bg-fm-surface-primary rounded-lg border px-4 py-3">
|
|
592
|
+
<p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-xl">
|
|
593
|
+
Version 2.4.1 · Last updated April 2026
|
|
594
|
+
</p>
|
|
1581
595
|
</div>
|
|
1582
|
-
<div className="text-fm-secondary text-xs">Performance</div>
|
|
1583
596
|
</div>
|
|
1584
|
-
</
|
|
1585
|
-
</
|
|
597
|
+
</TabsContent>
|
|
598
|
+
</Tabs>
|
|
1586
599
|
</div>
|
|
1587
|
-
</
|
|
1588
|
-
</Tabs>
|
|
1589
|
-
|
|
1590
|
-
<div className="text-fm-secondary text-center text-xs">
|
|
1591
|
-
<p>
|
|
1592
|
-
Current active tab:{" "}
|
|
1593
|
-
<span className="bg-fm-surface-secondary rounded px-2 py-0.5 font-mono">
|
|
1594
|
-
{activeTab}
|
|
1595
|
-
</span>
|
|
1596
|
-
</p>
|
|
1597
|
-
{isLoading && <p className="mt-1">Loading state active...</p>}
|
|
600
|
+
</div>
|
|
1598
601
|
</div>
|
|
1599
602
|
</div>
|
|
1600
603
|
)
|
|
@@ -1603,7 +606,7 @@ export const InteractiveStates: Story = {
|
|
|
1603
606
|
docs: {
|
|
1604
607
|
description: {
|
|
1605
608
|
story:
|
|
1606
|
-
"
|
|
609
|
+
"Stateful audio app tab switcher — Songs, Albums, Artists, About — with a left-side preset panel for controlled tab activation and a live preview stage showing each content panel.",
|
|
1607
610
|
},
|
|
1608
611
|
},
|
|
1609
612
|
},
|