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,6 +1,8 @@
1
1
  import React from "react"
2
2
  import type { Meta, StoryObj } from "@storybook/react-vite"
3
3
 
4
+ import { AuralComponentDocsPage } from "src/ui/story-spec/components/component-story-docs-page"
5
+
4
6
  import { ScrollArea, ScrollBar } from "."
5
7
 
6
8
  const meta: Meta<typeof ScrollArea> = {
@@ -8,69 +10,29 @@ const meta: Meta<typeof ScrollArea> = {
8
10
  component: ScrollArea,
9
11
  parameters: {
10
12
  layout: "centered",
11
- backgrounds: {
12
- default: "dark",
13
- values: [
14
- { name: "dark", value: "#0a0a0a" },
15
- { name: "light", value: "#ffffff" },
16
- ],
17
- },
18
13
  docs: {
19
14
  description: {
20
- component: `
21
- # ScrollArea Component
22
-
23
- A custom scrollable area component built on Radix UI primitives with styled scrollbars and smooth scrolling behavior.
24
-
25
- ## Features
26
-
27
- - **Custom Scrollbars**: Styled scrollbars that match your design system
28
- - **Smooth Scrolling**: Optimized scrolling performance with native feel
29
- - **Keyboard Navigation**: Full keyboard support for accessibility
30
- - **Focus Management**: Proper focus ring and outline handling
31
- - **Cross-browser**: Consistent appearance across different browsers
32
- - **Touch Support**: Touch-friendly scrolling on mobile devices
33
- - **Orientation Support**: Both vertical and horizontal scrolling
34
-
35
- ## Component Structure
36
-
37
- - **ScrollArea**: Root container that manages the scrollable region
38
- - **ScrollBar**: Custom scrollbar component with thumb indicator
39
- - **Viewport**: The actual scrollable content area
40
- - **Corner**: Corner element for when both scrollbars are present
41
-
42
- ## Usage Examples
43
-
44
- ### Basic Vertical Scroll
45
- \`\`\`tsx
46
- <ScrollArea className="h-72 w-48">
47
- <div className="p-4">
48
- {/* Long content that needs scrolling */}
49
- </div>
50
- </ScrollArea>
51
- \`\`\`
52
-
53
- ### Horizontal Scroll
54
- \`\`\`tsx
55
- <ScrollArea className="w-72 whitespace-nowrap">
56
- <div className="flex w-max gap-4 p-4">
57
- {/* Wide content that needs horizontal scrolling */}
58
- </div>
59
- <ScrollBar orientation="horizontal" />
60
- </ScrollArea>
61
- \`\`\`
62
-
63
- ### Both Directions
64
- \`\`\`tsx
65
- <ScrollArea className="h-72 w-72">
66
- <div className="w-[800px] h-[600px] p-4">
67
- {/* Content that overflows both directions */}
68
- </div>
69
- <ScrollBar orientation="horizontal" />
70
- </ScrollArea>
71
- \`\`\`
72
- `,
15
+ component:
16
+ "A custom scrollable container built on Radix UI primitives. Provides styled scrollbars and smooth scrolling in vertical, horizontal, or both directions. Ideal for constraining long lists, message threads, track queues, and other overflow content within a fixed viewport.",
73
17
  },
18
+ page: () => (
19
+ <AuralComponentDocsPage
20
+ features={[
21
+ {
22
+ title: "Styled Scrollbars",
23
+ description: "Custom Radix scrollbar",
24
+ },
25
+ {
26
+ title: "Both Directions",
27
+ description: "Vertical and horizontal",
28
+ },
29
+ {
30
+ title: "Fixed Viewport",
31
+ description: "Overflow content area",
32
+ },
33
+ ]}
34
+ />
35
+ ),
74
36
  },
75
37
  },
76
38
  tags: ["autodocs"],
@@ -79,459 +41,146 @@ A custom scrollable area component built on Radix UI primitives with styled scro
79
41
  export default meta
80
42
  type Story = StoryObj<typeof ScrollArea>
81
43
 
82
- // 1. Basic Vertical Scroll
83
- export const BasicVerticalScroll: Story = {
44
+ // ─── 1. Configurations ────────────────────────────────────────────────────────
45
+
46
+ export const Configurations: Story = {
84
47
  render: () => (
85
48
  <div className="space-y-8">
86
- <div className="text-center">
87
- <h3 className="text-fm-primary mb-2 font-medium">
88
- Basic Vertical Scroll
89
- </h3>
90
- <p className="text-fm-secondary text-sm">
91
- Standard vertical scrolling with custom styled scrollbar
92
- </p>
93
- </div>
94
-
95
- <div className="flex flex-wrap justify-center gap-8">
96
- {/* Text Content */}
97
- <div className="space-y-2">
98
- <h4 className="text-fm-secondary text-sm font-medium">
99
- Text Content
100
- </h4>
101
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-72 w-80 rounded-lg border">
102
- <div className="p-4">
103
- <h4 className="text-fm-primary mb-4 text-sm leading-none font-medium">
104
- The Art of Web Development
105
- </h4>
106
- <div className="text-fm-secondary space-y-4 text-sm">
107
- <p>
108
- Web development is an ever-evolving field that combines
109
- creativity with technical expertise. Modern developers must
110
- master a wide array of technologies, from frontend frameworks
111
- like React and Vue to backend systems built with Node.js,
112
- Python, or Go.
113
- </p>
114
- <p>
115
- The importance of user experience cannot be overstated. Every
116
- line of code we write should be with the end user in mind.
117
- Performance, accessibility, and intuitive design are not just
118
- buzzwords—they are fundamental requirements for successful web
119
- applications.
120
- </p>
121
- <p>
122
- Component-driven development has revolutionized how we build
123
- user interfaces. By creating reusable, modular components, we
124
- can maintain consistency across large applications while
125
- reducing development time and improving code quality.
126
- </p>
127
- <p>
128
- CSS has grown tremendously powerful with features like Grid,
129
- Flexbox, and custom properties. Combined with modern tools
130
- like Tailwind CSS, we can create beautiful, responsive designs
131
- with unprecedented efficiency.
132
- </p>
133
- <p>
134
- The future of web development looks bright with emerging
135
- technologies like WebAssembly, Web Components, and progressive
136
- enhancement techniques that make the web more capable and
137
- accessible to everyone.
138
- </p>
139
- <p>
140
- Testing and quality assurance remain critical aspects of
141
- professional development. Unit tests, integration tests, and
142
- end-to-end testing help ensure our applications work reliably
143
- across different environments and use cases.
144
- </p>
145
- </div>
146
- </div>
147
- </ScrollArea>
148
- </div>
149
-
150
- {/* List Content */}
151
- <div className="space-y-2">
152
- <h4 className="text-fm-secondary text-sm font-medium">
153
- List Content
154
- </h4>
155
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-72 w-80 rounded-lg border">
156
- <div className="p-4">
157
- <h4 className="text-fm-primary mb-4 text-sm leading-none font-medium">
158
- Popular Programming Languages
159
- </h4>
160
- <div className="space-y-2">
161
- {[
162
- {
163
- name: "JavaScript",
164
- desc: "Dynamic web programming language",
165
- },
166
- { name: "TypeScript", desc: "Typed superset of JavaScript" },
167
- { name: "Python", desc: "Versatile and beginner-friendly" },
168
- { name: "Java", desc: "Object-oriented enterprise language" },
169
- {
170
- name: "C#",
171
- desc: "Microsoft's modern programming language",
172
- },
173
- { name: "Go", desc: "Fast and efficient systems language" },
174
- { name: "Rust", desc: "Memory-safe systems programming" },
175
- {
176
- name: "Swift",
177
- desc: "Apple's modern programming language",
178
- },
179
- { name: "Kotlin", desc: "Modern alternative to Java" },
180
- { name: "PHP", desc: "Server-side web development" },
181
- { name: "Ruby", desc: "Elegant and expressive language" },
182
- {
183
- name: "C++",
184
- desc: "Powerful systems programming language",
185
- },
186
- { name: "Dart", desc: "Language for Flutter development" },
187
- { name: "Scala", desc: "Functional programming on JVM" },
188
- { name: "Elixir", desc: "Concurrent and fault-tolerant" },
189
- ].map((lang, index) => (
49
+ {/* Vertical scroll */}
50
+ <div>
51
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
52
+ Vertical Scroll
53
+ </h4>
54
+ <div className="flex flex-wrap gap-6">
55
+ <div className="space-y-2 text-center">
56
+ <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-56 w-64 rounded-lg border">
57
+ <div className="space-y-2 p-4">
58
+ {Array.from({ length: 12 }, (_, i) => (
190
59
  <div
191
- key={index}
192
- className="border-fm-divider-secondary bg-fm-surface-secondary rounded-lg border p-3"
60
+ key={i}
61
+ className="border-fm-divider-secondary bg-fm-surface-primary rounded-md border px-3 py-2"
193
62
  >
194
- <div className="text-fm-primary font-medium">
195
- {lang.name}
196
- </div>
197
- <div className="text-fm-secondary text-xs">{lang.desc}</div>
63
+ <p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
64
+ Track {i + 1}
65
+ </p>
198
66
  </div>
199
67
  ))}
200
68
  </div>
201
- </div>
202
- </ScrollArea>
203
- </div>
204
- </div>
205
- </div>
206
- ),
207
- parameters: {
208
- docs: {
209
- description: {
210
- story:
211
- "Basic vertical scrolling examples with text content and list items showing custom scrollbar styling.",
212
- },
213
- },
214
- },
215
- }
216
-
217
- // 2. Horizontal Scroll
218
- export const HorizontalScroll: Story = {
219
- render: () => (
220
- <div className="space-y-8">
221
- <div className="text-center">
222
- <h3 className="text-fm-primary mb-2 font-medium">Horizontal Scroll</h3>
223
- <p className="text-fm-secondary text-sm">
224
- Horizontal scrolling with custom scrollbar orientation
225
- </p>
226
- </div>
69
+ </ScrollArea>
70
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
71
+ Fixed height (224px)
72
+ </p>
73
+ </div>
227
74
 
228
- <div className="space-y-6">
229
- {/* Image Gallery */}
230
- <div className="space-y-2">
231
- <h4 className="text-fm-secondary text-sm font-medium">
232
- Image Gallery
233
- </h4>
234
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary w-full max-w-4xl rounded-lg border whitespace-nowrap">
235
- <div className="flex w-max gap-4 p-4">
236
- {[
237
- {
238
- id: 1,
239
- color: "from-blue-500 to-purple-600",
240
- name: "Mountain Vista",
241
- },
242
- {
243
- id: 2,
244
- color: "from-green-500 to-teal-600",
245
- name: "Forest Path",
246
- },
247
- {
248
- id: 3,
249
- color: "from-orange-500 to-red-600",
250
- name: "Desert Sunset",
251
- },
252
- {
253
- id: 4,
254
- color: "from-purple-500 to-pink-600",
255
- name: "Ocean Waves",
256
- },
257
- {
258
- id: 5,
259
- color: "from-teal-500 to-cyan-600",
260
- name: "City Lights",
261
- },
262
- {
263
- id: 6,
264
- color: "from-yellow-500 to-orange-600",
265
- name: "Golden Hour",
266
- },
267
- {
268
- id: 7,
269
- color: "from-indigo-500 to-blue-600",
270
- name: "Starry Night",
271
- },
272
- {
273
- id: 8,
274
- color: "from-pink-500 to-rose-600",
275
- name: "Cherry Blossoms",
276
- },
277
- ].map((item) => (
278
- <div key={item.id} className="flex-none space-y-2">
75
+ <div className="space-y-2 text-center">
76
+ <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-40 w-64 rounded-lg border">
77
+ <div className="space-y-2 p-4">
78
+ {Array.from({ length: 10 }, (_, i) => (
279
79
  <div
280
- className={`h-32 w-48 rounded-lg bg-gradient-to-br ${item.color} flex items-center justify-center font-medium text-white`}
80
+ key={i}
81
+ className="border-fm-divider-secondary bg-fm-surface-primary rounded-md border px-3 py-2"
281
82
  >
282
- {item.name}
83
+ <p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
84
+ Playlist item {i + 1}
85
+ </p>
283
86
  </div>
284
- <p className="text-fm-secondary text-center text-xs">
285
- {item.name}
286
- </p>
287
- </div>
288
- ))}
289
- </div>
290
- <ScrollBar orientation="horizontal" />
291
- </ScrollArea>
87
+ ))}
88
+ </div>
89
+ </ScrollArea>
90
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
91
+ Compact height (160px)
92
+ </p>
93
+ </div>
292
94
  </div>
95
+ </div>
293
96
 
294
- {/* Tag List */}
295
- <div className="space-y-2">
296
- <h4 className="text-fm-secondary text-sm font-medium">
297
- Technology Tags
298
- </h4>
299
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary w-full max-w-2xl rounded-lg border whitespace-nowrap">
300
- <div className="flex w-max gap-2 p-4">
97
+ {/* Horizontal scroll */}
98
+ <div>
99
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
100
+ Horizontal Scroll
101
+ </h4>
102
+ <div className="space-y-2 text-center">
103
+ <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary w-80 rounded-lg border whitespace-nowrap">
104
+ <div className="flex w-max gap-3 p-4">
301
105
  {[
302
- "React",
303
- "Vue.js",
304
- "Angular",
305
- "Svelte",
306
- "Next.js",
307
- "Nuxt.js",
308
- "Gatsby",
309
- "TypeScript",
310
- "JavaScript",
311
- "Node.js",
312
- "Express",
313
- "Fastify",
314
- "Koa",
315
- "MongoDB",
316
- "PostgreSQL",
317
- "MySQL",
318
- "Redis",
319
- "GraphQL",
320
- "REST API",
321
- "Docker",
322
- "Kubernetes",
323
- "AWS",
324
- "Vercel",
325
- "Netlify",
326
- "Firebase",
327
- ].map((tag, index) => (
106
+ "Hip-Hop",
107
+ "R&B",
108
+ "Electronic",
109
+ "Jazz",
110
+ "Classical",
111
+ "Indie",
112
+ "Pop",
113
+ "Metal",
114
+ "Soul",
115
+ "Funk",
116
+ "Reggae",
117
+ ].map((genre) => (
328
118
  <div
329
- key={index}
330
- className="border-fm-divider-secondary bg-fm-surface-info-sec text-fm-info flex-none rounded-full border px-3 py-1 text-xs"
119
+ key={genre}
120
+ className="border-fm-divider-secondary bg-fm-surface-primary flex-none rounded-full border px-4 py-1.5"
331
121
  >
332
- {tag}
333
- </div>
334
- ))}
335
- </div>
336
- <ScrollBar orientation="horizontal" />
337
- </ScrollArea>
338
- </div>
339
-
340
- {/* Timeline */}
341
- <div className="space-y-2">
342
- <h4 className="text-fm-secondary text-sm font-medium">
343
- Project Timeline
344
- </h4>
345
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary w-full max-w-3xl rounded-lg border whitespace-nowrap">
346
- <div className="flex w-max gap-6 p-4">
347
- {[
348
- { phase: "Planning", duration: "2 weeks", status: "completed" },
349
- { phase: "Design", duration: "3 weeks", status: "completed" },
350
- {
351
- phase: "Development",
352
- duration: "8 weeks",
353
- status: "in-progress",
354
- },
355
- { phase: "Testing", duration: "2 weeks", status: "pending" },
356
- { phase: "Deployment", duration: "1 week", status: "pending" },
357
- { phase: "Launch", duration: "1 week", status: "pending" },
358
- ].map((item, index) => (
359
- <div key={index} className="flex-none space-y-2">
360
- <div className="border-fm-divider-secondary bg-fm-surface-secondary w-32 rounded-lg border p-3">
361
- <div
362
- className={`mb-2 h-2 w-2 rounded-full ${
363
- item.status === "completed"
364
- ? "bg-fm-surface-positive"
365
- : item.status === "in-progress"
366
- ? "bg-fm-surface-warning"
367
- : "bg-fm-surface-tertiary"
368
- }`}
369
- ></div>
370
- <div className="text-fm-primary text-sm font-medium">
371
- {item.phase}
372
- </div>
373
- <div className="text-fm-secondary text-xs">
374
- {item.duration}
375
- </div>
376
- </div>
122
+ <p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
123
+ {genre}
124
+ </p>
377
125
  </div>
378
126
  ))}
379
127
  </div>
380
128
  <ScrollBar orientation="horizontal" />
381
129
  </ScrollArea>
130
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
131
+ Genre tag strip (fixed width 320px)
132
+ </p>
382
133
  </div>
383
134
  </div>
384
- </div>
385
- ),
386
- parameters: {
387
- docs: {
388
- description: {
389
- story:
390
- "Horizontal scrolling examples including image galleries, tag lists, and timeline components with horizontal scrollbars.",
391
- },
392
- },
393
- },
394
- }
395
-
396
- // 3. Both Directions
397
- export const BothDirectionsScroll: Story = {
398
- render: () => (
399
- <div className="space-y-8">
400
- <div className="text-center">
401
- <h3 className="text-fm-primary mb-2 font-medium">
402
- Two-Dimensional Scroll
403
- </h3>
404
- <p className="text-fm-secondary text-sm">
405
- Content that scrolls both horizontally and vertically
406
- </p>
407
- </div>
408
135
 
409
- <div className="space-y-6">
410
- {/* Data Table */}
411
- <div className="space-y-2">
412
- <h4 className="text-fm-secondary text-sm font-medium">Data Table</h4>
413
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-80 w-full max-w-4xl rounded-lg border">
414
- <div className="w-[1200px] p-4">
415
- <table className="w-full text-sm">
416
- <thead>
417
- <tr className="border-fm-divider-secondary border-b">
418
- <th className="text-fm-primary p-2 text-left">ID</th>
419
- <th className="text-fm-primary p-2 text-left">Name</th>
420
- <th className="text-fm-primary p-2 text-left">Email</th>
421
- <th className="text-fm-primary p-2 text-left">Role</th>
422
- <th className="text-fm-primary p-2 text-left">
423
- Department
424
- </th>
425
- <th className="text-fm-primary p-2 text-left">Location</th>
426
- <th className="text-fm-primary p-2 text-left">
427
- Start Date
428
- </th>
429
- <th className="text-fm-primary p-2 text-left">Salary</th>
430
- <th className="text-fm-primary p-2 text-left">Status</th>
431
- </tr>
432
- </thead>
433
- <tbody>
434
- {Array.from({ length: 50 }, (_, i) => (
435
- <tr
436
- key={i}
437
- className="border-fm-divider-secondary border-b"
136
+ {/* Both directions */}
137
+ <div>
138
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
139
+ Both Directions
140
+ </h4>
141
+ <div className="space-y-2 text-center">
142
+ <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-48 w-80 rounded-lg border">
143
+ <div className="w-140 p-4">
144
+ <div className="mb-3 grid grid-cols-5 gap-3">
145
+ {["Title", "Artist", "Album", "Duration", "Plays"].map(
146
+ (col) => (
147
+ <p
148
+ key={col}
149
+ className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm font-medium"
438
150
  >
439
- <td className="text-fm-secondary p-2">{1000 + i}</td>
440
- <td className="text-fm-secondary p-2">
441
- Employee {i + 1}
442
- </td>
443
- <td className="text-fm-secondary p-2">
444
- employee{i + 1}@company.com
445
- </td>
446
- <td className="text-fm-secondary p-2">
447
- {["Developer", "Designer", "Manager", "Analyst"][i % 4]}
448
- </td>
449
- <td className="text-fm-secondary p-2">
450
- {["Engineering", "Design", "Marketing", "Sales"][i % 4]}
451
- </td>
452
- <td className="text-fm-secondary p-2">
453
- {
454
- ["San Francisco", "New York", "London", "Tokyo"][
455
- i % 4
456
- ]
457
- }
458
- </td>
459
- <td className="text-fm-secondary p-2">
460
- {new Date(
461
- 2020 + (i % 4),
462
- i % 12,
463
- (i % 28) + 1
464
- ).toLocaleDateString()}
465
- </td>
466
- <td className="text-fm-secondary p-2">
467
- ${(50000 + i * 1000).toLocaleString()}
468
- </td>
469
- <td className="p-2">
470
- <span
471
- className={`rounded-full px-2 py-1 text-xs ${
472
- i % 3 === 0
473
- ? "bg-fm-surface-positive-sec text-fm-positive"
474
- : i % 3 === 1
475
- ? "bg-fm-surface-warning-sec text-fm-warning"
476
- : "bg-fm-surface-secondary text-fm-icon-negative"
477
- }`}
478
- >
479
- {i % 3 === 0
480
- ? "Active"
481
- : i % 3 === 1
482
- ? "Away"
483
- : "Inactive"}
484
- </span>
485
- </td>
486
- </tr>
487
- ))}
488
- </tbody>
489
- </table>
490
- </div>
491
- <ScrollBar orientation="horizontal" />
492
- </ScrollArea>
493
- </div>
494
-
495
- {/* Large Canvas */}
496
- <div className="space-y-2">
497
- <h4 className="text-fm-secondary text-sm font-medium">
498
- Design Canvas
499
- </h4>
500
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-96 w-full max-w-2xl rounded-lg border">
501
- <div className="h-[1200px] w-[1500px] bg-gradient-to-br from-blue-900/20 to-purple-900/20 p-4">
502
- <div className="relative h-full w-full">
503
- {/* Grid Pattern */}
151
+ {col}
152
+ </p>
153
+ )
154
+ )}
155
+ </div>
156
+ {Array.from({ length: 10 }, (_, i) => (
504
157
  <div
505
- className="absolute inset-0 opacity-20"
506
- style={{
507
- backgroundImage: `
508
- linear-gradient(rgba(255,255,255,0.1) 1px, transparent 1px),
509
- linear-gradient(90deg, rgba(255,255,255,0.1) 1px, transparent 1px)
510
- `,
511
- backgroundSize: "50px 50px",
512
- }}
513
- />
514
-
515
- {/* Design Elements */}
516
- <div className="text-fm-primary absolute top-20 left-20 flex h-32 w-48 items-center justify-center rounded-lg border border-blue-400/50 bg-blue-500/30">
517
- Header Component
518
- </div>
519
- <div className="text-fm-primary absolute top-60 left-20 flex h-40 w-64 items-center justify-center rounded-lg border border-green-400/50 bg-green-500/30">
520
- Navigation Menu
521
- </div>
522
- <div className="text-fm-primary absolute top-20 left-80 flex h-96 w-80 items-center justify-center rounded-lg border border-purple-400/50 bg-purple-500/30">
523
- Main Content Area
524
- </div>
525
- <div className="text-fm-primary absolute top-20 right-20 flex h-64 w-56 items-center justify-center rounded-lg border border-orange-400/50 bg-orange-500/30">
526
- Sidebar Widget
527
- </div>
528
- <div className="border-fm-divider-secondary bg-fm-surface-secondary text-fm-primary absolute bottom-20 left-20 flex h-24 w-[calc(100%-160px)] items-center justify-center rounded-lg border">
529
- Footer Component
158
+ key={i}
159
+ className="border-fm-divider-secondary grid grid-cols-5 gap-3 border-t py-2"
160
+ >
161
+ <p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm truncate">
162
+ Song {i + 1}
163
+ </p>
164
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm truncate">
165
+ Artist
166
+ </p>
167
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm truncate">
168
+ Album Name
169
+ </p>
170
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
171
+ 3:45
172
+ </p>
173
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
174
+ 1.2M
175
+ </p>
530
176
  </div>
531
- </div>
177
+ ))}
532
178
  </div>
533
179
  <ScrollBar orientation="horizontal" />
534
180
  </ScrollArea>
181
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm">
182
+ Wide table (560px content, 320px viewport)
183
+ </p>
535
184
  </div>
536
185
  </div>
537
186
  </div>
@@ -540,608 +189,283 @@ export const BothDirectionsScroll: Story = {
540
189
  docs: {
541
190
  description: {
542
191
  story:
543
- "Two-dimensional scrolling examples including data tables and design canvases that require both horizontal and vertical scrolling.",
192
+ "Comparison of all three scroll orientations: vertical with different height constraints, horizontal with a tag strip, and bidirectional with a wide data table.",
544
193
  },
545
194
  },
546
195
  },
547
196
  }
548
197
 
549
- // 4. Different Sizes
550
- export const DifferentSizes: Story = {
551
- render: () => (
552
- <div className="space-y-8">
553
- <div className="text-center">
554
- <h3 className="text-fm-primary mb-2 font-medium">Different Sizes</h3>
555
- <p className="text-fm-secondary text-sm">
556
- ScrollArea components in various sizes and configurations
557
- </p>
558
- </div>
559
-
560
- <div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
561
- {/* Small */}
562
- <div className="space-y-2">
563
- <h4 className="text-fm-secondary text-sm font-medium">
564
- Small (h-40)
565
- </h4>
566
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-40 w-full rounded-lg border">
567
- <div className="p-3">
568
- <h5 className="text-fm-primary mb-2 text-sm font-medium">
569
- Quick Notes
570
- </h5>
571
- <div className="text-fm-secondary space-y-2 text-xs">
572
- {Array.from({ length: 15 }, (_, i) => (
573
- <div key={i} className="bg-fm-surface-secondary rounded p-2">
574
- Note item {i + 1}: This is a quick note or reminder item.
575
- </div>
576
- ))}
577
- </div>
578
- </div>
579
- </ScrollArea>
580
- </div>
198
+ // ─── 2. UseCases ──────────────────────────────────────────────────────────────
581
199
 
582
- {/* Medium */}
583
- <div className="space-y-2">
584
- <h4 className="text-fm-secondary text-sm font-medium">
585
- Medium (h-64)
586
- </h4>
587
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-64 w-full rounded-lg border">
588
- <div className="p-4">
589
- <h5 className="text-fm-primary mb-3 text-sm font-medium">
590
- Task List
591
- </h5>
592
- <div className="space-y-3">
593
- {Array.from({ length: 12 }, (_, i) => (
594
- <div
595
- key={i}
596
- className="bg-fm-surface-secondary flex items-center gap-3 rounded-lg p-3"
597
- >
598
- <div
599
- className={`h-3 w-3 rounded-full ${
600
- i % 3 === 0
601
- ? "bg-fm-surface-positive"
602
- : "bg-fm-surface-tertiary"
603
- }`}
604
- ></div>
605
- <div>
606
- <div className="text-fm-primary text-sm">
607
- Task {i + 1}
608
- </div>
609
- <div className="text-fm-secondary text-xs">
610
- {i % 3 === 0 ? "Completed" : "Pending"}
611
- </div>
612
- </div>
613
- </div>
614
- ))}
615
- </div>
616
- </div>
617
- </ScrollArea>
618
- </div>
619
-
620
- {/* Large */}
621
- <div className="space-y-2">
622
- <h4 className="text-fm-secondary text-sm font-medium">
623
- Large (h-96)
624
- </h4>
625
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-96 w-full rounded-lg border">
626
- <div className="p-4">
627
- <h5 className="text-fm-primary mb-4 text-sm font-medium">
628
- Activity Feed
629
- </h5>
630
- <div className="space-y-4">
631
- {Array.from({ length: 20 }, (_, i) => (
632
- <div
633
- key={i}
634
- className="bg-fm-surface-secondary flex gap-3 rounded-lg p-3"
635
- >
636
- <div className="text-fm-primary flex h-8 w-8 items-center justify-center rounded-full bg-gradient-to-br from-blue-500 to-purple-600 text-xs font-medium">
637
- {String.fromCharCode(65 + (i % 26))}
638
- </div>
639
- <div className="flex-1">
640
- <div className="text-fm-primary text-sm">
641
- User {i + 1} performed an action
642
- </div>
643
- <div className="text-fm-secondary text-xs">
644
- {Math.floor(Math.random() * 60)} minutes ago
645
- </div>
646
- </div>
647
- </div>
648
- ))}
649
- </div>
650
- </div>
651
- </ScrollArea>
652
- </div>
653
- </div>
654
- </div>
655
- ),
656
- parameters: {
657
- docs: {
658
- description: {
659
- story:
660
- "ScrollArea components in different sizes from small notification lists to large activity feeds.",
661
- },
662
- },
200
+ const tracks = [
201
+ {
202
+ title: "Neon Pulse",
203
+ artist: "Synthwave Collective",
204
+ duration: "3:42",
205
+ plays: "4.1M",
663
206
  },
664
- }
207
+ {
208
+ title: "Midnight Rain",
209
+ artist: "Luna Beats",
210
+ duration: "4:10",
211
+ plays: "2.8M",
212
+ },
213
+ { title: "Golden Hour", artist: "Solstice", duration: "3:55", plays: "6.3M" },
214
+ {
215
+ title: "City Echoes",
216
+ artist: "Urban Drift",
217
+ duration: "2:58",
218
+ plays: "1.4M",
219
+ },
220
+ {
221
+ title: "Deep Waters",
222
+ artist: "Ocean State",
223
+ duration: "5:12",
224
+ plays: "892K",
225
+ },
226
+ {
227
+ title: "Electric Sky",
228
+ artist: "Volt Lab",
229
+ duration: "3:30",
230
+ plays: "3.7M",
231
+ },
232
+ {
233
+ title: "Static Dreams",
234
+ artist: "Cassette Ghost",
235
+ duration: "4:05",
236
+ plays: "2.1M",
237
+ },
238
+ {
239
+ title: "Sunrise Protocol",
240
+ artist: "Dawn Circuit",
241
+ duration: "3:18",
242
+ plays: "5.0M",
243
+ },
244
+ {
245
+ title: "Phantom Groove",
246
+ artist: "The Frequency",
247
+ duration: "4:48",
248
+ plays: "1.6M",
249
+ },
250
+ {
251
+ title: "Quiet Storm",
252
+ artist: "Ember Tone",
253
+ duration: "3:22",
254
+ plays: "3.2M",
255
+ },
256
+ ]
257
+
258
+ const messages = [
259
+ {
260
+ user: "Mia",
261
+ avatar: "M",
262
+ text: "Just dropped a new EP — check it out!",
263
+ time: "2m ago",
264
+ self: false,
265
+ },
266
+ {
267
+ user: "You",
268
+ avatar: "Y",
269
+ text: "Sounds amazing, already on repeat.",
270
+ time: "1m ago",
271
+ self: true,
272
+ },
273
+ {
274
+ user: "Mia",
275
+ avatar: "M",
276
+ text: "Thanks! Recorded it all in one weekend.",
277
+ time: "1m ago",
278
+ self: false,
279
+ },
280
+ {
281
+ user: "Kai",
282
+ avatar: "K",
283
+ text: "The production on track 3 is incredible.",
284
+ time: "45s ago",
285
+ self: false,
286
+ },
287
+ {
288
+ user: "You",
289
+ avatar: "Y",
290
+ text: "Agreed. The bass line hits hard.",
291
+ time: "30s ago",
292
+ self: true,
293
+ },
294
+ {
295
+ user: "Mia",
296
+ avatar: "M",
297
+ text: "I'll share the stems if you want to remix.",
298
+ time: "20s ago",
299
+ self: false,
300
+ },
301
+ {
302
+ user: "Kai",
303
+ avatar: "K",
304
+ text: "Yes please! Would love to flip it.",
305
+ time: "10s ago",
306
+ self: false,
307
+ },
308
+ {
309
+ user: "You",
310
+ avatar: "Y",
311
+ text: "Count me in too.",
312
+ time: "just now",
313
+ self: true,
314
+ },
315
+ ]
316
+
317
+ const settingsSections = [
318
+ {
319
+ section: "Playback",
320
+ items: [
321
+ "Audio quality",
322
+ "Crossfade duration",
323
+ "Equalizer presets",
324
+ "Volume normalisation",
325
+ ],
326
+ },
327
+ {
328
+ section: "Downloads",
329
+ items: [
330
+ "Download quality",
331
+ "Storage location",
332
+ "Auto-download new releases",
333
+ "Cache size limit",
334
+ ],
335
+ },
336
+ {
337
+ section: "Notifications",
338
+ items: [
339
+ "New release alerts",
340
+ "Friend activity",
341
+ "Podcast updates",
342
+ "Weekly digest",
343
+ ],
344
+ },
345
+ {
346
+ section: "Privacy",
347
+ items: [
348
+ "Listening history",
349
+ "Public profile",
350
+ "Activity status",
351
+ "Data sharing",
352
+ ],
353
+ },
354
+ ]
665
355
 
666
- // 5. Real World Examples
667
- export const RealWorldExamples: Story = {
356
+ export const UseCases: Story = {
668
357
  render: () => (
669
- <div className="space-y-8">
670
- <div className="text-center">
671
- <h3 className="text-fm-primary mb-2 font-medium">
672
- Real World Examples
673
- </h3>
674
- <p className="text-fm-secondary text-sm">
675
- Common use cases for scrollable areas in applications
676
- </p>
358
+ <div className="mx-auto max-w-3xl space-y-8 p-8">
359
+ {/* Track list */}
360
+ <div>
361
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
362
+ Scrollable Track List
363
+ </h4>
364
+ <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-72 rounded-xl border">
365
+ <div className="p-2">
366
+ {tracks.map((track, i) => (
367
+ <div
368
+ key={i}
369
+ className="hover:bg-fm-surface-primary flex items-center gap-4 rounded-lg px-3 py-2.5 transition-colors"
370
+ >
371
+ <span className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm w-5 text-right">
372
+ {i + 1}
373
+ </span>
374
+ <div className="bg-fm-surface-tertiary flex h-9 w-9 flex-none items-center justify-center rounded-md">
375
+ <span className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold">
376
+
377
+ </span>
378
+ </div>
379
+ <div className="min-w-0 flex-1">
380
+ <p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm truncate font-medium">
381
+ {track.title}
382
+ </p>
383
+ <p className="text-fm-secondary font-fm-text text-fm-sm leading-fm-sm truncate">
384
+ {track.artist}
385
+ </p>
386
+ </div>
387
+ <span className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm hidden sm:block">
388
+ {track.plays}
389
+ </span>
390
+ <span className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
391
+ {track.duration}
392
+ </span>
393
+ </div>
394
+ ))}
395
+ </div>
396
+ </ScrollArea>
677
397
  </div>
678
398
 
679
- <div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
680
- {/* Chat Messages */}
681
- <div className="space-y-2">
682
- <h4 className="text-fm-secondary text-sm font-medium">
683
- Chat Messages
684
- </h4>
685
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-80 w-full rounded-lg border">
686
- <div className="space-y-4 p-4">
687
- {[
688
- {
689
- user: "Alice",
690
- message: "Hey everyone! How's the project going?",
691
- time: "10:30",
692
- self: false,
693
- },
694
- {
695
- user: "You",
696
- message:
697
- "Going well! Just finished the new component library.",
698
- time: "10:32",
699
- self: true,
700
- },
701
- {
702
- user: "Bob",
703
- message: "That's awesome! Can't wait to try it out.",
704
- time: "10:33",
705
- self: false,
706
- },
707
- {
708
- user: "Alice",
709
- message: "Same here! Are there any examples we can look at?",
710
- time: "10:35",
711
- self: false,
712
- },
713
- {
714
- user: "You",
715
- message:
716
- "Yes! I've created a Storybook with all the components and examples.",
717
- time: "10:36",
718
- self: true,
719
- },
720
- {
721
- user: "Carol",
722
- message:
723
- "Perfect timing! I was just about to ask about documentation.",
724
- time: "10:38",
725
- self: false,
726
- },
727
- {
728
- user: "Bob",
729
- message: "The dark theme looks really good btw 👍",
730
- time: "10:40",
731
- self: false,
732
- },
733
- {
734
- user: "You",
735
- message:
736
- "Thanks! We spent a lot of time getting the frosted glass effects right.",
737
- time: "10:41",
738
- self: true,
739
- },
740
- {
741
- user: "Alice",
742
- message:
743
- "It really shows! The attention to detail is impressive.",
744
- time: "10:43",
745
- self: false,
746
- },
747
- {
748
- user: "Carol",
749
- message: "Should we schedule a demo session for the team?",
750
- time: "10:45",
751
- self: false,
752
- },
753
- {
754
- user: "You",
755
- message: "Great idea! How about tomorrow at 2 PM?",
756
- time: "10:46",
757
- self: true,
758
- },
759
- {
760
- user: "Bob",
761
- message: "Works for me! I'll send out calendar invites.",
762
- time: "10:47",
763
- self: false,
764
- },
765
- ].map((msg, i) => (
399
+ {/* Message thread */}
400
+ <div>
401
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
402
+ Message Thread
403
+ </h4>
404
+ <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-64 rounded-xl border">
405
+ <div className="flex flex-col gap-3 p-4">
406
+ {messages.map((msg, i) => (
407
+ <div
408
+ key={i}
409
+ className={`flex items-end gap-2 ${msg.self ? "flex-row-reverse" : "flex-row"}`}
410
+ >
411
+ <div className="bg-fm-surface-tertiary flex h-7 w-7 flex-none items-center justify-center rounded-full">
412
+ <span className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm font-semibold">
413
+ {msg.avatar}
414
+ </span>
415
+ </div>
766
416
  <div
767
- key={i}
768
- className={`flex ${msg.self ? "justify-end" : "justify-start"}`}
417
+ className={`max-w-[72%] space-y-1 ${msg.self ? "items-end" : "items-start"} flex flex-col`}
769
418
  >
770
419
  <div
771
- className={`max-w-xs rounded-lg p-3 ${
420
+ className={`rounded-2xl px-3 py-2 ${
772
421
  msg.self
773
- ? "bg-fm-surface-info text-fm-surface-primary"
774
- : "bg-fm-surface-secondary text-fm-primary"
422
+ ? "bg-fm-surface-info-sec"
423
+ : "bg-fm-surface-primary border-fm-divider-secondary border"
775
424
  }`}
776
425
  >
777
- {!msg.self && (
778
- <div className="text-fm-secondary mb-1 text-xs font-medium">
779
- {msg.user}
780
- </div>
781
- )}
782
- <div className="text-sm">{msg.message}</div>
783
- <div
784
- className={`mt-1 text-xs ${
785
- msg.self ? "text-fm-info-sec" : "text-fm-secondary"
786
- }`}
787
- >
788
- {msg.time}
789
- </div>
426
+ <p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
427
+ {msg.text}
428
+ </p>
790
429
  </div>
430
+ <p className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm px-1">
431
+ {msg.time}
432
+ </p>
791
433
  </div>
792
- ))}
793
- </div>
794
- </ScrollArea>
795
- </div>
796
-
797
- {/* File Explorer */}
798
- <div className="space-y-2">
799
- <h4 className="text-fm-secondary text-sm font-medium">
800
- File Explorer
801
- </h4>
802
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-80 w-full rounded-lg border">
803
- <div className="text-fm-primary p-2">
804
- {[
805
- {
806
- name: "📁 Documents",
807
- type: "folder",
808
- size: "",
809
- modified: "Today",
810
- },
811
- {
812
- name: "📁 Images",
813
- type: "folder",
814
- size: "",
815
- modified: "Yesterday",
816
- },
817
- {
818
- name: "📁 Projects",
819
- type: "folder",
820
- size: "",
821
- modified: "2 days ago",
822
- },
823
- {
824
- name: "📄 README.md",
825
- type: "file",
826
- size: "2.1 KB",
827
- modified: "Today",
828
- },
829
- {
830
- name: "📄 package.json",
831
- type: "file",
832
- size: "1.8 KB",
833
- modified: "Today",
834
- },
835
- {
836
- name: "🖼️ hero-image.jpg",
837
- type: "file",
838
- size: "245 KB",
839
- modified: "Yesterday",
840
- },
841
- {
842
- name: "📄 index.html",
843
- type: "file",
844
- size: "3.2 KB",
845
- modified: "2 days ago",
846
- },
847
- {
848
- name: "🎨 styles.css",
849
- type: "file",
850
- size: "12.5 KB",
851
- modified: "Today",
852
- },
853
- {
854
- name: "⚡ app.js",
855
- type: "file",
856
- size: "8.7 KB",
857
- modified: "Today",
858
- },
859
- {
860
- name: "📄 config.json",
861
- type: "file",
862
- size: "892 B",
863
- modified: "3 days ago",
864
- },
865
- {
866
- name: "🖼️ logo.svg",
867
- type: "file",
868
- size: "3.4 KB",
869
- modified: "Yesterday",
870
- },
871
- {
872
- name: "📄 .gitignore",
873
- type: "file",
874
- size: "156 B",
875
- modified: "5 days ago",
876
- },
877
- {
878
- name: "📁 node_modules",
879
- type: "folder",
880
- size: "",
881
- modified: "Today",
882
- },
883
- {
884
- name: "📄 tsconfig.json",
885
- type: "file",
886
- size: "654 B",
887
- modified: "Yesterday",
888
- },
889
- {
890
- name: "🔧 webpack.config.js",
891
- type: "file",
892
- size: "2.9 KB",
893
- modified: "3 days ago",
894
- },
895
- ].map((item, i) => (
896
- <div
897
- key={i}
898
- className="hover:bg-fm-surface-secondary flex cursor-pointer items-center justify-between rounded p-2"
899
- >
900
- <div className="flex min-w-0 flex-1 items-center gap-2">
901
- <span className="text-sm">{item.name}</span>
902
- </div>
903
- <div className="text-fm-secondary flex items-center gap-4 text-xs">
904
- <span className="w-12 text-right">{item.size}</span>
905
- <span className="w-20 text-right">{item.modified}</span>
906
- </div>
907
- </div>
908
- ))}
909
- </div>
910
- </ScrollArea>
911
- </div>
912
-
913
- {/* Code Editor Sidebar */}
914
- <div className="space-y-2">
915
- <h4 className="text-fm-secondary text-sm font-medium">
916
- Code Editor Sidebar
917
- </h4>
918
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-80 w-full rounded-lg border">
919
- <div className="p-2">
920
- <div className="space-y-1">
921
- <div className="text-fm-primary p-2 text-xs font-medium tracking-wide uppercase">
922
- Explorer
923
- </div>
924
- {[
925
- { name: "src", level: 0, type: "folder", expanded: true },
926
- {
927
- name: "components",
928
- level: 1,
929
- type: "folder",
930
- expanded: true,
931
- },
932
- { name: "Button.tsx", level: 2, type: "file" },
933
- { name: "Button.stories.tsx", level: 2, type: "file" },
934
- { name: "Avatar.tsx", level: 2, type: "file" },
935
- { name: "Avatar.stories.tsx", level: 2, type: "file" },
936
- { name: "ScrollArea.tsx", level: 2, type: "file" },
937
- { name: "hooks", level: 1, type: "folder", expanded: false },
938
- { name: "utils", level: 1, type: "folder", expanded: true },
939
- { name: "cn.ts", level: 2, type: "file" },
940
- { name: "types.ts", level: 2, type: "file" },
941
- { name: "index.ts", level: 1, type: "file" },
942
- { name: "App.tsx", level: 1, type: "file" },
943
- { name: "public", level: 0, type: "folder", expanded: false },
944
- { name: "package.json", level: 0, type: "file" },
945
- { name: "tsconfig.json", level: 0, type: "file" },
946
- { name: "tailwind.config.js", level: 0, type: "file" },
947
- { name: "vite.config.ts", level: 0, type: "file" },
948
- ].map((item, i) => (
949
- <div
950
- key={i}
951
- className="hover:bg-fm-surface-secondary flex cursor-pointer items-center gap-1 rounded p-1 text-sm"
952
- style={{ paddingLeft: `${8 + item.level * 16}px` }}
953
- >
954
- {item.type === "folder" && (
955
- <span className="text-fm-secondary">
956
- {item.expanded ? "📂" : "📁"}
957
- </span>
958
- )}
959
- {item.type === "file" && (
960
- <span className="text-fm-secondary">📄</span>
961
- )}
962
- <span className="text-fm-primary">{item.name}</span>
963
- </div>
964
- ))}
965
434
  </div>
966
- </div>
967
- </ScrollArea>
968
- </div>
969
-
970
- {/* Settings Panel */}
971
- <div className="space-y-2">
972
- <h4 className="text-fm-secondary text-sm font-medium">
973
- Settings Panel
974
- </h4>
975
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-80 w-full rounded-lg border">
976
- <div className="space-y-6 p-4">
977
- {[
978
- {
979
- section: "Appearance",
980
- settings: [
981
- { label: "Theme", value: "Dark", type: "select" },
982
- { label: "Font Size", value: "Medium", type: "select" },
983
- { label: "Animations", value: true, type: "toggle" },
984
- ],
985
- },
986
- {
987
- section: "Behavior",
988
- settings: [
989
- { label: "Auto Save", value: true, type: "toggle" },
990
- {
991
- label: "Smart Suggestions",
992
- value: false,
993
- type: "toggle",
994
- },
995
- {
996
- label: "Keyboard Shortcuts",
997
- value: true,
998
- type: "toggle",
999
- },
1000
- ],
1001
- },
1002
- {
1003
- section: "Privacy",
1004
- settings: [
1005
- { label: "Analytics", value: false, type: "toggle" },
1006
- { label: "Crash Reports", value: true, type: "toggle" },
1007
- { label: "Usage Data", value: false, type: "toggle" },
1008
- ],
1009
- },
1010
- {
1011
- section: "Advanced",
1012
- settings: [
1013
- { label: "Developer Mode", value: false, type: "toggle" },
1014
- {
1015
- label: "Experimental Features",
1016
- value: false,
1017
- type: "toggle",
1018
- },
1019
- { label: "Debug Logging", value: false, type: "toggle" },
1020
- ],
1021
- },
1022
- ].map((group, i) => (
1023
- <div key={i}>
1024
- <h5 className="text-fm-primary mb-3 text-sm font-medium">
1025
- {group.section}
1026
- </h5>
1027
- <div className="space-y-3">
1028
- {group.settings.map((setting, j) => (
1029
- <div
1030
- key={j}
1031
- className="flex items-center justify-between"
1032
- >
1033
- <span className="text-fm-secondary text-sm">
1034
- {setting.label}
1035
- </span>
1036
- {setting.type === "toggle" ? (
1037
- <div
1038
- className={`h-5 w-10 rounded-full p-1 ${
1039
- setting.value
1040
- ? "bg-fm-surface-info"
1041
- : "bg-fm-surface-tertiary"
1042
- }`}
1043
- >
1044
- <div
1045
- className={`bg-fm-surface-primary h-3 w-3 rounded-full transition-transform ${
1046
- setting.value
1047
- ? "translate-x-5"
1048
- : "translate-x-0"
1049
- }`}
1050
- ></div>
1051
- </div>
1052
- ) : (
1053
- <span className="text-fm-secondary text-sm">
1054
- {setting.value}
1055
- </span>
1056
- )}
1057
- </div>
1058
- ))}
1059
- </div>
1060
- </div>
1061
- ))}
1062
- </div>
1063
- </ScrollArea>
1064
- </div>
1065
- </div>
1066
- </div>
1067
- ),
1068
- parameters: {
1069
- docs: {
1070
- description: {
1071
- story:
1072
- "Real-world examples including chat interfaces, file explorers, code editor sidebars, and settings panels demonstrating practical ScrollArea usage.",
1073
- },
1074
- },
1075
- },
1076
- }
1077
-
1078
- // 6. Performance Example
1079
- export const PerformanceExample: Story = {
1080
- render: () => (
1081
- <div className="space-y-8">
1082
- <div className="text-center">
1083
- <h3 className="text-fm-primary mb-2 font-medium">
1084
- Performance Example
1085
- </h3>
1086
- <p className="text-fm-secondary text-sm">
1087
- Large datasets handled efficiently with virtual scrolling simulation
1088
- </p>
1089
- </div>
1090
-
1091
- <div className="space-y-4">
1092
- <div className="text-center">
1093
- <div className="border-fm-divider-secondary bg-fm-surface-secondary inline-block rounded-lg border p-4">
1094
- <h4 className="text-fm-primary mb-2 text-sm font-medium">
1095
- Large Dataset
1096
- </h4>
1097
- <p className="text-fm-secondary text-xs leading-relaxed">
1098
- This example shows 1000+ items in a scrollable area. The
1099
- ScrollArea component handles smooth scrolling even with large
1100
- amounts of content.
1101
- </p>
435
+ ))}
1102
436
  </div>
1103
- </div>
437
+ </ScrollArea>
438
+ </div>
1104
439
 
1105
- <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary mx-auto h-96 w-full max-w-2xl rounded-lg border">
440
+ {/* Settings panel */}
441
+ <div>
442
+ <h4 className="text-fm-secondary font-fm-text text-fm-md leading-fm-md mb-4 font-medium">
443
+ Settings Panel
444
+ </h4>
445
+ <ScrollArea className="border-fm-divider-secondary bg-fm-surface-secondary h-64 w-72 rounded-xl border">
1106
446
  <div className="p-4">
1107
- <h4 className="text-fm-primary mb-4 text-sm leading-none font-medium">
1108
- Large Item List (1000 items)
1109
- </h4>
1110
- <div className="space-y-1">
1111
- {Array.from({ length: 1000 }, (_, i) => (
1112
- <div
1113
- key={i}
1114
- className="bg-fm-surface-secondary hover:bg-fm-surface-tertiary flex items-center justify-between rounded-lg p-3 transition-colors"
1115
- >
1116
- <div className="flex items-center gap-3">
447
+ {settingsSections.map((group) => (
448
+ <div key={group.section} className="mb-5 last:mb-0">
449
+ <p className="text-fm-primary font-fm-brand text-fm-sm leading-fm-sm mb-2 font-semibold tracking-widest uppercase">
450
+ {group.section}
451
+ </p>
452
+ <div className="space-y-px">
453
+ {group.items.map((item) => (
1117
454
  <div
1118
- className={`text-fm-primary flex h-8 w-8 items-center justify-center rounded-full text-xs font-medium ${
1119
- [
1120
- "bg-blue-500",
1121
- "bg-green-500",
1122
- "bg-purple-500",
1123
- "bg-orange-500",
1124
- ][i % 4]
1125
- }`}
455
+ key={item}
456
+ className="hover:bg-fm-surface-primary flex items-center justify-between rounded-md px-3 py-2 transition-colors"
1126
457
  >
1127
- {i + 1}
1128
- </div>
1129
- <div>
1130
- <div className="text-fm-primary text-sm font-medium">
1131
- Item {i + 1}
1132
- </div>
1133
- <div className="text-fm-secondary text-xs">
1134
- Category:{" "}
1135
- {["Development", "Design", "Marketing", "Sales"][i % 4]}
1136
- </div>
458
+ <p className="text-fm-primary font-fm-text text-fm-sm leading-fm-sm">
459
+ {item}
460
+ </p>
461
+ <span className="text-fm-tertiary font-fm-text text-fm-sm leading-fm-sm">
462
+
463
+ </span>
1137
464
  </div>
1138
- </div>
1139
- <div className="text-fm-secondary text-xs">
1140
- {new Date(Date.now() - i * 60000).toLocaleTimeString()}
1141
- </div>
465
+ ))}
1142
466
  </div>
1143
- ))}
1144
- </div>
467
+ </div>
468
+ ))}
1145
469
  </div>
1146
470
  </ScrollArea>
1147
471
  </div>
@@ -1151,7 +475,7 @@ export const PerformanceExample: Story = {
1151
475
  docs: {
1152
476
  description: {
1153
477
  story:
1154
- "Performance demonstration with 1000+ items showing how ScrollArea maintains smooth scrolling with large datasets.",
478
+ "Real product-shaped scenarios: a numbered track list with play counts, a chat message thread between collaborators, and a settings panel with categorised preferences — all inside fixed-height scroll regions.",
1155
479
  },
1156
480
  },
1157
481
  },