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.
Files changed (175) hide show
  1. package/README.md +8 -1
  2. package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1228
  3. package/dist/components/avatar/Avatar.stories.tsx +219 -235
  4. package/dist/components/badge/Badge.stories.tsx +379 -116
  5. package/dist/components/banner/Banner.stories.tsx +445 -391
  6. package/dist/components/breadcrumb/Breadcrumb.stories.tsx +453 -199
  7. package/dist/components/button/Button.stories.tsx +585 -230
  8. package/dist/components/card/Card.stories.tsx +619 -301
  9. package/dist/components/char-count/CharCount.stories.tsx +350 -248
  10. package/dist/components/checkbox/Checkbox.stories.tsx +309 -167
  11. package/dist/components/chip/Chip.stories.tsx +362 -168
  12. package/dist/components/circular-loader/CircularLoader.stories.tsx +221 -636
  13. package/dist/components/clamp-lines/ClampLines.stories.tsx +246 -117
  14. package/dist/components/collapsible/Collapsible.stories.tsx +391 -252
  15. package/dist/components/command/Command.stories.tsx +530 -867
  16. package/dist/components/dialog/Dialog.stories.tsx +501 -950
  17. package/dist/components/divider/Divider.stories.tsx +264 -527
  18. package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
  19. package/dist/components/drawer/Drawer.stories.tsx +659 -1023
  20. package/dist/components/dropdown/Dropdown.stories.tsx +643 -1028
  21. package/dist/components/form/Form.stories.tsx +560 -274
  22. package/dist/components/helper-text/HelperText.stories.tsx +199 -200
  23. package/dist/components/hover-card/HoverCard.stories.tsx +318 -1254
  24. package/dist/components/icon-button/IconButton.stories.tsx +837 -194
  25. package/dist/components/if-else/if-else.stories.tsx +370 -83
  26. package/dist/components/input/Input.stories.tsx +436 -368
  27. package/dist/components/label/Label.stories.tsx +156 -154
  28. package/dist/components/list/List.stories.tsx +484 -835
  29. package/dist/components/marquee/Marquee.stories.tsx +356 -712
  30. package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -422
  31. package/dist/components/overlay/Overlay.stories.tsx +452 -824
  32. package/dist/components/pagination/Pagination.stories.tsx +721 -210
  33. package/dist/components/popover/Popover.stories.tsx +481 -896
  34. package/dist/components/radio/Radio.stories.tsx +432 -124
  35. package/dist/components/resizable/Resizable.stories.tsx +495 -799
  36. package/dist/components/scroll-area/ScrollArea.stories.tsx +383 -1059
  37. package/dist/components/search/Search.stories.tsx +312 -595
  38. package/dist/components/select/Select.stories.tsx +684 -789
  39. package/dist/components/sheet/Sheet.stories.tsx +671 -950
  40. package/dist/components/skelton/Skelton.stories.tsx +230 -764
  41. package/dist/components/slider/Slider.stories.tsx +383 -760
  42. package/dist/components/stepper/Stepper.stories.tsx +371 -514
  43. package/dist/components/switch/Switch.stories.tsx +461 -208
  44. package/dist/components/switch-case/SwitchCase.stories.tsx +367 -188
  45. package/dist/components/table/Table.stories.tsx +770 -916
  46. package/dist/components/tabs/Tabs.stories.tsx +458 -1455
  47. package/dist/components/tag/Tag.stories.tsx +714 -542
  48. package/dist/components/textarea/TextArea.stories.tsx +621 -562
  49. package/dist/components/thumbnail-tags/ThumbnailTags.stories.tsx +228 -154
  50. package/dist/components/toast/Toast.stories.tsx +452 -1339
  51. package/dist/components/toggle/Toggle.stories.tsx +488 -931
  52. package/dist/components/tooltip/Tooltip.stories.tsx +344 -1388
  53. package/dist/components/typography/Typography.stories.tsx +406 -89
  54. package/dist/hooks/use-change-state/UseChangeState.stories.tsx +309 -606
  55. package/dist/hooks/use-previous/UsePrevious.stories.tsx +367 -917
  56. package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +639 -867
  57. package/dist/icons/Icons.stories.tsx +0 -12
  58. package/dist/icons/ai-avatar-icon/AiAvatarIcon.stories.tsx +223 -1060
  59. package/dist/icons/alert-icon/AlertIcon.stories.tsx +106 -968
  60. package/dist/icons/all-icons.tsx +37 -16
  61. package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +137 -1010
  62. package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +145 -935
  63. package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +132 -1046
  64. package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +134 -986
  65. package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +135 -1028
  66. package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +133 -971
  67. package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +145 -1123
  68. package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +143 -1252
  69. package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +123 -632
  70. package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +141 -1223
  71. package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +164 -1018
  72. package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +121 -1236
  73. package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +121 -1213
  74. package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +116 -893
  75. package/dist/icons/camera-icon/CameraIcon.stories.tsx +109 -1254
  76. package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +114 -975
  77. package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +157 -994
  78. package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +160 -992
  79. package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +140 -970
  80. package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +126 -993
  81. package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +144 -987
  82. package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +141 -1007
  83. package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +147 -1187
  84. package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +110 -476
  85. package/dist/icons/coin-icon/CoinIcon.stories.tsx +120 -1364
  86. package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +113 -1360
  87. package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +111 -942
  88. package/dist/icons/command-icon/CommandIcon.stories.tsx +124 -1087
  89. package/dist/icons/copy-icon/CopyIcon.stories.tsx +119 -996
  90. package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +144 -1046
  91. package/dist/icons/cross-icon/CrossIcon.stories.tsx +136 -999
  92. package/dist/icons/download-icon/DownloadIcon.stories.tsx +123 -857
  93. package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +121 -1080
  94. package/dist/icons/email-icon/EmailIcon.stories.tsx +112 -979
  95. package/dist/icons/expand-icon/ExpandIcon.stories.tsx +109 -1146
  96. package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +141 -1068
  97. package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +140 -1081
  98. package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +124 -1050
  99. package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +123 -1091
  100. package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +122 -633
  101. package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +116 -1087
  102. package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +166 -1020
  103. package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +112 -1182
  104. package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +112 -1155
  105. package/dist/icons/globe-icon/GlobeIcon.stories.tsx +127 -325
  106. package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +142 -985
  107. package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +116 -1217
  108. package/dist/icons/head-icon/HeadIcon.stories.tsx +108 -953
  109. package/dist/icons/heart-icon/HeartIcon.stories.tsx +117 -1060
  110. package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +116 -716
  111. package/dist/icons/image-icon/ImageIcon.stories.tsx +102 -1164
  112. package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +108 -1233
  113. package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +133 -1289
  114. package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +155 -1012
  115. package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +158 -1438
  116. package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +121 -1011
  117. package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +116 -981
  118. package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +116 -979
  119. package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +105 -1252
  120. package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +151 -1554
  121. package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +107 -1227
  122. package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +116 -707
  123. package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +119 -1226
  124. package/dist/icons/message-icon/MessageIcon.stories.tsx +111 -557
  125. package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +112 -1198
  126. package/dist/icons/moon-icon/MoonIcon.stories.tsx +117 -557
  127. package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +106 -1235
  128. package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +112 -1185
  129. package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +116 -1012
  130. package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +108 -1137
  131. package/dist/icons/notes-icon/NotesIcon.stories.tsx +116 -1138
  132. package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +106 -1146
  133. package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +119 -719
  134. package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +110 -999
  135. package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +109 -912
  136. package/dist/icons/pause-icon/PauseIcon.stories.tsx +110 -1041
  137. package/dist/icons/pencil-icon/PencilIcon.stories.tsx +112 -1109
  138. package/dist/icons/phone-icon/PhoneIcon.stories.tsx +112 -1023
  139. package/dist/icons/plus-icon/PlusIcon.stories.tsx +103 -1132
  140. package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +104 -870
  141. package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +99 -476
  142. package/dist/icons/search-icon/SearchIcon.stories.tsx +108 -1161
  143. package/dist/icons/setting-icon/SettingIcon.stories.tsx +104 -1009
  144. package/dist/icons/share-icon/ShareIcon.stories.tsx +117 -1064
  145. package/dist/icons/shield-icon/ShieldIcon.stories.tsx +114 -974
  146. package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +134 -1160
  147. package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +169 -1017
  148. package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +161 -1016
  149. package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +102 -1001
  150. package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +155 -593
  151. package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +155 -608
  152. package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +142 -712
  153. package/dist/icons/star-icon/StarIcon.stories.tsx +120 -946
  154. package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +109 -1013
  155. package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +113 -891
  156. package/dist/icons/sun-icon/SunIcon.stories.tsx +117 -864
  157. package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +113 -989
  158. package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +120 -1027
  159. package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +153 -1476
  160. package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +143 -1187
  161. package/dist/icons/tick-icon/TickIcon.stories.tsx +142 -1322
  162. package/dist/icons/trash-icon/TrashIcon.stories.tsx +105 -970
  163. package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +154 -1457
  164. package/dist/icons/upload-icon/UploadIcon.stories.tsx +112 -930
  165. package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +115 -1019
  166. package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +122 -1092
  167. package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +120 -1401
  168. package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +107 -1212
  169. package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +109 -1122
  170. package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +112 -1124
  171. package/dist/icons/warning-icon/WarningIcon.stories.tsx +119 -1083
  172. package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +158 -983
  173. package/dist/index.cjs +90 -90
  174. package/dist/index.js +90 -90
  175. 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
- PlusIcon,
5
+ HeartIcon,
6
+ MusicalNoteIcon,
9
7
  SearchIcon,
10
- TickCircleIcon,
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
- # Tabs Component
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
- // 1. Basic Tabs
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
- // 2. With Icons
326
- export const WithIcons: Story = {
73
+ export const AllVariants: Story = {
327
74
  render: () => (
328
- <div className="w-full max-w-3xl">
329
- <Tabs defaultValue="dashboard" className="w-full">
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
- <h3 className="text-fm-primary text-lg font-medium">
613
- Medium Size (Default)
614
- </h3>
615
- <Tabs defaultValue="tab1" size="md" className="w-full">
616
- <TabsList className="grid w-full grid-cols-3">
617
- <TabsTrigger value="tab1">Standard</TabsTrigger>
618
- <TabsTrigger value="tab2">Medium</TabsTrigger>
619
- <TabsTrigger value="tab3">Default</TabsTrigger>
620
- </TabsList>
621
- <TabsContent value="tab1" className="mt-4">
622
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
623
- <p className="text-fm-secondary">
624
- Medium tabs provide the perfect balance between visibility and
625
- space efficiency.
626
- </p>
627
- </div>
628
- </TabsContent>
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
- <TabsContent value="normal" className="mt-6">
744
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
745
- <h3 className="text-fm-primary mb-4 text-lg font-semibold">
746
- Normal Size
747
- </h3>
748
- <p className="text-fm-secondary">
749
- This tab uses the default size inherited from the parent Tabs
750
- component (
751
- <code className="bg-fm-surface-secondary rounded px-2 py-1 text-sm">
752
- size="md"
753
- </code>
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
- <TabsContent value="normal2" className="mt-6">
772
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
773
- <h3 className="text-fm-primary mb-4 text-lg font-semibold">
774
- Another Normal Tab
775
- </h3>
776
- <p className="text-fm-secondary">
777
- Another tab using the inherited medium size from the parent
778
- component.
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
- </TabsContent>
129
+ </div>
130
+ </div>
802
131
 
803
- <TabsContent value="large" className="mt-6">
804
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
805
- <h3 className="text-fm-primary mb-4 text-lg font-semibold">
806
- Large Override
807
- </h3>
808
- <p className="text-fm-secondary">
809
- This tab trigger has{" "}
810
- <code className="bg-fm-surface-secondary rounded px-2 py-1 text-sm">
811
- size="lg"
812
- </code>{" "}
813
- which overrides the parent's medium size setting, making it more
814
- prominent.
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
- <div className="text-fm-secondary space-y-1 text-center text-xs">
844
- <p>
845
- Parent Tabs component:{" "}
846
- <code className="bg-fm-surface-secondary rounded px-2 py-0.5 font-mono">
847
- size="md"
848
- </code>
849
- </p>
850
- <p>Individual overrides: Tab 1 (sm), Tab 4 (lg)</p>
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
- "Demonstrates how individual TabsTrigger components can override the parent Tabs size setting. The parent has size='md' but individual triggers can specify their own size for special emphasis.",
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
- // 5. Complex Content (Updated to use size prop)
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
- <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
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="w-full max-w-4xl space-y-8">
193
+ <div className="space-y-8">
194
+ {/* With icons */}
1227
195
  <div className="space-y-4">
1228
- <h3 className="text-fm-primary text-lg font-medium">
1229
- Bottom Glow (Default)
1230
- </h3>
1231
- <Tabs defaultValue="tab1" size="md" className="w-full">
1232
- <TabsList className="grid w-full grid-cols-3">
1233
- <TabsTrigger value="tab1" glowDirection="bottom">
1234
- Dashboard
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="tab2" glowDirection="bottom">
1237
- Reports
205
+ <TabsTrigger value="favorites" className="gap-2">
206
+ <HeartIcon className="h-4 w-4" />
207
+ Favorites
1238
208
  </TabsTrigger>
1239
- <TabsTrigger value="tab3" glowDirection="bottom">
1240
- Profile
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="tab1" className="mt-4">
1244
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1245
- <p className="text-fm-secondary">
1246
- Bottom glow creates an underline effect that emphasizes the
1247
- tab's connection to content below.
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="tab2" className="mt-4">
1252
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1253
- <p className="text-fm-secondary">
1254
- Perfect for interfaces where you want to draw attention to the
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="tab3" className="mt-4">
1260
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1261
- <p className="text-fm-secondary">
1262
- Creates a strong visual connection between the tab and its
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
- <h3 className="text-fm-primary text-lg font-medium">Top Glow</h3>
1272
- <Tabs defaultValue="tab1" size="md" className="w-full">
1273
- <TabsList className="grid w-full grid-cols-3">
1274
- <TabsTrigger value="tab1" glowDirection="top">
1275
- Overview
1276
- </TabsTrigger>
1277
- <TabsTrigger value="tab2" glowDirection="top">
1278
- Analytics
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="tab3" glowDirection="top">
1281
- Settings
250
+ <TabsTrigger value="new" size="lg">
251
+ New (lg)
1282
252
  </TabsTrigger>
1283
253
  </TabsList>
1284
- <TabsContent value="tab1" className="mt-4">
1285
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1286
- <p className="text-fm-secondary">
1287
- Top glow creates a subtle highlight effect above the active tab,
1288
- perfect for elevated interfaces.
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="tab2" className="mt-4">
1293
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1294
- <p className="text-fm-secondary">
1295
- Alternative glow direction for different visual effects.
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="tab3" className="mt-4">
1300
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1301
- <p className="text-fm-secondary">
1302
- Ideal for creating variety in your interface design.
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
- <h3 className="text-fm-primary text-lg font-medium">
1311
- Mixed Glow Directions
1312
- </h3>
1313
- <Tabs defaultValue="tab1" size="md" className="w-full">
1314
- <TabsList className="grid w-full grid-cols-4">
1315
- <TabsTrigger value="tab1" glowDirection="bottom">
1316
- Bottom Glow
1317
- </TabsTrigger>
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="tab3" glowDirection="bottom">
1322
- Bottom Glow
301
+ <TabsTrigger value="top" className="gap-2">
302
+ <StarIcon className="h-4 w-4" />
303
+ Top Tracks
1323
304
  </TabsTrigger>
1324
- <TabsTrigger value="tab4" glowDirection="top">
1325
- Top Glow
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="tab1" className="mt-4">
1329
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1330
- <p className="text-fm-secondary">
1331
- You can mix and match glow directions for different visual
1332
- effects.
1333
- </p>
1334
- </div>
1335
- </TabsContent>
1336
- <TabsContent value="tab2" className="mt-4">
1337
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1338
- <p className="text-fm-secondary">
1339
- Each tab can have its own glow direction for maximum
1340
- flexibility.
1341
- </p>
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="tab3" className="mt-4">
1345
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1346
- <p className="text-fm-secondary">
1347
- Useful for creating visual hierarchy or emphasizing specific
1348
- tabs.
1349
- </p>
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="tab4" className="mt-4">
1353
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1354
- <p className="text-fm-secondary">
1355
- Experiment with different combinations to achieve your desired
1356
- design.
1357
- </p>
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
- "Demonstrates the glowDirection prop with different configurations. Shows top glow (default), bottom glow, and mixed directions for various visual effects.",
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
- // 7. Interactive States (keeping the same as it demonstrates good functionality)
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
- // Simulate loading
1395
- setTimeout(() => {
1396
- setIsLoading(false)
1397
- }, 1000)
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 max-w-3xl space-y-6">
1402
- <div className="text-center">
1403
- <h3 className="text-fm-primary mb-2 text-lg font-medium">
1404
- Interactive States Demo
1405
- </h3>
1406
- <p className="text-fm-secondary text-sm">
1407
- Click tabs to see loading states and transitions
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="grid grid-cols-2 gap-4">
1450
- <div className="border-fm-divider-secondary bg-fm-surface-info-sec rounded-lg border p-3">
1451
- <div className="text-fm-primary text-lg font-semibold">
1452
- 98.5%
1453
- </div>
1454
- <div className="text-fm-secondary text-sm">System Uptime</div>
1455
- </div>
1456
- <div className="border-fm-divider-positive bg-fm-surface-positive-sec rounded-lg border p-3">
1457
- <div className="text-fm-primary text-lg font-semibold">
1458
- 1,247
1459
- </div>
1460
- <div className="text-fm-secondary text-sm">Active Users</div>
1461
- </div>
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=&quot;{activeTab}&quot;
467
+ </code>
1462
468
  </div>
1463
469
  </div>
1464
- </TabsContent>
1465
470
 
1466
- <TabsContent value="loading" className="mt-6">
1467
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-6">
1468
- {isLoading ? (
1469
- <div className="py-8 text-center">
1470
- <div className="border-fm-divider-secondary border-t-fm-primary mx-auto mb-4 h-8 w-8 animate-spin rounded-full border-2" />
1471
- <h3 className="text-fm-primary mb-2 text-lg font-semibold">
1472
- Loading Content...
1473
- </h3>
1474
- <p className="text-fm-secondary">
1475
- Please wait while we fetch the latest data.
1476
- </p>
1477
- </div>
1478
- ) : (
1479
- <>
1480
- <h3 className="text-fm-primary mb-4 text-lg font-semibold">
1481
- Loading State Demo
1482
- </h3>
1483
- <p className="text-fm-secondary mb-4">
1484
- This tab demonstrates loading states and async content
1485
- fetching.
1486
- </p>
1487
- <div className="space-y-3">
1488
- <div className="bg-fm-surface-secondary flex items-center gap-3 rounded-lg p-3">
1489
- <div className="bg-fm-surface-positive flex h-5 w-5 items-center justify-center rounded-full">
1490
- <TickCircleIcon className="text-fm-primary h-3 w-3" />
1491
- </div>
1492
- <span className="text-fm-secondary">
1493
- Content loaded successfully
1494
- </span>
1495
- </div>
1496
- <div className="bg-fm-surface-secondary flex items-center gap-3 rounded-lg p-3">
1497
- <div className="bg-fm-surface-info flex h-5 w-5 items-center justify-center rounded-full">
1498
- <AlertIcon className="text-fm-primary h-3 w-3" />
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
- <span className="text-fm-secondary">
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
- </div>
1562
-
1563
- <div className="grid grid-cols-3 gap-3">
1564
- <div className="bg-fm-surface-secondary rounded-lg p-3 text-center">
1565
- <div className="text-fm-primary text-lg font-semibold">
1566
- 100%
1567
- </div>
1568
- <div className="text-fm-secondary text-xs">
1569
- Success Rate
1570
- </div>
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
- <div className="bg-fm-surface-secondary rounded-lg p-3 text-center">
1573
- <div className="text-fm-primary text-lg font-semibold">
1574
- 0ms
1575
- </div>
1576
- <div className="text-fm-secondary text-xs">Error Rate</div>
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
- <div className="bg-fm-surface-secondary rounded-lg p-3 text-center">
1579
- <div className="text-fm-primary text-lg font-semibold">
1580
- Fast
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
- </div>
1585
- </div>
597
+ </TabsContent>
598
+ </Tabs>
1586
599
  </div>
1587
- </TabsContent>
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
- "Interactive states demonstration showing loading, error, and success states with real-time tab switching using the new size prop approach.",
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
  },