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,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
  },