aural-ui 4.0.1 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/dist/components/aspect-ratio/AspectRatio.stories.tsx +290 -1228
  2. package/dist/components/avatar/Avatar.stories.tsx +219 -235
  3. package/dist/components/badge/Badge.stories.tsx +379 -116
  4. package/dist/components/banner/Banner.stories.tsx +445 -391
  5. package/dist/components/breadcrumb/Breadcrumb.stories.tsx +453 -199
  6. package/dist/components/button/Button.stories.tsx +585 -230
  7. package/dist/components/card/Card.stories.tsx +619 -301
  8. package/dist/components/char-count/CharCount.stories.tsx +350 -248
  9. package/dist/components/checkbox/Checkbox.stories.tsx +309 -167
  10. package/dist/components/chip/Chip.stories.tsx +362 -168
  11. package/dist/components/circular-loader/CircularLoader.stories.tsx +221 -636
  12. package/dist/components/clamp-lines/ClampLines.stories.tsx +246 -117
  13. package/dist/components/collapsible/Collapsible.stories.tsx +391 -252
  14. package/dist/components/command/Command.stories.tsx +530 -867
  15. package/dist/components/dialog/Dialog.stories.tsx +501 -950
  16. package/dist/components/divider/Divider.stories.tsx +264 -527
  17. package/dist/components/dot-loader/DotLoader.stories.tsx +256 -257
  18. package/dist/components/drawer/Drawer.stories.tsx +659 -1023
  19. package/dist/components/dropdown/Dropdown.stories.tsx +643 -1028
  20. package/dist/components/form/Form.stories.tsx +560 -274
  21. package/dist/components/helper-text/HelperText.stories.tsx +199 -200
  22. package/dist/components/hover-card/HoverCard.stories.tsx +318 -1254
  23. package/dist/components/icon-button/IconButton.stories.tsx +837 -194
  24. package/dist/components/if-else/if-else.stories.tsx +370 -83
  25. package/dist/components/input/Input.stories.tsx +436 -368
  26. package/dist/components/label/Label.stories.tsx +156 -154
  27. package/dist/components/list/List.stories.tsx +484 -835
  28. package/dist/components/marquee/Marquee.stories.tsx +356 -712
  29. package/dist/components/otp-inputs/OtpInputs.stories.tsx +352 -422
  30. package/dist/components/overlay/Overlay.stories.tsx +452 -824
  31. package/dist/components/pagination/Pagination.stories.tsx +721 -210
  32. package/dist/components/popover/Popover.stories.tsx +481 -896
  33. package/dist/components/radio/Radio.stories.tsx +432 -124
  34. package/dist/components/resizable/Resizable.stories.tsx +495 -799
  35. package/dist/components/scroll-area/ScrollArea.stories.tsx +383 -1059
  36. package/dist/components/search/Search.stories.tsx +312 -595
  37. package/dist/components/select/Select.stories.tsx +684 -789
  38. package/dist/components/sheet/Sheet.stories.tsx +671 -950
  39. package/dist/components/skelton/Skelton.stories.tsx +230 -764
  40. package/dist/components/slider/Slider.stories.tsx +383 -760
  41. package/dist/components/stepper/Stepper.stories.tsx +371 -514
  42. package/dist/components/switch/Switch.stories.tsx +461 -208
  43. package/dist/components/switch-case/SwitchCase.stories.tsx +367 -188
  44. package/dist/components/table/Table.stories.tsx +770 -916
  45. package/dist/components/tabs/Tabs.stories.tsx +458 -1455
  46. package/dist/components/tag/Tag.stories.tsx +714 -542
  47. package/dist/components/textarea/TextArea.stories.tsx +621 -562
  48. package/dist/components/thumbnail-tags/ThumbnailTags.stories.tsx +228 -154
  49. package/dist/components/toast/Toast.stories.tsx +452 -1339
  50. package/dist/components/toggle/Toggle.stories.tsx +488 -931
  51. package/dist/components/tooltip/Tooltip.stories.tsx +344 -1388
  52. package/dist/components/typography/Typography.stories.tsx +406 -89
  53. package/dist/hooks/use-change-state/UseChangeState.stories.tsx +309 -606
  54. package/dist/hooks/use-previous/UsePrevious.stories.tsx +367 -917
  55. package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +639 -867
  56. package/dist/icons/Icons.stories.tsx +0 -12
  57. package/dist/icons/ai-avatar-icon/AiAvatarIcon.stories.tsx +223 -1060
  58. package/dist/icons/alert-icon/AlertIcon.stories.tsx +106 -968
  59. package/dist/icons/all-icons.tsx +37 -16
  60. package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +137 -1010
  61. package/dist/icons/apple-logo-icon/AppleLogoIcon.stories.tsx +145 -935
  62. package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +132 -1046
  63. package/dist/icons/arrow-corner-up-left-icon/ArrowCornerUpLeftIcon.stories.tsx +134 -986
  64. package/dist/icons/arrow-corner-up-right-icon/ArrowCornerUpRightIcon.stories.tsx +135 -1028
  65. package/dist/icons/arrow-left-icon/ArrowLeftIcon.stories.tsx +133 -971
  66. package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +145 -1123
  67. package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +143 -1252
  68. package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +123 -632
  69. package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +141 -1223
  70. package/dist/icons/backward-ten-seconds-icon/BackwardTenSecondsIcon.stories.tsx +164 -1018
  71. package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +121 -1236
  72. package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +121 -1213
  73. package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +116 -893
  74. package/dist/icons/camera-icon/CameraIcon.stories.tsx +109 -1254
  75. package/dist/icons/capital-a-letter-icon/CapitalALetterIcon.stories.tsx +114 -975
  76. package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +157 -994
  77. package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +160 -992
  78. package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +140 -970
  79. package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +126 -993
  80. package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +144 -987
  81. package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +141 -1007
  82. package/dist/icons/circle-tick-icon/CircleTickIcon.stories.tsx +147 -1187
  83. package/dist/icons/circular-play-icon/CircularPlayIcon.stories.tsx +110 -476
  84. package/dist/icons/coin-icon/CoinIcon.stories.tsx +120 -1364
  85. package/dist/icons/coin-toons-icon/CoinToonsIcon.stories.tsx +113 -1360
  86. package/dist/icons/column-wide-add-icon/ColumnWideAddIcon.stories.tsx +111 -942
  87. package/dist/icons/command-icon/CommandIcon.stories.tsx +124 -1087
  88. package/dist/icons/copy-icon/CopyIcon.stories.tsx +119 -996
  89. package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +144 -1046
  90. package/dist/icons/cross-icon/CrossIcon.stories.tsx +136 -999
  91. package/dist/icons/download-icon/DownloadIcon.stories.tsx +123 -857
  92. package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +121 -1080
  93. package/dist/icons/email-icon/EmailIcon.stories.tsx +112 -979
  94. package/dist/icons/expand-icon/ExpandIcon.stories.tsx +109 -1146
  95. package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +141 -1068
  96. package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +140 -1081
  97. package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +124 -1050
  98. package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +123 -1091
  99. package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +122 -633
  100. package/dist/icons/filter-bar-row-icon/FilterBarRowIcon.stories.tsx +116 -1087
  101. package/dist/icons/forward-ten-seconds-icon/ForwardTenSecondsIcon.stories.tsx +166 -1020
  102. package/dist/icons/git-branch-icon/GitBranchIcon.stories.tsx +112 -1182
  103. package/dist/icons/git-fork-icon/GitForkIcon.stories.tsx +112 -1155
  104. package/dist/icons/globe-icon/GlobeIcon.stories.tsx +127 -325
  105. package/dist/icons/google-logo-icon/GoogleLogoIcon.stories.tsx +142 -985
  106. package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +116 -1217
  107. package/dist/icons/head-icon/HeadIcon.stories.tsx +108 -953
  108. package/dist/icons/heart-icon/HeartIcon.stories.tsx +117 -1060
  109. package/dist/icons/image-avatar-sparkle-icon/ImageAvatarSparkleIcon.stories.tsx +116 -716
  110. package/dist/icons/image-icon/ImageIcon.stories.tsx +102 -1164
  111. package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +108 -1233
  112. package/dist/icons/import-left-arrow-folder-icon/ImportLeftArrowFolderIcon.stories.tsx +133 -1289
  113. package/dist/icons/indian-flag-icon/IndianFlagIcon.stories.tsx +155 -1012
  114. package/dist/icons/instagram-icon/InstagramIcon.stories.tsx +158 -1438
  115. package/dist/icons/layout-column-icon/LayoutColumnIcon.stories.tsx +121 -1011
  116. package/dist/icons/layout-left-icon/LayoutLeftIcon.stories.tsx +116 -981
  117. package/dist/icons/layout-right-icon/LayoutRightIcon.stories.tsx +116 -979
  118. package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +105 -1252
  119. package/dist/icons/linked-in-icon/LinkedInIcon.stories.tsx +151 -1554
  120. package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +107 -1227
  121. package/dist/icons/magic-edit-icon/MagicEditIcon.stories.tsx +116 -707
  122. package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +119 -1226
  123. package/dist/icons/message-icon/MessageIcon.stories.tsx +111 -557
  124. package/dist/icons/minimize-icon/MinimizeIcon.stories.tsx +112 -1198
  125. package/dist/icons/moon-icon/MoonIcon.stories.tsx +117 -557
  126. package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +106 -1235
  127. package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +112 -1185
  128. package/dist/icons/musical-note-icon/MusicalNoteIcon.stories.tsx +116 -1012
  129. package/dist/icons/notepad-icon/NotepadIcon.stories.tsx +108 -1137
  130. package/dist/icons/notes-icon/NotesIcon.stories.tsx +116 -1138
  131. package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +106 -1146
  132. package/dist/icons/page-text-icon/PageTextIcon.stories.tsx +119 -719
  133. package/dist/icons/paint-roll-icon/PaintRollIcon.stories.tsx +110 -999
  134. package/dist/icons/paper-plane-icon/PaperPlaneIcon.stories.tsx +109 -912
  135. package/dist/icons/pause-icon/PauseIcon.stories.tsx +110 -1041
  136. package/dist/icons/pencil-icon/PencilIcon.stories.tsx +112 -1109
  137. package/dist/icons/phone-icon/PhoneIcon.stories.tsx +112 -1023
  138. package/dist/icons/plus-icon/PlusIcon.stories.tsx +103 -1132
  139. package/dist/icons/pocket-studio-icon/PocketStudioIcon.stories.tsx +104 -870
  140. package/dist/icons/scroll-down-icon/ScrollDownIcon.stories.tsx +99 -476
  141. package/dist/icons/search-icon/SearchIcon.stories.tsx +108 -1161
  142. package/dist/icons/setting-icon/SettingIcon.stories.tsx +104 -1009
  143. package/dist/icons/share-icon/ShareIcon.stories.tsx +117 -1064
  144. package/dist/icons/shield-icon/ShieldIcon.stories.tsx +114 -974
  145. package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +134 -1160
  146. package/dist/icons/skip-backward-icon/SkipBackwardIcon.stories.tsx +169 -1017
  147. package/dist/icons/skip-forward-icon/SkipForwardIcon.stories.tsx +161 -1016
  148. package/dist/icons/sparkles-soft-icon/SparklesSoftIcon.stories.tsx +102 -1001
  149. package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +155 -593
  150. package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +155 -608
  151. package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +142 -712
  152. package/dist/icons/star-icon/StarIcon.stories.tsx +120 -946
  153. package/dist/icons/store-coin-icon/StoreCoinIcon.stories.tsx +109 -1013
  154. package/dist/icons/suggestion-icon/SuggestionIcon.stories.tsx +113 -891
  155. package/dist/icons/sun-icon/SunIcon.stories.tsx +117 -864
  156. package/dist/icons/text-color-icon/TextColorIcon.stories.tsx +113 -989
  157. package/dist/icons/text-indicator-icon/TextIndicatorIcon.stories.tsx +120 -1027
  158. package/dist/icons/threads-icon/ThreadsIcon.stories.tsx +153 -1476
  159. package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +143 -1187
  160. package/dist/icons/tick-icon/TickIcon.stories.tsx +142 -1322
  161. package/dist/icons/trash-icon/TrashIcon.stories.tsx +105 -970
  162. package/dist/icons/twitter-x-icon/TwitterXIcon.stories.tsx +154 -1457
  163. package/dist/icons/upload-icon/UploadIcon.stories.tsx +112 -930
  164. package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +115 -1019
  165. package/dist/icons/video-play-list-icon/VideoPlaylistIcon.stories.tsx +122 -1092
  166. package/dist/icons/voice-playing-icon/VoicePlayingIcon.stories.tsx +120 -1401
  167. package/dist/icons/volume-full-icon/VolumeFullIcon.stories.tsx +107 -1212
  168. package/dist/icons/volume-half-icon/VolumeHalfIcon.stories.tsx +109 -1122
  169. package/dist/icons/volume-off-icon/VolumeOffIcon.stories.tsx +112 -1124
  170. package/dist/icons/warning-icon/WarningIcon.stories.tsx +119 -1083
  171. package/dist/icons/youtube-icon/YoutubeIcon.stories.tsx +158 -983
  172. package/dist/index.cjs +1 -1
  173. package/dist/index.js +1 -1
  174. package/package.json +1 -1
@@ -1,16 +1,9 @@
1
1
  import React from "react"
2
- import {
3
- AlertIcon,
4
- EditBigIcon,
5
- EyeOpenIcon,
6
- FileChartIcon,
7
- PlusIcon,
8
- SearchIcon,
9
- TickCircleIcon,
10
- TrashIcon,
11
- } from "@icons/index"
2
+ import { MusicalNoteIcon, TickCircleIcon } from "@icons/index"
12
3
  import type { Meta, StoryObj } from "@storybook/react-vite"
13
4
 
5
+ import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
6
+
14
7
  import Marquee from "."
15
8
 
16
9
  const meta: Meta<typeof Marquee> = {
@@ -18,114 +11,29 @@ const meta: Meta<typeof Marquee> = {
18
11
  component: Marquee,
19
12
  parameters: {
20
13
  layout: "centered",
21
- backgrounds: {
22
- default: "dark",
23
- values: [
24
- { name: "dark", value: "#0a0a0a" },
25
- { name: "light", value: "#ffffff" },
26
- ],
27
- },
28
14
  docs: {
29
15
  description: {
30
- component: `
31
- # Marquee Component
32
-
33
- A smooth, customizable marquee component for creating continuous scrolling content animations. Perfect for displaying logos, announcements, testimonials, or any repeating content.
34
-
35
- ## Features
36
-
37
- - **Horizontal & Vertical**: Support for both horizontal and vertical scrolling
38
- - **Pause on Hover**: Optional pause animation when hovering
39
- - **Reverse Direction**: Ability to reverse the animation direction
40
- - **Customizable Speed**: Control animation duration via CSS custom properties
41
- - **Responsive Design**: Adapts to container width and content
42
- - **Smooth Animation**: Hardware-accelerated CSS animations
43
- - **Repeat Control**: Configure how many times content repeats
44
- - **Gap Control**: Customizable spacing between repeated items
45
-
46
- ## Props
47
-
48
- ### Core Props
49
- - **children**: Content to be animated in the marquee
50
- - **className**: Additional CSS classes for the container
51
- - **itemClassName**: CSS classes for individual marquee items
52
- - **vertical**: Switch between horizontal (default) and vertical scrolling
53
- - **reverse**: Reverse the animation direction
54
- - **pauseOnHover**: Pause animation when hovering (default: false)
55
- - **repeat**: Number of times to repeat the content (default: 4)
56
-
57
- ## Usage Examples
58
-
59
- ### Basic Horizontal Marquee
60
- \`\`\`tsx
61
- <Marquee>
62
- <div>Item 1</div>
63
- <div>Item 2</div>
64
- <div>Item 3</div>
65
- </Marquee>
66
- \`\`\`
67
-
68
- ### Vertical Marquee
69
- \`\`\`tsx
70
- <Marquee vertical>
71
- <div>Vertical Item 1</div>
72
- <div>Vertical Item 2</div>
73
- <div>Vertical Item 3</div>
74
- </Marquee>
75
- \`\`\`
76
-
77
- ### With Pause on Hover
78
- \`\`\`tsx
79
- <Marquee pauseOnHover>
80
- <div>Hover to pause</div>
81
- <div>This content</div>
82
- </Marquee>
83
- \`\`\`
84
-
85
- ### Reverse Direction
86
- \`\`\`tsx
87
- <Marquee reverse>
88
- <div>Reversed</div>
89
- <div>Animation</div>
90
- </Marquee>
91
- \`\`\`
92
-
93
- ### Custom Speed
94
- \`\`\`tsx
95
- <Marquee
96
- className="[--duration:20s]"
97
- style={{ '--duration': '20s' }}
98
- >
99
- <div>Faster animation</div>
100
- </Marquee>
101
- \`\`\`
102
-
103
- ## Use Cases
104
-
105
- - **Logo Carousels**: Showcase partner or client logos
106
- - **News Tickers**: Display breaking news or announcements
107
- - **Testimonials**: Rotating customer testimonials
108
- - **Social Media Feeds**: Live social media content
109
- - **Product Showcases**: Continuous product displays
110
- - **Stock Tickers**: Financial data displays
111
- - **Event Announcements**: Scrolling event information
112
-
113
- ## Accessibility
114
-
115
- - Consider users with motion sensitivity
116
- - Provide pause controls for accessibility
117
- - Ensure content is accessible via keyboard navigation
118
- - Don't rely solely on marquee for critical information
119
- - Test with screen readers for content accessibility
120
-
121
- ## Performance
122
-
123
- - Uses CSS transforms for hardware acceleration
124
- - Minimal JavaScript overhead
125
- - Efficient DOM structure with repeated elements
126
- - Smooth 60fps animations on modern browsers
127
- `,
16
+ component:
17
+ "A smooth, CSS-animated marquee component for continuous horizontal or vertical scrolling content. Supports pause-on-hover, reverse direction, configurable speed, repeat count, and gutter spacing.",
128
18
  },
19
+ page: () => (
20
+ <AuralComponentDocsPage
21
+ features={[
22
+ {
23
+ title: "Horizontal & Vertical",
24
+ description: "Direction via prop",
25
+ },
26
+ {
27
+ title: "Pause on Hover",
28
+ description: "Built-in hover pause",
29
+ },
30
+ {
31
+ title: "Speed & Gutter",
32
+ description: "CSS duration and gap",
33
+ },
34
+ ]}
35
+ />
36
+ ),
129
37
  },
130
38
  },
131
39
  tags: ["autodocs"],
@@ -140,27 +48,19 @@ A smooth, customizable marquee component for creating continuous scrolling conte
140
48
  },
141
49
  pauseOnHover: {
142
50
  control: "boolean",
143
- description: "Pause animation when hovering",
51
+ description: "Pause animation when the pointer is over the marquee",
144
52
  },
145
53
  repeat: {
146
54
  control: { type: "number", min: 1, max: 10, step: 1 },
147
- description: "Number of times to repeat the content",
148
- },
149
- className: {
150
- control: "text",
151
- description: "Additional CSS classes for the container",
152
- },
153
- itemClassName: {
154
- control: "text",
155
- description: "CSS classes for individual marquee items",
55
+ description: "Number of times to repeat the children",
156
56
  },
157
57
  gutter: {
158
58
  control: "text",
159
- description: "Spacing between repeated items (default: 1rem)",
59
+ description: "Gap between repeated instances (CSS value, default: 1rem)",
160
60
  },
161
61
  duration: {
162
62
  control: "text",
163
- description: "Animation duration in seconds (default: 40s)",
63
+ description: "Animation cycle duration (CSS time value, default: 40s)",
164
64
  },
165
65
  },
166
66
  }
@@ -168,535 +68,240 @@ A smooth, customizable marquee component for creating continuous scrolling conte
168
68
  export default meta
169
69
  type Story = StoryObj<typeof Marquee>
170
70
 
171
- // 1. Basic Marquee
172
- export const Basic: Story = {
173
- args: {
174
- children: (
175
- <>
176
- <div className="flex h-16 w-32 items-center justify-center rounded-lg bg-blue-500/20 text-sm font-medium text-blue-300">
177
- Item 1
178
- </div>
179
- <div className="flex h-16 w-32 items-center justify-center rounded-lg bg-green-500/20 text-sm font-medium text-green-300">
180
- Item 2
181
- </div>
182
- <div className="flex h-16 w-32 items-center justify-center rounded-lg bg-purple-500/20 text-sm font-medium text-purple-300">
183
- Item 3
184
- </div>
185
- <div className="flex h-16 w-32 items-center justify-center rounded-lg bg-orange-500/20 text-sm font-medium text-orange-300">
186
- Item 4
187
- </div>
188
- </>
189
- ),
190
- },
191
- parameters: {
192
- docs: {
193
- description: {
194
- story: "A basic horizontal marquee with simple content blocks.",
195
- },
196
- },
197
- },
198
- }
199
-
200
- // 2. Logo Carousel
201
- export const LogoCarousel: Story = {
202
- render: () => (
203
- <div className="w-full max-w-4xl">
204
- <h3 className="text-fm-primary mb-6 text-center text-lg font-medium">
205
- Our Partners
206
- </h3>
207
- <Marquee pauseOnHover={false} duration="30s">
208
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary flex h-20 w-40 items-center justify-center rounded-lg border transition-colors">
209
- <div className="text-center">
210
- <div className="text-fm-primary text-2xl font-bold">ACME</div>
211
- <div className="text-fm-secondary text-xs">Corporation</div>
212
- </div>
213
- </div>
214
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary flex h-20 w-40 items-center justify-center rounded-lg border transition-colors">
215
- <div className="text-center">
216
- <div className="text-fm-icon-info text-2xl font-bold">TechCorp</div>
217
- <div className="text-fm-secondary text-xs">Innovation</div>
218
- </div>
219
- </div>
220
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary flex h-20 w-40 items-center justify-center rounded-lg border transition-colors">
221
- <div className="text-center">
222
- <div className="text-fm-icon-positive text-2xl font-bold">
223
- GlobalTech
224
- </div>
225
- <div className="text-fm-secondary text-xs">Solutions</div>
226
- </div>
227
- </div>
228
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary flex h-20 w-40 items-center justify-center rounded-lg border transition-colors">
229
- <div className="text-center">
230
- <div className="text-fm-icon-brand-secondary text-2xl font-bold">
231
- InnovateLab
232
- </div>
233
- <div className="text-fm-secondary text-xs">Research</div>
234
- </div>
235
- </div>
236
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary flex h-20 w-40 items-center justify-center rounded-lg border transition-colors">
237
- <div className="text-center">
238
- <div className="text-2xl font-bold text-orange-400">FutureTech</div>
239
- <div className="text-fm-secondary text-xs">Systems</div>
240
- </div>
241
- </div>
242
- </Marquee>
71
+ // ─── shared content helpers ───────────────────────────────────────────────────
72
+
73
+ /** A pill-shaped label card styled with design tokens only */
74
+ function TokenChip({
75
+ label,
76
+ surface,
77
+ }: {
78
+ label: string
79
+ surface:
80
+ | "secondary"
81
+ | "info-sec"
82
+ | "positive-sec"
83
+ | "warning-sec"
84
+ | "negative-sec"
85
+ }) {
86
+ const surfaceClass = {
87
+ secondary: "bg-fm-surface-secondary border-fm-divider-secondary",
88
+ "info-sec": "bg-fm-surface-info-sec border-fm-divider-secondary",
89
+ "positive-sec": "bg-fm-surface-positive-sec border-fm-divider-secondary",
90
+ "warning-sec": "bg-fm-surface-warning-sec border-fm-divider-secondary",
91
+ "negative-sec": "bg-fm-surface-negative-sec border-fm-divider-secondary",
92
+ }[surface]
93
+
94
+ return (
95
+ <div
96
+ className={`flex h-10 items-center rounded-full border px-4 whitespace-nowrap ${surfaceClass}`}
97
+ >
98
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm font-medium">
99
+ {label}
100
+ </span>
243
101
  </div>
244
- ),
245
- parameters: {
246
- docs: {
247
- description: {
248
- story:
249
- "A logo carousel showcasing partner companies with hover pause functionality.",
250
- },
251
- },
252
- },
102
+ )
253
103
  }
254
104
 
255
- // 3. News Ticker
256
- export const NewsTicker: Story = {
257
- render: () => (
258
- <div className="w-full max-w-4xl">
259
- <div className="bg-fm-surface-negative text-fm-surface-primary flex items-center px-4 py-2 text-sm font-medium">
260
- <span className="bg-fm-surface-primary text-fm-icon-negative mr-3 rounded px-2 py-1 text-xs font-bold">
261
- LIVE
105
+ /** Artist avatar card using design tokens */
106
+ function ArtistCard({ initials, name }: { initials: string; name: string }) {
107
+ return (
108
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary flex w-32 flex-col items-center gap-2 rounded-xl border p-3">
109
+ <div className="border-fm-divider-secondary bg-fm-surface-tertiary flex size-12 items-center justify-center rounded-full border">
110
+ <span className="text-fm-primary font-fm-brand text-fm-md leading-fm-md font-semibold">
111
+ {initials}
262
112
  </span>
263
- <Marquee duration="25s" pauseOnHover>
264
- <span className="whitespace-nowrap">
265
- 🔴 Breaking: New product launch scheduled for next month
266
- </span>
267
- <span className="whitespace-nowrap">
268
- 📈 Stock market reaches new highs as tech sector surges
269
- </span>
270
- <span className="whitespace-nowrap">
271
- 🚀 Space mission successfully launches with international crew
272
- </span>
273
- <span className="whitespace-nowrap">
274
- 💡 Revolutionary AI breakthrough announced by research team
275
- </span>
276
- </Marquee>
277
113
  </div>
114
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm truncate text-center">
115
+ {name}
116
+ </p>
278
117
  </div>
279
- ),
280
- parameters: {
281
- docs: {
282
- description: {
283
- story: "A news ticker with live updates and breaking news format.",
284
- },
285
- },
286
- },
118
+ )
287
119
  }
288
120
 
289
- // 4. Testimonials
290
- export const Testimonials: Story = {
291
- render: () => (
292
- <div className="w-full max-w-5xl">
293
- <h3 className="text-fm-primary mb-6 text-center text-lg font-medium">
294
- What Our Customers Say
295
- </h3>
296
- <Marquee pauseOnHover duration="35s">
297
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary w-80 rounded-lg border p-6 transition-colors">
298
- <div className="flex items-start space-x-4">
299
- <div className="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-blue-500 to-purple-600">
300
- <span className="text-fm-primary font-semibold">JD</span>
301
- </div>
302
- <div className="space-y-2">
303
- <p className="text-fm-secondary text-sm leading-relaxed">
304
- "This product has completely transformed our workflow. The
305
- intuitive design and powerful features make it indispensable."
306
- </p>
307
- <div>
308
- <div className="text-fm-primary text-sm font-medium">
309
- John Doe
310
- </div>
311
- <div className="text-fm-secondary text-xs">CEO, TechStart</div>
312
- </div>
313
- </div>
314
- </div>
315
- </div>
121
+ // ─── 1. Playground ────────────────────────────────────────────────────────────
316
122
 
317
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary w-80 rounded-lg border p-6 transition-colors">
318
- <div className="flex items-start space-x-4">
319
- <div className="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-green-500 to-teal-600">
320
- <span className="text-fm-primary font-semibold">SS</span>
321
- </div>
322
- <div className="space-y-2">
323
- <p className="text-fm-secondary text-sm leading-relaxed">
324
- "Outstanding customer support and a product that delivers on all
325
- its promises. Highly recommended for any team."
326
- </p>
327
- <div>
328
- <div className="text-fm-primary text-sm font-medium">
329
- Sarah Smith
330
- </div>
331
- <div className="text-fm-secondary text-xs">
332
- Designer, CreativeHub
333
- </div>
334
- </div>
335
- </div>
336
- </div>
337
- </div>
338
-
339
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary w-80 rounded-lg border p-6 transition-colors">
340
- <div className="flex items-start space-x-4">
341
- <div className="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-orange-500 to-red-600">
342
- <span className="text-fm-primary font-semibold">MJ</span>
343
- </div>
344
- <div className="space-y-2">
345
- <p className="text-fm-secondary text-sm leading-relaxed">
346
- "The ROI has been incredible. We've seen a 300% increase in
347
- productivity since implementation."
348
- </p>
349
- <div>
350
- <div className="text-fm-primary text-sm font-medium">
351
- Mike Johnson
352
- </div>
353
- <div className="text-fm-secondary text-xs">
354
- CTO, InnovateNow
355
- </div>
356
- </div>
357
- </div>
358
- </div>
359
- </div>
123
+ export const Playground: Story = {
124
+ args: {
125
+ pauseOnHover: true,
126
+ reverse: false,
127
+ vertical: false,
128
+ repeat: 4,
129
+ gutter: "1rem",
130
+ duration: "35s",
131
+ },
132
+ render: (args) => (
133
+ <div className="w-full max-w-2xl space-y-4">
134
+ <Marquee {...args}>
135
+ <TokenChip label="Electronic" surface="secondary" />
136
+ <TokenChip label="Hip-Hop" surface="secondary" />
137
+ <TokenChip label="Jazz" surface="secondary" />
138
+ <TokenChip label="Ambient" surface="secondary" />
139
+ <TokenChip label="R&B" surface="secondary" />
140
+ <TokenChip label="Indie" surface="secondary" />
141
+ <TokenChip label="Soul" surface="secondary" />
360
142
  </Marquee>
143
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border px-4 py-3">
144
+ <code className="text-fm-secondary text-fm-md leading-fm-md font-(--font-fm-mono)">{`<Marquee duration="${args.duration}" reverse={${args.reverse}} pauseOnHover={${args.pauseOnHover}} vertical={${args.vertical}} repeat={${args.repeat}} gutter="${args.gutter}" />`}</code>
145
+ </div>
361
146
  </div>
362
147
  ),
363
148
  parameters: {
364
149
  docs: {
365
150
  description: {
366
151
  story:
367
- "Customer testimonials in card format with avatars and company information.",
152
+ "Controls-driven playground. Use the Storybook sidebar to adjust duration, direction, pause-on-hover, orientation, repeat count, and gutter spacing.",
368
153
  },
369
154
  },
370
155
  },
371
156
  }
372
157
 
373
- // 5. Icon Showcase
374
- export const IconShowcase: Story = {
158
+ // ─── 2. Configurations ────────────────────────────────────────────────────────
159
+
160
+ export const Configurations: Story = {
375
161
  render: () => (
376
162
  <div className="w-full max-w-4xl space-y-8">
377
- <h3 className="text-fm-primary text-center text-lg font-medium">
378
- Feature Icons
379
- </h3>
380
-
381
- {/* Horizontal Icons */}
382
- <div className="space-y-4">
383
- <h4 className="text-fm-secondary text-center text-sm font-medium">
384
- Horizontal Scroll
163
+ {/* Horizontal (default) */}
164
+ <div className="space-y-3">
165
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
166
+ Horizontal (default)
385
167
  </h4>
386
- <Marquee pauseOnHover duration="20s">
387
- <div className="flex w-24 flex-col items-center space-y-2">
388
- <div className="flex h-16 w-16 items-center justify-center rounded-lg bg-blue-500/20">
389
- <SearchIcon className="text-fm-icon-info h-8 w-8" />
390
- </div>
391
- <span className="text-fm-secondary text-xs">Search</span>
392
- </div>
393
- <div className="flex w-24 flex-col items-center space-y-2">
394
- <div className="flex h-16 w-16 items-center justify-center rounded-lg bg-green-500/20">
395
- <TickCircleIcon className="text-fm-icon-positive h-8 w-8" />
396
- </div>
397
- <span className="text-fm-secondary text-xs">Complete</span>
398
- </div>
399
- <div className="flex w-24 flex-col items-center space-y-2">
400
- <div className="flex h-16 w-16 items-center justify-center rounded-lg bg-purple-500/20">
401
- <EditBigIcon className="text-fm-icon-brand-secondary h-8 w-8" />
402
- </div>
403
- <span className="text-fm-secondary text-xs">Edit</span>
404
- </div>
405
- <div className="flex w-24 flex-col items-center space-y-2">
406
- <div className="flex h-16 w-16 items-center justify-center rounded-lg bg-orange-500/20">
407
- <FileChartIcon className="text-fm-icon-warning h-8 w-8" />
408
- </div>
409
- <span className="text-fm-secondary text-xs">Analytics</span>
410
- </div>
411
- <div className="flex w-24 flex-col items-center space-y-2">
412
- <div className="flex h-16 w-16 items-center justify-center rounded-lg bg-red-500/20">
413
- <AlertIcon className="text-fm-icon-negative h-8 w-8" />
414
- </div>
415
- <span className="text-fm-secondary text-xs">Alert</span>
416
- </div>
417
- <div className="flex w-24 flex-col items-center space-y-2">
418
- <div className="flex h-16 w-16 items-center justify-center rounded-lg bg-cyan-500/20">
419
- <EyeOpenIcon className="text-fm-icon-info h-8 w-8" />
420
- </div>
421
- <span className="text-fm-secondary text-xs">View</span>
422
- </div>
168
+ <Marquee duration="35s" pauseOnHover>
169
+ <TokenChip label="Electronic" surface="secondary" />
170
+ <TokenChip label="Hip-Hop" surface="secondary" />
171
+ <TokenChip label="Jazz" surface="secondary" />
172
+ <TokenChip label="Ambient" surface="secondary" />
173
+ <TokenChip label="R&B" surface="secondary" />
174
+ <TokenChip label="Indie" surface="secondary" />
423
175
  </Marquee>
176
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
177
+ Hover to pause
178
+ </p>
424
179
  </div>
425
180
 
426
- {/* Reverse Direction */}
427
- <div className="space-y-4">
428
- <h4 className="text-fm-secondary text-center text-sm font-medium">
181
+ {/* Reverse direction */}
182
+ <div className="space-y-3">
183
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
429
184
  Reverse Direction
430
185
  </h4>
431
- <Marquee reverse pauseOnHover duration="25s">
432
- <div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-center space-x-3 rounded-lg border px-4 py-2">
433
- <PlusIcon className="text-fm-icon-positive h-5 w-5" />
434
- <span className="text-fm-primary text-sm">Add New</span>
435
- </div>
436
- <div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-center space-x-3 rounded-lg border px-4 py-2">
437
- <TrashIcon className="text-fm-icon-negative h-5 w-5" />
438
- <span className="text-fm-primary text-sm">Delete</span>
439
- </div>
440
- <div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-center space-x-3 rounded-lg border px-4 py-2">
441
- <EditBigIcon className="text-fm-icon-info h-5 w-5" />
442
- <span className="text-fm-primary text-sm">Edit</span>
443
- </div>
444
- <div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-center space-x-3 rounded-lg border px-4 py-2">
445
- <EyeOpenIcon className="text-fm-icon-brand-secondary h-5 w-5" />
446
- <span className="text-fm-primary text-sm">Preview</span>
447
- </div>
186
+ <Marquee duration="35s" reverse pauseOnHover>
187
+ <TokenChip label="Electronic" surface="info-sec" />
188
+ <TokenChip label="Hip-Hop" surface="info-sec" />
189
+ <TokenChip label="Jazz" surface="info-sec" />
190
+ <TokenChip label="Ambient" surface="info-sec" />
191
+ <TokenChip label="R&B" surface="info-sec" />
192
+ <TokenChip label="Indie" surface="info-sec" />
448
193
  </Marquee>
194
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
195
+ Scrolls right-to-left in reverse
196
+ </p>
449
197
  </div>
450
- </div>
451
- ),
452
- parameters: {
453
- docs: {
454
- description: {
455
- story:
456
- "Icon showcase with feature icons and action buttons in normal and reverse directions.",
457
- },
458
- },
459
- },
460
- }
461
198
 
462
- // 6. Vertical Marquee
463
- export const VerticalMarquee: Story = {
464
- render: () => (
465
- <div className="flex justify-center space-x-8">
466
- {/* Social Media Feed */}
467
- <div className="space-y-4">
468
- <h4 className="text-fm-secondary text-center text-sm font-medium">
469
- Social Feed
199
+ {/* Pause on hover — compare */}
200
+ <div className="space-y-3">
201
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
202
+ pauseOnHover: off vs. on
470
203
  </h4>
471
- <div className="h-96 w-80">
472
- <Marquee vertical pauseOnHover duration="30s" className="h-full">
473
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary rounded-lg border p-4 transition-colors">
474
- <div className="flex items-start space-x-3">
475
- <div className="flex h-10 w-10 items-center justify-center rounded-full bg-gradient-to-br from-blue-500 to-purple-600">
476
- <span className="text-fm-primary text-sm font-semibold">
477
- @A
478
- </span>
479
- </div>
480
- <div className="space-y-1">
481
- <div className="text-fm-primary text-sm font-medium">
482
- @alice_dev
483
- </div>
484
- <p className="text-fm-secondary text-sm">
485
- Just shipped a new feature! The team's hard work really paid
486
- off. 🚀
487
- </p>
488
- <div className="text-fm-tertiary text-xs">2 minutes ago</div>
489
- </div>
490
- </div>
491
- </div>
492
-
493
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary rounded-lg border p-4 transition-colors">
494
- <div className="flex items-start space-x-3">
495
- <div className="flex h-10 w-10 items-center justify-center rounded-full bg-gradient-to-br from-green-500 to-teal-600">
496
- <span className="text-fm-primary text-sm font-semibold">
497
- @B
498
- </span>
499
- </div>
500
- <div className="space-y-1">
501
- <div className="text-fm-primary text-sm font-medium">
502
- @bob_designer
503
- </div>
504
- <p className="text-fm-secondary text-sm">
505
- Working on some exciting new designs. Can't wait to share
506
- them with everyone! ✨
507
- </p>
508
- <div className="text-fm-tertiary text-xs">5 minutes ago</div>
509
- </div>
510
- </div>
511
- </div>
512
-
513
- <div className="border-fm-divider-secondary bg-fm-surface-secondary hover:bg-fm-surface-tertiary rounded-lg border p-4 transition-colors">
514
- <div className="flex items-start space-x-3">
515
- <div className="flex h-10 w-10 items-center justify-center rounded-full bg-gradient-to-br from-orange-500 to-red-600">
516
- <span className="text-fm-primary text-sm font-semibold">
517
- @C
518
- </span>
519
- </div>
520
- <div className="space-y-1">
521
- <div className="text-fm-primary text-sm font-medium">
522
- @charlie_pm
523
- </div>
524
- <p className="text-fm-secondary text-sm">
525
- Great sprint review today! The team exceeded all
526
- expectations. 📊
527
- </p>
528
- <div className="text-fm-tertiary text-xs">8 minutes ago</div>
529
- </div>
530
- </div>
531
- </div>
204
+ <div className="space-y-2">
205
+ <Marquee duration="25s" pauseOnHover={false}>
206
+ <TokenChip label="Always moving" surface="negative-sec" />
207
+ <TokenChip label="No pause" surface="negative-sec" />
208
+ <TokenChip label="Continuous" surface="negative-sec" />
209
+ <TokenChip label="Non-stop" surface="negative-sec" />
532
210
  </Marquee>
211
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
212
+ pauseOnHover: false — never pauses
213
+ </p>
533
214
  </div>
534
- </div>
535
-
536
- {/* Notification Feed */}
537
- <div className="space-y-4">
538
- <h4 className="text-fm-secondary text-center text-sm font-medium">
539
- Notifications
540
- </h4>
541
- <div className="h-96 w-72">
542
- <Marquee
543
- vertical
544
- reverse
545
- pauseOnHover
546
- duration="25s"
547
- className="h-full"
548
- >
549
- <div className="border-fm-divider-secondary bg-fm-surface-info-sec flex items-center space-x-3 rounded-lg border p-3">
550
- <AlertIcon className="text-fm-icon-info h-5 w-5 flex-shrink-0" />
551
- <div>
552
- <div className="text-fm-primary text-sm">
553
- New message received
554
- </div>
555
- <div className="text-fm-secondary text-xs">From John Doe</div>
556
- </div>
557
- </div>
558
-
559
- <div className="border-fm-divider-positive bg-fm-surface-positive-sec flex items-center space-x-3 rounded-lg border p-3">
560
- <TickCircleIcon className="text-fm-icon-positive h-5 w-5 flex-shrink-0" />
561
- <div>
562
- <div className="text-fm-primary text-sm">Task completed</div>
563
- <div className="text-fm-secondary text-xs">
564
- Design review finished
565
- </div>
566
- </div>
567
- </div>
568
-
569
- <div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-center space-x-3 rounded-lg border p-3">
570
- <FileChartIcon className="text-fm-icon-brand-secondary h-5 w-5 flex-shrink-0" />
571
- <div>
572
- <div className="text-fm-primary text-sm">Report generated</div>
573
- <div className="text-fm-secondary text-xs">
574
- Monthly analytics ready
575
- </div>
576
- </div>
577
- </div>
578
-
579
- <div className="border-fm-divider-warning bg-fm-surface-warning-sec flex items-center space-x-3 rounded-lg border p-3">
580
- <EditBigIcon className="text-fm-icon-warning h-5 w-5 flex-shrink-0" />
581
- <div>
582
- <div className="text-fm-primary text-sm">Document updated</div>
583
- <div className="text-fm-secondary text-xs">
584
- Project specs modified
585
- </div>
586
- </div>
587
- </div>
215
+ <div className="space-y-2">
216
+ <Marquee duration="25s" pauseOnHover>
217
+ <TokenChip label="Hover me" surface="positive-sec" />
218
+ <TokenChip label="Pauses here" surface="positive-sec" />
219
+ <TokenChip label="Mouse over" surface="positive-sec" />
220
+ <TokenChip label="Try it" surface="positive-sec" />
588
221
  </Marquee>
222
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
223
+ pauseOnHover: true — pauses on hover
224
+ </p>
589
225
  </div>
590
226
  </div>
591
- </div>
592
- ),
593
- parameters: {
594
- docs: {
595
- description: {
596
- story:
597
- "Vertical marquees showing social media feeds and notifications with different directions.",
598
- },
599
- },
600
- },
601
- }
602
-
603
- // 7. Speed Variations
604
- export const SpeedVariations: Story = {
605
- render: () => (
606
- <div className="w-full max-w-4xl space-y-8">
607
- <h3 className="text-fm-primary text-center text-lg font-medium">
608
- Speed Variations
609
- </h3>
610
227
 
611
- <div className="space-y-6">
612
- {/* Slow */}
228
+ {/* Speed variations */}
229
+ <div className="space-y-3">
230
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
231
+ Speed Variations
232
+ </h4>
613
233
  <div className="space-y-2">
614
- <h4 className="text-fm-secondary text-sm font-medium">
615
- Slow Speed (60s)
616
- </h4>
617
234
  <Marquee duration="60s" pauseOnHover>
618
- <div className="rounded-lg bg-blue-500/20 px-6 py-3 text-blue-300">
619
- Slow marquee content
620
- </div>
621
- <div className="rounded-lg bg-green-500/20 px-6 py-3 text-green-300">
622
- Takes 60 seconds
623
- </div>
624
- <div className="rounded-lg bg-purple-500/20 px-6 py-3 text-purple-300">
625
- To complete cycle
626
- </div>
627
- <div className="rounded-lg bg-orange-500/20 px-6 py-3 text-orange-300">
628
- Very relaxed pace
629
- </div>
630
- </Marquee>
631
- </div>
632
-
633
- {/* Normal */}
634
- <div className="space-y-2">
635
- <h4 className="text-fm-secondary text-sm font-medium">
636
- Normal Speed (40s - Default)
637
- </h4>
638
- <Marquee pauseOnHover>
639
- <div className="rounded-lg bg-blue-500/20 px-6 py-3 text-blue-300">
640
- Normal speed content
641
- </div>
642
- <div className="rounded-lg bg-green-500/20 px-6 py-3 text-green-300">
643
- Standard 40 seconds
644
- </div>
645
- <div className="rounded-lg bg-purple-500/20 px-6 py-3 text-purple-300">
646
- Balanced timing
647
- </div>
648
- <div className="rounded-lg bg-orange-500/20 px-6 py-3 text-orange-300">
649
- Good for most cases
650
- </div>
235
+ <TokenChip label="Slow 60s" surface="secondary" />
236
+ <TokenChip label="Relaxed pace" surface="secondary" />
237
+ <TokenChip label="Ambient feel" surface="secondary" />
238
+ <TokenChip label="Low energy" surface="secondary" />
651
239
  </Marquee>
240
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
241
+ 60s — slow
242
+ </p>
652
243
  </div>
653
-
654
- {/* Fast */}
655
244
  <div className="space-y-2">
656
- <h4 className="text-fm-secondary text-sm font-medium">
657
- Fast Speed (20s)
658
- </h4>
659
- <Marquee duration="20s" pauseOnHover>
660
- <div className="rounded-lg bg-blue-500/20 px-6 py-3 text-blue-300">
661
- Fast moving content
662
- </div>
663
- <div className="rounded-lg bg-green-500/20 px-6 py-3 text-green-300">
664
- Only 20 seconds
665
- </div>
666
- <div className="rounded-lg bg-purple-500/20 px-6 py-3 text-purple-300">
667
- Quick cycling
668
- </div>
669
- <div className="rounded-lg bg-orange-500/20 px-6 py-3 text-orange-300">
670
- High energy
671
- </div>
245
+ <Marquee duration="30s" pauseOnHover>
246
+ <TokenChip label="Normal — 30s" surface="secondary" />
247
+ <TokenChip label="Default feel" surface="secondary" />
248
+ <TokenChip label="Balanced" surface="secondary" />
249
+ <TokenChip label="Versatile" surface="secondary" />
672
250
  </Marquee>
251
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
252
+ 30s — normal
253
+ </p>
673
254
  </div>
674
-
675
- {/* Very Fast */}
676
255
  <div className="space-y-2">
677
- <h4 className="text-fm-secondary text-sm font-medium">
678
- Very Fast Speed (10s)
679
- </h4>
680
- <Marquee duration="10s" pauseOnHover>
681
- <div className="rounded-lg bg-blue-500/20 px-6 py-3 text-blue-300">
682
- Lightning fast
683
- </div>
684
- <div className="rounded-lg bg-green-500/20 px-6 py-3 text-green-300">
685
- Just 10 seconds
686
- </div>
687
- <div className="rounded-lg bg-purple-500/20 px-6 py-3 text-purple-300">
688
- Rapid movement
689
- </div>
690
- <div className="rounded-lg bg-orange-500/20 px-6 py-3 text-orange-300">
691
- Dynamic feel
692
- </div>
256
+ <Marquee duration="12s" pauseOnHover>
257
+ <TokenChip label="Fast 12s" surface="warning-sec" />
258
+ <TokenChip label="High energy" surface="warning-sec" />
259
+ <TokenChip label="Urgent" surface="warning-sec" />
260
+ <TokenChip label="Dynamic" surface="warning-sec" />
693
261
  </Marquee>
262
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
263
+ 12s — fast
264
+ </p>
694
265
  </div>
695
266
  </div>
696
267
 
697
- <div className="text-fm-secondary text-center text-xs">
698
- <p>
699
- All examples have pauseOnHover enabled - hover to pause any marquee
268
+ {/* Vertical */}
269
+ <div className="space-y-3">
270
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
271
+ Vertical Orientation
272
+ </h4>
273
+ <div className="flex justify-center">
274
+ <div className="h-48 w-56 overflow-hidden">
275
+ <Marquee vertical duration="18s" pauseOnHover className="h-full">
276
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary my-1 flex items-center gap-2 rounded-lg border px-3 py-2">
277
+ <MusicalNoteIcon className="text-fm-secondary h-4 w-4 shrink-0" />
278
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
279
+ Bicep — Glue
280
+ </span>
281
+ </div>
282
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary my-1 flex items-center gap-2 rounded-lg border px-3 py-2">
283
+ <MusicalNoteIcon className="text-fm-secondary h-4 w-4 shrink-0" />
284
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
285
+ Four Tet — Baby
286
+ </span>
287
+ </div>
288
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary my-1 flex items-center gap-2 rounded-lg border px-3 py-2">
289
+ <MusicalNoteIcon className="text-fm-secondary h-4 w-4 shrink-0" />
290
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
291
+ Floating Points
292
+ </span>
293
+ </div>
294
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary my-1 flex items-center gap-2 rounded-lg border px-3 py-2">
295
+ <MusicalNoteIcon className="text-fm-secondary h-4 w-4 shrink-0" />
296
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
297
+ Jon Hopkins
298
+ </span>
299
+ </div>
300
+ </Marquee>
301
+ </div>
302
+ </div>
303
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm text-center">
304
+ vertical: true — scrolls top to bottom
700
305
  </p>
701
306
  </div>
702
307
  </div>
@@ -705,132 +310,171 @@ export const SpeedVariations: Story = {
705
310
  docs: {
706
311
  description: {
707
312
  story:
708
- "Different animation speeds from very slow (60s) to very fast (10s) showing the flexibility of the marquee component.",
313
+ "Comparison of all main configuration axes: horizontal vs. vertical orientation, normal vs. reverse direction, pauseOnHover toggle, and speed variations from 12s (fast) to 60s (slow).",
709
314
  },
710
315
  },
711
316
  },
712
317
  }
713
318
 
714
- // 8. Interactive Controls
715
- export const InteractiveControls: Story = {
716
- render: () => {
717
- const [speed, setSpeed] = React.useState(40)
718
- const [isPaused, setIsPaused] = React.useState(false)
719
- const [isReverse, setIsReverse] = React.useState(false)
720
- const [isVertical, setIsVertical] = React.useState(false)
721
-
722
- return (
723
- <div className="w-full max-w-4xl space-y-6">
724
- <h3 className="text-fm-primary text-center text-lg font-medium">
725
- Interactive Controls
726
- </h3>
727
-
728
- {/* Controls */}
729
- <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
730
- <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
731
- <div className="space-y-2">
732
- <label className="text-fm-secondary text-sm">
733
- Speed (seconds)
734
- </label>
735
- <input
736
- type="range"
737
- min="5"
738
- max="60"
739
- value={speed}
740
- onChange={(e) => setSpeed(Number(e.target.value))}
741
- className="w-full"
742
- />
743
- <div className="text-fm-secondary text-center text-xs">
744
- {speed}s
745
- </div>
746
- </div>
319
+ // ─── 2. UseCases ──────────────────────────────────────────────────────────────
747
320
 
748
- <div className="space-y-2">
749
- <label className="text-fm-secondary text-sm">Direction</label>
750
- <button
751
- onClick={() => setIsReverse(!isReverse)}
752
- className={`w-full rounded px-3 py-2 text-sm transition-colors ${
753
- isReverse
754
- ? "bg-fm-surface-info text-fm-surface-primary"
755
- : "bg-fm-surface-secondary text-fm-secondary hover:bg-fm-surface-tertiary"
756
- }`}
757
- >
758
- {isReverse ? "Reverse" : "Normal"}
759
- </button>
760
- </div>
761
-
762
- <div className="space-y-2">
763
- <label className="text-fm-secondary text-sm">Orientation</label>
764
- <button
765
- onClick={() => setIsVertical(!isVertical)}
766
- className={`w-full rounded px-3 py-2 text-sm transition-colors ${
767
- isVertical
768
- ? "bg-fm-surface-positive text-fm-surface-primary"
769
- : "bg-fm-surface-secondary text-fm-secondary hover:bg-fm-surface-tertiary"
770
- }`}
771
- >
772
- {isVertical ? "Vertical" : "Horizontal"}
773
- </button>
774
- </div>
321
+ export const UseCases: Story = {
322
+ render: () => (
323
+ <div className="mx-auto max-w-3xl space-y-8 p-8">
324
+ {/* Artist avatar / label carousel */}
325
+ <div className="space-y-4">
326
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
327
+ Artist Carousel
328
+ </h4>
329
+ <Marquee duration="40s" pauseOnHover gutter="1rem">
330
+ <ArtistCard initials="BC" name="Bicep" />
331
+ <ArtistCard initials="FT" name="Four Tet" />
332
+ <ArtistCard initials="FP" name="Floating Pts" />
333
+ <ArtistCard initials="JH" name="Jon Hopkins" />
334
+ <ArtistCard initials="RP" name="Röyksopp" />
335
+ <ArtistCard initials="AP" name="Aphex Twin" />
336
+ <ArtistCard initials="BB" name="Bonobo" />
337
+ <ArtistCard initials="OV" name="Overmono" />
338
+ </Marquee>
339
+ </div>
775
340
 
776
- <div className="space-y-2">
777
- <label className="text-fm-secondary text-sm">Animation</label>
778
- <button
779
- onClick={() => setIsPaused(!isPaused)}
780
- className={`w-full rounded px-3 py-2 text-sm transition-colors ${
781
- isPaused
782
- ? "bg-fm-surface-negative text-fm-surface-primary"
783
- : "bg-fm-surface-secondary text-fm-secondary hover:bg-fm-surface-tertiary"
784
- }`}
785
- >
786
- {isPaused ? "Paused" : "Playing"}
787
- </button>
788
- </div>
341
+ {/* News ticker / announcement strip */}
342
+ <div className="space-y-4">
343
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
344
+ Announcements Ticker
345
+ </h4>
346
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary flex items-center gap-3 overflow-hidden rounded-lg border px-4 py-2">
347
+ <div className="bg-fm-surface-negative-sec text-fm-primary text-fm-xs leading-fm-xs shrink-0 rounded px-2 py-0.5 font-semibold tracking-widest uppercase">
348
+ Live
789
349
  </div>
350
+ <Marquee duration="28s" pauseOnHover className="flex-1">
351
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm px-6 whitespace-nowrap">
352
+ Bicep announce headline set at Primavera Sound 2026
353
+ </span>
354
+ <span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm px-6 whitespace-nowrap">
355
+ ·
356
+ </span>
357
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm px-6 whitespace-nowrap">
358
+ Four Tet drops surprise EP on Bandcamp — download now
359
+ </span>
360
+ <span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm px-6 whitespace-nowrap">
361
+ ·
362
+ </span>
363
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm px-6 whitespace-nowrap">
364
+ PocketFM 3.0 launch: redesigned player and social listening
365
+ </span>
366
+ <span className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm px-6 whitespace-nowrap">
367
+ ·
368
+ </span>
369
+ <span className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm px-6 whitespace-nowrap">
370
+ New editorial playlists updated every Friday
371
+ </span>
372
+ </Marquee>
790
373
  </div>
374
+ </div>
791
375
 
792
- {/* Live Marquee */}
793
- <div className={`${isVertical ? "h-64" : ""}`}>
794
- <Marquee
795
- vertical={isVertical}
796
- reverse={isReverse}
797
- pauseOnHover
798
- duration={`${speed}s`}
799
- className={`${isPaused ? "[animation-play-state:paused]" : ""} ${isVertical ? "h-full" : ""}`}
800
- >
801
- <div className="flex min-w-[120px] flex-col items-center space-y-2 rounded-lg bg-blue-500/20 p-4 text-blue-300">
802
- <AlertIcon className="h-8 w-8" />
803
- <span className="text-sm font-medium">Alert</span>
804
- </div>
805
- <div className="flex min-w-[120px] flex-col items-center space-y-2 rounded-lg bg-green-500/20 p-4 text-green-300">
806
- <TickCircleIcon className="h-8 w-8" />
807
- <span className="text-sm font-medium">Success</span>
808
- </div>
809
- <div className="flex min-w-[120px] flex-col items-center space-y-2 rounded-lg bg-purple-500/20 p-4 text-purple-300">
810
- <EditBigIcon className="h-8 w-8" />
811
- <span className="text-sm font-medium">Edit</span>
812
- </div>
813
- <div className="flex min-w-[120px] flex-col items-center space-y-2 rounded-lg bg-orange-500/20 p-4 text-orange-300">
814
- <SearchIcon className="h-8 w-8" />
815
- <span className="text-sm font-medium">Search</span>
816
- </div>
376
+ {/* Song queue strip */}
377
+ <div className="space-y-4">
378
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
379
+ Now Playing Queue Strip
380
+ </h4>
381
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-xl border p-4">
382
+ <p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm mb-3 tracking-widest uppercase">
383
+ Up next
384
+ </p>
385
+ <Marquee duration="50s" pauseOnHover gutter="0.75rem">
386
+ {[
387
+ { track: "Glue", artist: "Bicep", active: true },
388
+ { track: "Baby", artist: "Four Tet", active: false },
389
+ { track: "Nacht 001-iv", artist: "Floating Pts", active: false },
390
+ { track: "Emerald Rush", artist: "Jon Hopkins", active: false },
391
+ { track: "Fridge Hum", artist: "Bonobo", active: false },
392
+ { track: "Kerning", artist: "Overmono", active: false },
393
+ { track: "Monument", artist: "Röyksopp", active: false },
394
+ { track: "Alberto Balsam", artist: "Aphex Twin", active: false },
395
+ ].map((item) => (
396
+ <div
397
+ key={item.track}
398
+ className={[
399
+ "flex shrink-0 flex-col gap-0.5 rounded-lg border px-3 py-2 transition-colors",
400
+ item.active
401
+ ? "border-fm-divider-brand-secondary bg-fm-surface-secondary"
402
+ : "border-fm-divider-secondary bg-fm-surface-secondary",
403
+ ].join(" ")}
404
+ >
405
+ <div className="flex items-center gap-2">
406
+ {item.active && (
407
+ <TickCircleIcon className="text-fm-positive h-3 w-3 shrink-0" />
408
+ )}
409
+ <p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm font-medium whitespace-nowrap">
410
+ {item.track}
411
+ </p>
412
+ </div>
413
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm whitespace-nowrap">
414
+ {item.artist}
415
+ </p>
416
+ </div>
417
+ ))}
817
418
  </Marquee>
818
419
  </div>
420
+ </div>
819
421
 
820
- <div className="text-fm-secondary text-center text-xs">
821
- <p>
822
- Adjust the controls above to see real-time changes to the marquee
823
- behavior
824
- </p>
422
+ {/* Dual-row reverse for status badges */}
423
+ <div className="space-y-4">
424
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md font-medium">
425
+ Genre Tag Cloud (dual-row)
426
+ </h4>
427
+ <div className="space-y-2 overflow-hidden">
428
+ <Marquee duration="45s" pauseOnHover>
429
+ {[
430
+ "Techno",
431
+ "House",
432
+ "Drum & Bass",
433
+ "Jungle",
434
+ "UK Garage",
435
+ "Deep House",
436
+ "Trance",
437
+ "Breaks",
438
+ "Electro",
439
+ ].map((g) => (
440
+ <TokenChip key={g} label={g} surface="secondary" />
441
+ ))}
442
+ </Marquee>
443
+ <Marquee duration="38s" reverse pauseOnHover>
444
+ {[
445
+ "Neo-Soul",
446
+ "Lo-Fi",
447
+ "Jazz Fusion",
448
+ "Afrobeat",
449
+ "Latin",
450
+ "Bossa Nova",
451
+ "Downtempo",
452
+ "Trip-Hop",
453
+ "Chillout",
454
+ ].map((g) => (
455
+ <TokenChip key={g} label={g} surface="info-sec" />
456
+ ))}
457
+ </Marquee>
825
458
  </div>
826
459
  </div>
827
- )
828
- },
460
+
461
+ {/* Info box */}
462
+ <div className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-4">
463
+ <p className="text-fm-secondary font-fm-text text-fm-md leading-fm-xl">
464
+ All marquee examples above use only design system tokens for color,
465
+ spacing, and typography — no hardcoded values. Reduced-motion users
466
+ will see a paused state automatically, as the component respects
467
+ <code className="text-fm-primary mx-1">prefers-reduced-motion</code>.
468
+ </p>
469
+ </div>
470
+ </div>
471
+ ),
829
472
  parameters: {
473
+ layout: "fullscreen",
830
474
  docs: {
831
475
  description: {
832
476
  story:
833
- "Interactive controls allowing real-time adjustment of marquee properties including speed, direction, orientation, and play state.",
477
+ "Real product-shaped examples: an artist avatar carousel, a live announcements ticker, a now-playing queue strip, and a dual-row genre tag cloud. All using design system tokens.",
834
478
  },
835
479
  },
836
480
  },