@snowcone-app/ui 0.1.43 → 0.2.1

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 (196) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +18 -4
  3. package/dist/index.cjs +5 -2
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.js +5 -2
  6. package/dist/index.js.map +1 -1
  7. package/package.json +9 -5
  8. package/src/components/CanvasIsolationBoundary.tsx +202 -0
  9. package/src/components/LoadingOverlayPrism.tsx +251 -0
  10. package/src/composed/AddToCart.tsx +229 -0
  11. package/src/composed/ArtAlignment.tsx +703 -0
  12. package/src/composed/ArtSelector.tsx +290 -0
  13. package/src/composed/ArtworkCustomizer.tsx +212 -0
  14. package/src/composed/CanvasEditor.tsx +79 -0
  15. package/src/composed/ColorPicker.tsx +111 -0
  16. package/src/composed/CurrentSelectionDisplay.tsx +86 -0
  17. package/src/composed/HeroProductImage.tsx +1079 -0
  18. package/src/composed/Lightbox.index.ts +2 -0
  19. package/src/composed/Lightbox.tsx +230 -0
  20. package/src/composed/PlacementClipShapeSelector.tsx +88 -0
  21. package/src/composed/PlacementTabs.tsx +179 -0
  22. package/src/composed/ProductCard.tsx +298 -0
  23. package/src/composed/ProductGallery.tsx +54 -0
  24. package/src/composed/ProductImage.tsx +129 -0
  25. package/src/composed/ProductList.tsx +147 -0
  26. package/src/composed/ProductOptions.tsx +305 -0
  27. package/src/composed/RealtimeMockup.tsx +121 -0
  28. package/src/composed/TileCount.tsx +348 -0
  29. package/src/composed/carousels/HeroCarousel.tsx +240 -0
  30. package/src/composed/carousels/MobileProductCarousel.tsx +1002 -0
  31. package/src/composed/carousels/index.ts +11 -0
  32. package/src/composed/carousels/types.ts +58 -0
  33. package/src/composed/grids/MasonryGrid.tsx +238 -0
  34. package/src/composed/grids/index.ts +9 -0
  35. package/src/composed/search/CurrentRefinements.tsx +80 -0
  36. package/src/composed/search/Filters.tsx +49 -0
  37. package/src/composed/search/FiltersButton.tsx +57 -0
  38. package/src/composed/search/FiltersDrawer.tsx +375 -0
  39. package/src/composed/search/ProductGrid.tsx +118 -0
  40. package/src/composed/search/ProductHit.tsx +56 -0
  41. package/src/composed/search/SearchBox.tsx +109 -0
  42. package/src/composed/search/SearchProvider.tsx +136 -0
  43. package/src/composed/search/facetConfig.ts +16 -0
  44. package/src/composed/search/index.ts +22 -0
  45. package/src/composed/search/meilisearchAdapter.ts +20 -0
  46. package/src/composed/search/types.ts +22 -0
  47. package/src/composed/zoom/EnhancedImageViewer.tsx +505 -0
  48. package/src/composed/zoom/ResponsiveZoom.tsx +134 -0
  49. package/src/composed/zoom/ZoomOverlay.tsx +194 -0
  50. package/src/composed/zoom/index.ts +12 -0
  51. package/src/composed/zoom/types.ts +12 -0
  52. package/src/design-system/ColorPalette.tsx +126 -0
  53. package/src/design-system/ColorSwatch.tsx +49 -0
  54. package/src/design-system/DesignSystemPage.tsx +130 -0
  55. package/src/design-system/ThemeSwitcher.tsx +181 -0
  56. package/src/design-system/TypographyScale.tsx +106 -0
  57. package/src/design-system/index.ts +5 -0
  58. package/src/ecommerce/stories/HeroProductImage.stories.tsx +66 -0
  59. package/src/ecommerce/stories/PDPHeroGallery.stories.tsx +105 -0
  60. package/src/ecommerce/stories/PDPInfoPanel.stories.tsx +472 -0
  61. package/src/ecommerce/stories/PDPLayout.stories.tsx +365 -0
  62. package/src/hooks/useBrand.ts +41 -0
  63. package/src/hooks/useCanvasContext.ts +127 -0
  64. package/src/hooks/useDeviceDetection.ts +64 -0
  65. package/src/hooks/useFocusTrap.ts +70 -0
  66. package/src/hooks/useImagePreloader.ts +268 -0
  67. package/src/hooks/useImageTransition.ts +608 -0
  68. package/src/hooks/usePlacementsProcessor.ts +74 -0
  69. package/src/hooks/useProductGallery.ts +193 -0
  70. package/src/hooks/useProductPage.ts +467 -0
  71. package/src/hooks/useRenderGuard.ts +96 -0
  72. package/src/hooks/useScrollDirection.ts +196 -0
  73. package/src/hooks/viewport/index.ts +25 -0
  74. package/src/hooks/viewport/useContainerWidth.ts +59 -0
  75. package/src/hooks/viewport/useMediaQuery.ts +52 -0
  76. package/src/hooks/viewport/useResponsiveImageCap.ts +149 -0
  77. package/src/hooks/viewport/useViewportDimensions.ts +135 -0
  78. package/src/hooks/viewport/useWideMonitorMode.ts +150 -0
  79. package/src/hooks/visibility/index.ts +15 -0
  80. package/src/hooks/visibility/observerPool.ts +150 -0
  81. package/src/index.ts +240 -0
  82. package/src/layouts/hero-zoom/HeroShrinkLayout.tsx +209 -0
  83. package/src/layouts/hero-zoom/HeroZoomLayout.tsx +351 -0
  84. package/src/layouts/hero-zoom/index.ts +30 -0
  85. package/src/layouts/hero-zoom/stories/HeroZoomLayout.stories.tsx +350 -0
  86. package/src/layouts/hero-zoom/types.ts +113 -0
  87. package/src/layouts/hero-zoom/useHeroZoomScales.ts +156 -0
  88. package/src/layouts/index.ts +9 -0
  89. package/src/layouts/pdp/EdgeBlurBox.tsx +210 -0
  90. package/src/layouts/pdp/ImageBlurExtension.tsx +215 -0
  91. package/src/layouts/pdp/ImageEdgeBlur.tsx +215 -0
  92. package/src/layouts/pdp/PDPLayout.tsx +246 -0
  93. package/src/layouts/pdp/SimpleImageBlur.tsx +140 -0
  94. package/src/layouts/pdp/index.ts +40 -0
  95. package/src/lib/env.ts +15 -0
  96. package/src/lib/locale.ts +167 -0
  97. package/src/lib/router.tsx +46 -0
  98. package/src/lib/utils.ts +6 -0
  99. package/src/lightbox/README.md +77 -0
  100. package/src/next/index.tsx +26 -0
  101. package/src/patterns/MockupPriorityProvider.tsx +1014 -0
  102. package/src/patterns/Product.tsx +850 -0
  103. package/src/patterns/ProductPageProvider.tsx +224 -0
  104. package/src/patterns/RealtimeProvider.tsx +1162 -0
  105. package/src/patterns/ShopProvider.tsx +603 -0
  106. package/src/personalization/PersonalizationBridge.tsx +235 -0
  107. package/src/personalization/PersonalizationContext.ts +29 -0
  108. package/src/personalization/PersonalizationInputs.tsx +110 -0
  109. package/src/personalization/PersonalizationProvider.tsx +407 -0
  110. package/src/personalization/canvas-stub.d.ts +22 -0
  111. package/src/personalization/index.ts +43 -0
  112. package/src/personalization/types.ts +48 -0
  113. package/src/personalization/usePersonalization.ts +32 -0
  114. package/src/personalization/usePersonalizationShimmer.ts +159 -0
  115. package/src/personalization/utils.ts +59 -0
  116. package/src/primitives/BrandLogo.tsx +65 -0
  117. package/src/primitives/BrandName.tsx +51 -0
  118. package/src/primitives/Button.tsx +123 -0
  119. package/src/primitives/ColorSwatch.tsx +221 -0
  120. package/src/primitives/DragHintAnimation.tsx +190 -0
  121. package/src/primitives/EdgeSwipeGuards.tsx +60 -0
  122. package/src/primitives/FloatingActionGroup.tsx +176 -0
  123. package/src/primitives/ProductPrice.tsx +171 -0
  124. package/src/primitives/ProgressiveBlur.tsx +295 -0
  125. package/src/primitives/ThemeToggle.tsx +125 -0
  126. package/src/primitives/__tests__/story-coverage.test.ts +98 -0
  127. package/src/primitives/accordion.tsx +280 -0
  128. package/src/primitives/badge.tsx +137 -0
  129. package/src/primitives/card.tsx +61 -0
  130. package/src/primitives/checkbox.tsx +56 -0
  131. package/src/primitives/collapsible.tsx +51 -0
  132. package/src/primitives/drawer.tsx +828 -0
  133. package/src/primitives/dropdown-menu.tsx +197 -0
  134. package/src/primitives/fieldset.tsx +73 -0
  135. package/src/primitives/index.ts +138 -0
  136. package/src/primitives/input.tsx +91 -0
  137. package/src/primitives/kbd.tsx +130 -0
  138. package/src/primitives/label.tsx +20 -0
  139. package/src/primitives/link.tsx +182 -0
  140. package/src/primitives/popover.tsx +80 -0
  141. package/src/primitives/radio-group.tsx +79 -0
  142. package/src/primitives/scroll-fade.tsx +159 -0
  143. package/src/primitives/select.tsx +170 -0
  144. package/src/primitives/separator.tsx +25 -0
  145. package/src/primitives/slider.tsx +221 -0
  146. package/src/primitives/spinner.tsx +72 -0
  147. package/src/primitives/stories/Accordion.stories.tsx +121 -0
  148. package/src/primitives/stories/Badge.stories.tsx +221 -0
  149. package/src/primitives/stories/Button.stories.tsx +185 -0
  150. package/src/primitives/stories/Card.stories.tsx +171 -0
  151. package/src/primitives/stories/Checkbox.stories.tsx +214 -0
  152. package/src/primitives/stories/Collapsible.stories.tsx +230 -0
  153. package/src/primitives/stories/Drawer.stories.tsx +378 -0
  154. package/src/primitives/stories/DropdownMenu.stories.tsx +182 -0
  155. package/src/primitives/stories/Fieldset.stories.tsx +212 -0
  156. package/src/primitives/stories/Input.stories.tsx +172 -0
  157. package/src/primitives/stories/Kbd.stories.tsx +183 -0
  158. package/src/primitives/stories/Label.stories.tsx +98 -0
  159. package/src/primitives/stories/Link.stories.tsx +260 -0
  160. package/src/primitives/stories/Popover.stories.tsx +178 -0
  161. package/src/primitives/stories/RadioGroup.stories.tsx +205 -0
  162. package/src/primitives/stories/Select.stories.tsx +222 -0
  163. package/src/primitives/stories/Separator.stories.tsx +134 -0
  164. package/src/primitives/stories/Slider.stories.tsx +203 -0
  165. package/src/primitives/stories/Spinner.stories.tsx +142 -0
  166. package/src/primitives/stories/Surface.stories.tsx +257 -0
  167. package/src/primitives/stories/Switch.stories.tsx +131 -0
  168. package/src/primitives/stories/Tabs.stories.tsx +275 -0
  169. package/src/primitives/stories/TextField.stories.tsx +139 -0
  170. package/src/primitives/stories/Textarea.stories.tsx +148 -0
  171. package/src/primitives/stories/Tooltip.stories.tsx +119 -0
  172. package/src/primitives/surface.tsx +86 -0
  173. package/src/primitives/switch.tsx +35 -0
  174. package/src/primitives/tabs.tsx +206 -0
  175. package/src/primitives/text-field.tsx +84 -0
  176. package/src/primitives/textarea.tsx +50 -0
  177. package/src/primitives/tooltip.tsx +58 -0
  178. package/src/services/CanvasExportService.ts +518 -0
  179. package/src/styles/base.css +380 -0
  180. package/src/styles/defaults.css +280 -0
  181. package/src/styles/globals.css +1242 -0
  182. package/src/styles/index.css +17 -0
  183. package/src/styles/ne-themes.css +4740 -0
  184. package/src/styles/tailwind.css +11 -0
  185. package/src/styles/tokens.css +117 -0
  186. package/src/styles/utilities.css +188 -0
  187. package/src/themes/apply-theme.ts +449 -0
  188. package/src/themes/getThemeStyles.ts +454 -0
  189. package/src/themes/index.ts +48 -0
  190. package/src/themes/oklch-theme.ts +283 -0
  191. package/src/themes/presets.ts +989 -0
  192. package/src/themes/types.ts +386 -0
  193. package/src/themes/useTheme.tsx +450 -0
  194. package/src/utils/dev-warnings.ts +161 -0
  195. package/src/utils/devWarnings.ts +153 -0
  196. package/dist/styles.css +0 -1
@@ -0,0 +1,134 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { Separator } from '../separator';
3
+ import { Input } from '../input';
4
+ import { Label } from '../label';
5
+ import { Button } from '../button';
6
+
7
+ const meta: Meta<typeof Separator> = {
8
+ title: 'UI/Separator',
9
+ component: Separator,
10
+ parameters: {
11
+ layout: 'centered',
12
+ },
13
+ tags: ['autodocs'],
14
+ argTypes: {
15
+ orientation: {
16
+ control: 'select',
17
+ options: ['horizontal', 'vertical'],
18
+ },
19
+ decorative: {
20
+ control: 'boolean',
21
+ },
22
+ },
23
+ };
24
+
25
+ export default meta;
26
+ type Story = StoryObj<typeof meta>;
27
+
28
+ export const Horizontal: Story = {
29
+ render: () => (
30
+ <div className="w-[400px]">
31
+ <div className="space-y-1">
32
+ <h4 className="text-sm leading-none text-foreground font-label">Radix Primitives</h4>
33
+ <p className="text-sm text-muted-foreground font-body">An open-source UI component library.</p>
34
+ </div>
35
+ <Separator className="my-4" />
36
+ <div className="flex h-5 items-center space-x-4 text-sm text-foreground">
37
+ <div>Blog</div>
38
+ <Separator orientation="vertical" />
39
+ <div>Docs</div>
40
+ <Separator orientation="vertical" />
41
+ <div>Source</div>
42
+ </div>
43
+ </div>
44
+ ),
45
+ };
46
+
47
+ export const Vertical: Story = {
48
+ render: () => (
49
+ <div className="flex h-[200px] items-center">
50
+ <div className="p-4">
51
+ <h4 className="text-sm text-foreground font-label">Section 1</h4>
52
+ <p className="text-sm text-muted-foreground font-body">Content for section one.</p>
53
+ </div>
54
+ <Separator orientation="vertical" className="mx-4" />
55
+ <div className="p-4">
56
+ <h4 className="text-sm text-foreground font-label">Section 2</h4>
57
+ <p className="text-sm text-muted-foreground font-body">Content for section two.</p>
58
+ </div>
59
+ <Separator orientation="vertical" className="mx-4" />
60
+ <div className="p-4">
61
+ <h4 className="text-sm text-foreground font-label">Section 3</h4>
62
+ <p className="text-sm text-muted-foreground font-body">Content for section three.</p>
63
+ </div>
64
+ </div>
65
+ ),
66
+ };
67
+
68
+ export const InCard: Story = {
69
+ render: () => (
70
+ <div className="w-[350px] rounded-xl border border-divider bg-surface p-6">
71
+ <h3 className="font-heading text-foreground">Account Settings</h3>
72
+ <p className="text-sm text-muted-foreground">Manage your account preferences.</p>
73
+ <Separator className="my-4" />
74
+ <div className="space-y-4">
75
+ <div className="flex justify-between">
76
+ <span className="text-sm text-foreground">Email notifications</span>
77
+ <span className="text-sm text-muted-foreground">Enabled</span>
78
+ </div>
79
+ <div className="flex justify-between">
80
+ <span className="text-sm text-foreground">Two-factor auth</span>
81
+ <span className="text-sm text-muted-foreground">Disabled</span>
82
+ </div>
83
+ </div>
84
+ <Separator className="my-4" />
85
+ <div className="flex justify-end">
86
+ <button className="text-sm text-primary hover:underline">Edit settings</button>
87
+ </div>
88
+ </div>
89
+ ),
90
+ };
91
+
92
+ export const WithText: Story = {
93
+ render: () => (
94
+ <div className="w-[400px]">
95
+ <div className="relative">
96
+ <div className="absolute inset-0 flex items-center">
97
+ <Separator />
98
+ </div>
99
+ <div className="relative flex justify-center text-xs uppercase">
100
+ <span className="bg-background px-2 text-muted-foreground">Or continue with</span>
101
+ </div>
102
+ </div>
103
+ </div>
104
+ ),
105
+ };
106
+
107
+ export const FormDivider: Story = {
108
+ render: () => (
109
+ <div className="w-[350px] space-y-4">
110
+ <div className="space-y-2">
111
+ <Label htmlFor="email">Email</Label>
112
+ <Input id="email" type="email" placeholder="email@example.com" />
113
+ </div>
114
+ <div className="space-y-2">
115
+ <Label htmlFor="password">Password</Label>
116
+ <Input id="password" type="password" placeholder="••••••••" />
117
+ </div>
118
+ <Button className="w-full">Sign In</Button>
119
+
120
+ <div className="relative py-4">
121
+ <div className="absolute inset-0 flex items-center">
122
+ <Separator />
123
+ </div>
124
+ <div className="relative flex justify-center text-xs uppercase">
125
+ <span className="bg-background px-2 text-muted-foreground">Or</span>
126
+ </div>
127
+ </div>
128
+
129
+ <Button variant="secondary" className="w-full">
130
+ Continue with Google
131
+ </Button>
132
+ </div>
133
+ ),
134
+ };
@@ -0,0 +1,203 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { useState } from 'react';
3
+ import { Slider } from '../slider';
4
+ import { Label } from '../label';
5
+
6
+ const meta: Meta<typeof Slider> = {
7
+ title: 'UI/Slider',
8
+ component: Slider,
9
+ parameters: {
10
+ layout: 'centered',
11
+ },
12
+ tags: ['autodocs'],
13
+ argTypes: {
14
+ min: {
15
+ control: { type: 'number' },
16
+ description: 'Minimum value',
17
+ },
18
+ max: {
19
+ control: { type: 'number' },
20
+ description: 'Maximum value',
21
+ },
22
+ step: {
23
+ control: { type: 'number' },
24
+ description: 'Step increment',
25
+ },
26
+ disabled: {
27
+ control: 'boolean',
28
+ description: 'Disable the slider',
29
+ },
30
+ },
31
+ };
32
+
33
+ export default meta;
34
+ type Story = StoryObj<typeof meta>;
35
+
36
+ export const Default: Story = {
37
+ args: {
38
+ defaultValue: [50],
39
+ max: 100,
40
+ step: 1,
41
+ className: 'w-[200px]',
42
+ },
43
+ };
44
+
45
+ export const WithLabel: Story = {
46
+ render: () => {
47
+ const [value, setValue] = useState([50]);
48
+ return (
49
+ <div className="grid w-full max-w-sm gap-2">
50
+ <div className="flex justify-between">
51
+ <Label>Volume</Label>
52
+ <span className="text-sm text-muted-foreground">{value[0]}%</span>
53
+ </div>
54
+ <Slider value={value} onValueChange={setValue} max={100} step={1} />
55
+ </div>
56
+ );
57
+ },
58
+ };
59
+
60
+ export const Range: Story = {
61
+ render: () => {
62
+ const [value, setValue] = useState([25, 75]);
63
+ return (
64
+ <div className="grid w-full max-w-sm gap-2">
65
+ <div className="flex justify-between">
66
+ <Label>Price Range</Label>
67
+ <span className="text-sm text-muted-foreground">
68
+ ${value[0]} - ${value[1]}
69
+ </span>
70
+ </div>
71
+ <Slider value={value} onValueChange={setValue} max={100} step={1} />
72
+ </div>
73
+ );
74
+ },
75
+ };
76
+
77
+ export const CustomStep: Story = {
78
+ render: () => {
79
+ const [value, setValue] = useState([50]);
80
+ return (
81
+ <div className="grid w-full max-w-sm gap-2">
82
+ <div className="flex justify-between">
83
+ <Label>Step: 10</Label>
84
+ <span className="text-sm text-muted-foreground">{value[0]}</span>
85
+ </div>
86
+ <Slider value={value} onValueChange={setValue} max={100} step={10} />
87
+ </div>
88
+ );
89
+ },
90
+ };
91
+
92
+ export const Disabled: Story = {
93
+ args: {
94
+ defaultValue: [50],
95
+ max: 100,
96
+ step: 1,
97
+ disabled: true,
98
+ className: 'w-[200px]',
99
+ },
100
+ };
101
+
102
+ export const WithOnChangeEnd: Story = {
103
+ render: () => {
104
+ const [value, setValue] = useState([50]);
105
+ const [finalValue, setFinalValue] = useState([50]);
106
+ return (
107
+ <div className="grid w-full max-w-sm gap-4">
108
+ <div className="flex justify-between">
109
+ <Label>Drag to change</Label>
110
+ <span className="text-sm text-muted-foreground">Current: {value[0]}</span>
111
+ </div>
112
+ <Slider
113
+ value={value}
114
+ onValueChange={setValue}
115
+ onChangeEnd={setFinalValue}
116
+ max={100}
117
+ step={1}
118
+ />
119
+ <p className="text-sm text-muted-foreground">
120
+ Final value (on release): {finalValue[0]}
121
+ </p>
122
+ </div>
123
+ );
124
+ },
125
+ };
126
+
127
+ /**
128
+ * Compound Component Pattern
129
+ *
130
+ * Use the compound component pattern for full control over slider parts.
131
+ * Provides Slider.Track, Slider.Fill, and Slider.Thumb sub-components.
132
+ */
133
+ export const CompoundComponent: Story = {
134
+ render: () => {
135
+ const [value, setValue] = useState([50]);
136
+ return (
137
+ <div className="grid w-full max-w-sm gap-4">
138
+ <div className="flex justify-between">
139
+ <Label>Compound Component Pattern</Label>
140
+ <span className="text-sm text-muted-foreground">{value[0]}%</span>
141
+ </div>
142
+ <Slider value={value} onValueChange={setValue} max={100} step={1}>
143
+ <Slider.Track>
144
+ <Slider.Fill />
145
+ <Slider.Thumb />
146
+ </Slider.Track>
147
+ </Slider>
148
+ </div>
149
+ );
150
+ },
151
+ };
152
+
153
+ /**
154
+ * Compound Component with Output
155
+ *
156
+ * Use Slider.Output for an accessible output element that displays the current value.
157
+ */
158
+ export const WithOutput: Story = {
159
+ render: () => {
160
+ const [value, setValue] = useState([75]);
161
+ return (
162
+ <div className="grid w-full max-w-sm gap-4">
163
+ <div className="flex justify-between items-center">
164
+ <Label>Volume</Label>
165
+ <Slider.Output className="min-w-[3ch] text-right">
166
+ {({ state }) => `${state.values[0]}%`}
167
+ </Slider.Output>
168
+ </div>
169
+ <Slider value={value} onValueChange={setValue} max={100} step={1}>
170
+ <Slider.Track>
171
+ <Slider.Fill />
172
+ <Slider.Thumb />
173
+ </Slider.Track>
174
+ </Slider>
175
+ </div>
176
+ );
177
+ },
178
+ };
179
+
180
+ /**
181
+ * Custom Styled Compound
182
+ *
183
+ * Example of customizing individual slider parts with Tailwind classes.
184
+ */
185
+ export const CustomStyled: Story = {
186
+ render: () => {
187
+ const [value, setValue] = useState([60]);
188
+ return (
189
+ <div className="grid w-full max-w-sm gap-4">
190
+ <div className="flex justify-between">
191
+ <Label>Custom Styled</Label>
192
+ <span className="text-sm text-muted-foreground">{value[0]}</span>
193
+ </div>
194
+ <Slider value={value} onValueChange={setValue} max={100} step={1}>
195
+ <Slider.Track className="h-3 bg-muted">
196
+ <Slider.Fill className="bg-success" />
197
+ <Slider.Thumb className="h-6 w-6 border-success" />
198
+ </Slider.Track>
199
+ </Slider>
200
+ </div>
201
+ );
202
+ },
203
+ };
@@ -0,0 +1,142 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { Spinner } from '../spinner';
3
+ import { Button } from '../button';
4
+
5
+ const meta: Meta<typeof Spinner> = {
6
+ title: 'UI/Spinner',
7
+ component: Spinner,
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ tags: ['autodocs'],
12
+ argTypes: {
13
+ size: {
14
+ control: 'select',
15
+ options: ['sm', 'default', 'md', 'lg', 'xl'],
16
+ },
17
+ color: {
18
+ control: 'select',
19
+ options: ['default', 'primary', 'secondary', 'success', 'warning', 'danger', 'current'],
20
+ },
21
+ label: {
22
+ control: 'text',
23
+ },
24
+ },
25
+ };
26
+
27
+ export default meta;
28
+ type Story = StoryObj<typeof meta>;
29
+
30
+ export const Default: Story = {
31
+ args: {},
32
+ render: (args) => (
33
+ <div className="flex items-center gap-3">
34
+ <Spinner {...args} />
35
+ </div>
36
+ ),
37
+ };
38
+
39
+ export const AllSizes: Story = {
40
+ render: () => (
41
+ <div className="flex items-center gap-8">
42
+ <div className="flex flex-col items-center gap-2">
43
+ <Spinner size="sm" />
44
+ <span className="text-xs text-muted-foreground">Small</span>
45
+ </div>
46
+ <div className="flex flex-col items-center gap-2">
47
+ <Spinner size="md" />
48
+ <span className="text-xs text-muted-foreground">Medium</span>
49
+ </div>
50
+ <div className="flex flex-col items-center gap-2">
51
+ <Spinner size="lg" />
52
+ <span className="text-xs text-muted-foreground">Large</span>
53
+ </div>
54
+ <div className="flex flex-col items-center gap-2">
55
+ <Spinner size="xl" />
56
+ <span className="text-xs text-muted-foreground">Extra Large</span>
57
+ </div>
58
+ </div>
59
+ ),
60
+ };
61
+
62
+ export const AllColors: Story = {
63
+ render: () => (
64
+ <div className="flex items-center gap-8">
65
+ <div className="flex flex-col items-center gap-2">
66
+ <Spinner color="primary" />
67
+ <span className="text-xs text-muted-foreground">Primary</span>
68
+ </div>
69
+ <div className="flex flex-col items-center gap-2">
70
+ <Spinner color="current" />
71
+ <span className="text-xs text-muted-foreground">Current</span>
72
+ </div>
73
+ <div className="flex flex-col items-center gap-2">
74
+ <Spinner color="success" />
75
+ <span className="text-xs text-muted-foreground">Success</span>
76
+ </div>
77
+ <div className="flex flex-col items-center gap-2">
78
+ <Spinner color="warning" />
79
+ <span className="text-xs text-muted-foreground">Warning</span>
80
+ </div>
81
+ <div className="flex flex-col items-center gap-2">
82
+ <Spinner color="danger" />
83
+ <span className="text-xs text-muted-foreground">Danger</span>
84
+ </div>
85
+ </div>
86
+ ),
87
+ };
88
+
89
+ export const InheritColor: Story = {
90
+ render: () => (
91
+ <div className="flex items-center gap-6">
92
+ <div className="flex items-center gap-2 text-primary">
93
+ <Spinner color="current" size="sm" />
94
+ <span>Loading primary...</span>
95
+ </div>
96
+ <div className="flex items-center gap-2 text-success">
97
+ <Spinner color="current" size="sm" />
98
+ <span>Loading success...</span>
99
+ </div>
100
+ <div className="flex items-center gap-2 text-danger">
101
+ <Spinner color="current" size="sm" />
102
+ <span>Loading danger...</span>
103
+ </div>
104
+ </div>
105
+ ),
106
+ };
107
+
108
+ export const InButton: Story = {
109
+ render: () => (
110
+ <div className="flex gap-4">
111
+ <Button disabled>
112
+ <Spinner size="sm" color="current" />
113
+ Loading...
114
+ </Button>
115
+ <Button variant="secondary" disabled>
116
+ <Spinner size="sm" color="current" />
117
+ Processing
118
+ </Button>
119
+ <Button variant="destructive" disabled>
120
+ <Spinner size="sm" color="current" />
121
+ Deleting
122
+ </Button>
123
+ </div>
124
+ ),
125
+ };
126
+
127
+ export const FullPage: Story = {
128
+ render: () => (
129
+ <div className="flex flex-col items-center justify-center gap-4 min-h-[200px] w-[300px] border border-divider rounded-lg bg-surface">
130
+ <Spinner size="xl" color="primary" />
131
+ <span className="text-foreground/70">Loading content...</span>
132
+ </div>
133
+ ),
134
+ };
135
+
136
+ export const Inline: Story = {
137
+ render: () => (
138
+ <p className="text-foreground">
139
+ Please wait while we process your request <Spinner size="sm" color="current" className="inline-block ml-1" />
140
+ </p>
141
+ ),
142
+ };