@snowcone-app/ui 0.1.43 → 0.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.
- package/CHANGELOG.md +26 -0
- package/README.md +18 -4
- package/package.json +9 -5
- package/src/components/CanvasIsolationBoundary.tsx +202 -0
- package/src/components/LoadingOverlayPrism.tsx +251 -0
- package/src/composed/AddToCart.tsx +229 -0
- package/src/composed/ArtAlignment.tsx +703 -0
- package/src/composed/ArtSelector.tsx +290 -0
- package/src/composed/ArtworkCustomizer.tsx +212 -0
- package/src/composed/CanvasEditor.tsx +79 -0
- package/src/composed/ColorPicker.tsx +111 -0
- package/src/composed/CurrentSelectionDisplay.tsx +86 -0
- package/src/composed/HeroProductImage.tsx +1071 -0
- package/src/composed/Lightbox.index.ts +2 -0
- package/src/composed/Lightbox.tsx +230 -0
- package/src/composed/PlacementClipShapeSelector.tsx +88 -0
- package/src/composed/PlacementTabs.tsx +179 -0
- package/src/composed/ProductCard.tsx +298 -0
- package/src/composed/ProductGallery.tsx +54 -0
- package/src/composed/ProductImage.tsx +129 -0
- package/src/composed/ProductList.tsx +147 -0
- package/src/composed/ProductOptions.tsx +305 -0
- package/src/composed/RealtimeMockup.tsx +121 -0
- package/src/composed/TileCount.tsx +348 -0
- package/src/composed/carousels/HeroCarousel.tsx +240 -0
- package/src/composed/carousels/MobileProductCarousel.tsx +1002 -0
- package/src/composed/carousels/index.ts +11 -0
- package/src/composed/carousels/types.ts +58 -0
- package/src/composed/grids/MasonryGrid.tsx +238 -0
- package/src/composed/grids/index.ts +9 -0
- package/src/composed/search/CurrentRefinements.tsx +80 -0
- package/src/composed/search/Filters.tsx +49 -0
- package/src/composed/search/FiltersButton.tsx +57 -0
- package/src/composed/search/FiltersDrawer.tsx +375 -0
- package/src/composed/search/ProductGrid.tsx +118 -0
- package/src/composed/search/ProductHit.tsx +56 -0
- package/src/composed/search/SearchBox.tsx +109 -0
- package/src/composed/search/SearchProvider.tsx +136 -0
- package/src/composed/search/facetConfig.ts +16 -0
- package/src/composed/search/index.ts +22 -0
- package/src/composed/search/meilisearchAdapter.ts +20 -0
- package/src/composed/search/types.ts +22 -0
- package/src/composed/zoom/EnhancedImageViewer.tsx +505 -0
- package/src/composed/zoom/ResponsiveZoom.tsx +134 -0
- package/src/composed/zoom/ZoomOverlay.tsx +194 -0
- package/src/composed/zoom/index.ts +12 -0
- package/src/composed/zoom/types.ts +12 -0
- package/src/design-system/ColorPalette.tsx +126 -0
- package/src/design-system/ColorSwatch.tsx +49 -0
- package/src/design-system/DesignSystemPage.tsx +130 -0
- package/src/design-system/ThemeSwitcher.tsx +181 -0
- package/src/design-system/TypographyScale.tsx +106 -0
- package/src/design-system/index.ts +5 -0
- package/src/ecommerce/stories/HeroProductImage.stories.tsx +66 -0
- package/src/ecommerce/stories/PDPHeroGallery.stories.tsx +105 -0
- package/src/ecommerce/stories/PDPInfoPanel.stories.tsx +472 -0
- package/src/ecommerce/stories/PDPLayout.stories.tsx +365 -0
- package/src/hooks/useBrand.ts +41 -0
- package/src/hooks/useCanvasContext.ts +127 -0
- package/src/hooks/useDeviceDetection.ts +64 -0
- package/src/hooks/useFocusTrap.ts +70 -0
- package/src/hooks/useImagePreloader.ts +268 -0
- package/src/hooks/useImageTransition.ts +608 -0
- package/src/hooks/usePlacementsProcessor.ts +74 -0
- package/src/hooks/useProductGallery.ts +193 -0
- package/src/hooks/useProductPage.ts +467 -0
- package/src/hooks/useRenderGuard.ts +96 -0
- package/src/hooks/useScrollDirection.ts +196 -0
- package/src/hooks/viewport/index.ts +25 -0
- package/src/hooks/viewport/useContainerWidth.ts +59 -0
- package/src/hooks/viewport/useMediaQuery.ts +52 -0
- package/src/hooks/viewport/useResponsiveImageCap.ts +149 -0
- package/src/hooks/viewport/useViewportDimensions.ts +135 -0
- package/src/hooks/viewport/useWideMonitorMode.ts +150 -0
- package/src/hooks/visibility/index.ts +15 -0
- package/src/hooks/visibility/observerPool.ts +150 -0
- package/src/index.ts +240 -0
- package/src/layouts/hero-zoom/HeroShrinkLayout.tsx +209 -0
- package/src/layouts/hero-zoom/HeroZoomLayout.tsx +351 -0
- package/src/layouts/hero-zoom/index.ts +30 -0
- package/src/layouts/hero-zoom/stories/HeroZoomLayout.stories.tsx +350 -0
- package/src/layouts/hero-zoom/types.ts +113 -0
- package/src/layouts/hero-zoom/useHeroZoomScales.ts +156 -0
- package/src/layouts/index.ts +9 -0
- package/src/layouts/pdp/EdgeBlurBox.tsx +210 -0
- package/src/layouts/pdp/ImageBlurExtension.tsx +215 -0
- package/src/layouts/pdp/ImageEdgeBlur.tsx +215 -0
- package/src/layouts/pdp/PDPLayout.tsx +246 -0
- package/src/layouts/pdp/SimpleImageBlur.tsx +140 -0
- package/src/layouts/pdp/index.ts +40 -0
- package/src/lib/env.ts +15 -0
- package/src/lib/locale.ts +167 -0
- package/src/lib/router.tsx +46 -0
- package/src/lib/utils.ts +6 -0
- package/src/lightbox/README.md +77 -0
- package/src/next/index.tsx +26 -0
- package/src/patterns/MockupPriorityProvider.tsx +1014 -0
- package/src/patterns/Product.tsx +850 -0
- package/src/patterns/ProductPageProvider.tsx +224 -0
- package/src/patterns/RealtimeProvider.tsx +1162 -0
- package/src/patterns/ShopProvider.tsx +603 -0
- package/src/personalization/PersonalizationBridge.tsx +235 -0
- package/src/personalization/PersonalizationContext.ts +29 -0
- package/src/personalization/PersonalizationInputs.tsx +110 -0
- package/src/personalization/PersonalizationProvider.tsx +407 -0
- package/src/personalization/canvas-stub.d.ts +22 -0
- package/src/personalization/index.ts +43 -0
- package/src/personalization/types.ts +48 -0
- package/src/personalization/usePersonalization.ts +32 -0
- package/src/personalization/usePersonalizationShimmer.ts +159 -0
- package/src/personalization/utils.ts +59 -0
- package/src/primitives/BrandLogo.tsx +65 -0
- package/src/primitives/BrandName.tsx +51 -0
- package/src/primitives/Button.tsx +123 -0
- package/src/primitives/ColorSwatch.tsx +221 -0
- package/src/primitives/DragHintAnimation.tsx +190 -0
- package/src/primitives/EdgeSwipeGuards.tsx +60 -0
- package/src/primitives/FloatingActionGroup.tsx +176 -0
- package/src/primitives/ProductPrice.tsx +171 -0
- package/src/primitives/ProgressiveBlur.tsx +295 -0
- package/src/primitives/ThemeToggle.tsx +125 -0
- package/src/primitives/__tests__/story-coverage.test.ts +98 -0
- package/src/primitives/accordion.tsx +280 -0
- package/src/primitives/badge.tsx +137 -0
- package/src/primitives/card.tsx +61 -0
- package/src/primitives/checkbox.tsx +56 -0
- package/src/primitives/collapsible.tsx +51 -0
- package/src/primitives/drawer.tsx +828 -0
- package/src/primitives/dropdown-menu.tsx +197 -0
- package/src/primitives/fieldset.tsx +73 -0
- package/src/primitives/index.ts +138 -0
- package/src/primitives/input.tsx +91 -0
- package/src/primitives/kbd.tsx +130 -0
- package/src/primitives/label.tsx +20 -0
- package/src/primitives/link.tsx +182 -0
- package/src/primitives/popover.tsx +80 -0
- package/src/primitives/radio-group.tsx +79 -0
- package/src/primitives/scroll-fade.tsx +159 -0
- package/src/primitives/select.tsx +170 -0
- package/src/primitives/separator.tsx +25 -0
- package/src/primitives/slider.tsx +221 -0
- package/src/primitives/spinner.tsx +72 -0
- package/src/primitives/stories/Accordion.stories.tsx +121 -0
- package/src/primitives/stories/Badge.stories.tsx +221 -0
- package/src/primitives/stories/Button.stories.tsx +185 -0
- package/src/primitives/stories/Card.stories.tsx +171 -0
- package/src/primitives/stories/Checkbox.stories.tsx +214 -0
- package/src/primitives/stories/Collapsible.stories.tsx +230 -0
- package/src/primitives/stories/Drawer.stories.tsx +378 -0
- package/src/primitives/stories/DropdownMenu.stories.tsx +182 -0
- package/src/primitives/stories/Fieldset.stories.tsx +212 -0
- package/src/primitives/stories/Input.stories.tsx +172 -0
- package/src/primitives/stories/Kbd.stories.tsx +183 -0
- package/src/primitives/stories/Label.stories.tsx +98 -0
- package/src/primitives/stories/Link.stories.tsx +260 -0
- package/src/primitives/stories/Popover.stories.tsx +178 -0
- package/src/primitives/stories/RadioGroup.stories.tsx +205 -0
- package/src/primitives/stories/Select.stories.tsx +222 -0
- package/src/primitives/stories/Separator.stories.tsx +134 -0
- package/src/primitives/stories/Slider.stories.tsx +203 -0
- package/src/primitives/stories/Spinner.stories.tsx +142 -0
- package/src/primitives/stories/Surface.stories.tsx +257 -0
- package/src/primitives/stories/Switch.stories.tsx +131 -0
- package/src/primitives/stories/Tabs.stories.tsx +275 -0
- package/src/primitives/stories/TextField.stories.tsx +139 -0
- package/src/primitives/stories/Textarea.stories.tsx +148 -0
- package/src/primitives/stories/Tooltip.stories.tsx +119 -0
- package/src/primitives/surface.tsx +86 -0
- package/src/primitives/switch.tsx +35 -0
- package/src/primitives/tabs.tsx +206 -0
- package/src/primitives/text-field.tsx +84 -0
- package/src/primitives/textarea.tsx +50 -0
- package/src/primitives/tooltip.tsx +58 -0
- package/src/services/CanvasExportService.ts +518 -0
- package/src/styles/base.css +380 -0
- package/src/styles/defaults.css +280 -0
- package/src/styles/globals.css +1242 -0
- package/src/styles/index.css +17 -0
- package/src/styles/ne-themes.css +4740 -0
- package/src/styles/tailwind.css +11 -0
- package/src/styles/tokens.css +117 -0
- package/src/styles/utilities.css +188 -0
- package/src/themes/apply-theme.ts +449 -0
- package/src/themes/getThemeStyles.ts +454 -0
- package/src/themes/index.ts +48 -0
- package/src/themes/oklch-theme.ts +283 -0
- package/src/themes/presets.ts +989 -0
- package/src/themes/types.ts +386 -0
- package/src/themes/useTheme.tsx +450 -0
- package/src/utils/dev-warnings.ts +161 -0
- package/src/utils/devWarnings.ts +153 -0
- package/dist/styles.css +0 -1
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Kbd } from '../kbd';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Kbd> = {
|
|
5
|
+
title: 'UI/Kbd',
|
|
6
|
+
component: Kbd,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
argTypes: {
|
|
12
|
+
variant: {
|
|
13
|
+
control: 'select',
|
|
14
|
+
options: ['default', 'minimal', 'outline'],
|
|
15
|
+
description: 'Visual style of the keyboard key',
|
|
16
|
+
},
|
|
17
|
+
size: {
|
|
18
|
+
control: 'select',
|
|
19
|
+
options: ['sm', 'md', 'lg'],
|
|
20
|
+
description: 'Size of the keyboard key',
|
|
21
|
+
},
|
|
22
|
+
keys: {
|
|
23
|
+
control: 'text',
|
|
24
|
+
description: 'Keyboard key(s) to display. Can be a string like "cmd+K" or an array',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default meta;
|
|
30
|
+
type Story = StoryObj<typeof meta>;
|
|
31
|
+
|
|
32
|
+
export const Default: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
children: 'K',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const WithKeys: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
keys: 'cmd+K',
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const KeysArray: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
keys: ['cmd', 'shift', 'P'],
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const Variants: Story = {
|
|
51
|
+
render: () => (
|
|
52
|
+
<div className="flex items-center gap-4">
|
|
53
|
+
<div className="flex flex-col items-center gap-2">
|
|
54
|
+
<Kbd variant="default" keys="cmd+K" />
|
|
55
|
+
<span className="text-xs text-foreground/60">default</span>
|
|
56
|
+
</div>
|
|
57
|
+
<div className="flex flex-col items-center gap-2">
|
|
58
|
+
<Kbd variant="minimal" keys="cmd+K" />
|
|
59
|
+
<span className="text-xs text-foreground/60">minimal</span>
|
|
60
|
+
</div>
|
|
61
|
+
<div className="flex flex-col items-center gap-2">
|
|
62
|
+
<Kbd variant="outline" keys="cmd+K" />
|
|
63
|
+
<span className="text-xs text-foreground/60">outline</span>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const Sizes: Story = {
|
|
70
|
+
render: () => (
|
|
71
|
+
<div className="flex items-center gap-4">
|
|
72
|
+
<div className="flex flex-col items-center gap-2">
|
|
73
|
+
<Kbd size="sm" keys="cmd+K" />
|
|
74
|
+
<span className="text-xs text-foreground/60">sm</span>
|
|
75
|
+
</div>
|
|
76
|
+
<div className="flex flex-col items-center gap-2">
|
|
77
|
+
<Kbd size="md" keys="cmd+K" />
|
|
78
|
+
<span className="text-xs text-foreground/60">md</span>
|
|
79
|
+
</div>
|
|
80
|
+
<div className="flex flex-col items-center gap-2">
|
|
81
|
+
<Kbd size="lg" keys="cmd+K" />
|
|
82
|
+
<span className="text-xs text-foreground/60">lg</span>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
),
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const SpecialKeys: Story = {
|
|
89
|
+
render: () => (
|
|
90
|
+
<div className="flex flex-wrap items-center gap-3">
|
|
91
|
+
<Kbd keys="cmd" />
|
|
92
|
+
<Kbd keys="ctrl" />
|
|
93
|
+
<Kbd keys="alt" />
|
|
94
|
+
<Kbd keys="shift" />
|
|
95
|
+
<Kbd keys="enter" />
|
|
96
|
+
<Kbd keys="backspace" />
|
|
97
|
+
<Kbd keys="escape" />
|
|
98
|
+
<Kbd keys="tab" />
|
|
99
|
+
<Kbd keys="space" />
|
|
100
|
+
<Kbd keys="up" />
|
|
101
|
+
<Kbd keys="down" />
|
|
102
|
+
<Kbd keys="left" />
|
|
103
|
+
<Kbd keys="right" />
|
|
104
|
+
</div>
|
|
105
|
+
),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export const CommonShortcuts: Story = {
|
|
109
|
+
render: () => (
|
|
110
|
+
<div className="space-y-3">
|
|
111
|
+
<div className="flex items-center justify-between w-[250px]">
|
|
112
|
+
<span className="text-sm">Save</span>
|
|
113
|
+
<Kbd keys="cmd+S" />
|
|
114
|
+
</div>
|
|
115
|
+
<div className="flex items-center justify-between w-[250px]">
|
|
116
|
+
<span className="text-sm">Undo</span>
|
|
117
|
+
<Kbd keys="cmd+Z" />
|
|
118
|
+
</div>
|
|
119
|
+
<div className="flex items-center justify-between w-[250px]">
|
|
120
|
+
<span className="text-sm">Redo</span>
|
|
121
|
+
<Kbd keys="cmd+shift+Z" />
|
|
122
|
+
</div>
|
|
123
|
+
<div className="flex items-center justify-between w-[250px]">
|
|
124
|
+
<span className="text-sm">Copy</span>
|
|
125
|
+
<Kbd keys="cmd+C" />
|
|
126
|
+
</div>
|
|
127
|
+
<div className="flex items-center justify-between w-[250px]">
|
|
128
|
+
<span className="text-sm">Paste</span>
|
|
129
|
+
<Kbd keys="cmd+V" />
|
|
130
|
+
</div>
|
|
131
|
+
<div className="flex items-center justify-between w-[250px]">
|
|
132
|
+
<span className="text-sm">Select All</span>
|
|
133
|
+
<Kbd keys="cmd+A" />
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
),
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const SingleLetters: Story = {
|
|
140
|
+
render: () => (
|
|
141
|
+
<div className="flex items-center gap-2">
|
|
142
|
+
<Kbd>A</Kbd>
|
|
143
|
+
<Kbd>B</Kbd>
|
|
144
|
+
<Kbd>C</Kbd>
|
|
145
|
+
<Kbd>1</Kbd>
|
|
146
|
+
<Kbd>2</Kbd>
|
|
147
|
+
<Kbd>3</Kbd>
|
|
148
|
+
</div>
|
|
149
|
+
),
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export const InlineWithText: Story = {
|
|
153
|
+
render: () => (
|
|
154
|
+
<p className="text-sm">
|
|
155
|
+
Press <Kbd variant="minimal" size="sm">cmd</Kbd> + <Kbd variant="minimal" size="sm">K</Kbd> to
|
|
156
|
+
open the command palette, or <Kbd variant="minimal" size="sm">Esc</Kbd> to close it.
|
|
157
|
+
</p>
|
|
158
|
+
),
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export const MenuItemExample: Story = {
|
|
162
|
+
render: () => (
|
|
163
|
+
<div className="w-[200px] rounded-lg border border-divider bg-surface p-1">
|
|
164
|
+
<div className="flex items-center justify-between rounded-md px-3 py-2 hover:bg-muted cursor-pointer">
|
|
165
|
+
<span className="text-sm">New File</span>
|
|
166
|
+
<Kbd variant="minimal" size="sm" keys="cmd+N" />
|
|
167
|
+
</div>
|
|
168
|
+
<div className="flex items-center justify-between rounded-md px-3 py-2 hover:bg-muted cursor-pointer">
|
|
169
|
+
<span className="text-sm">Open</span>
|
|
170
|
+
<Kbd variant="minimal" size="sm" keys="cmd+O" />
|
|
171
|
+
</div>
|
|
172
|
+
<div className="flex items-center justify-between rounded-md px-3 py-2 hover:bg-muted cursor-pointer">
|
|
173
|
+
<span className="text-sm">Save</span>
|
|
174
|
+
<Kbd variant="minimal" size="sm" keys="cmd+S" />
|
|
175
|
+
</div>
|
|
176
|
+
<div className="h-px bg-divider my-1" />
|
|
177
|
+
<div className="flex items-center justify-between rounded-md px-3 py-2 hover:bg-muted cursor-pointer">
|
|
178
|
+
<span className="text-sm">Close</span>
|
|
179
|
+
<Kbd variant="minimal" size="sm" keys="cmd+W" />
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
),
|
|
183
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Label } from '../label';
|
|
3
|
+
|
|
4
|
+
const meta: Meta<typeof Label> = {
|
|
5
|
+
title: 'UI/Label',
|
|
6
|
+
component: Label,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'centered',
|
|
9
|
+
},
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
argTypes: {
|
|
12
|
+
htmlFor: {
|
|
13
|
+
control: 'text',
|
|
14
|
+
description: 'ID of the form element this label is for',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
type Story = StoryObj<typeof meta>;
|
|
21
|
+
|
|
22
|
+
export const Default: Story = {
|
|
23
|
+
args: {
|
|
24
|
+
children: 'Email Address',
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const WithInput: Story = {
|
|
29
|
+
render: () => (
|
|
30
|
+
<div className="grid w-full max-w-sm items-center gap-1.5">
|
|
31
|
+
<Label htmlFor="email">Email</Label>
|
|
32
|
+
<input
|
|
33
|
+
type="email"
|
|
34
|
+
id="email"
|
|
35
|
+
placeholder="Enter your email"
|
|
36
|
+
className="flex h-9 w-full rounded-md border border-divider bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus"
|
|
37
|
+
/>
|
|
38
|
+
</div>
|
|
39
|
+
),
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const Required: Story = {
|
|
43
|
+
render: () => (
|
|
44
|
+
<div className="grid w-full max-w-sm items-center gap-1.5">
|
|
45
|
+
<Label htmlFor="name">
|
|
46
|
+
Name <span className="text-destructive">*</span>
|
|
47
|
+
</Label>
|
|
48
|
+
<input
|
|
49
|
+
type="text"
|
|
50
|
+
id="name"
|
|
51
|
+
placeholder="Enter your name"
|
|
52
|
+
className="flex h-9 w-full rounded-md border border-divider bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus"
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
55
|
+
),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const Disabled: Story = {
|
|
59
|
+
render: () => (
|
|
60
|
+
<div className="grid w-full max-w-sm items-center gap-1.5">
|
|
61
|
+
<Label htmlFor="disabled" className="peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
|
|
62
|
+
Disabled Field
|
|
63
|
+
</Label>
|
|
64
|
+
<input
|
|
65
|
+
type="text"
|
|
66
|
+
id="disabled"
|
|
67
|
+
disabled
|
|
68
|
+
placeholder="Cannot edit"
|
|
69
|
+
className="peer flex h-9 w-full rounded-md border border-divider bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50"
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const FormExample: Story = {
|
|
76
|
+
render: () => (
|
|
77
|
+
<form className="w-full max-w-sm space-y-4">
|
|
78
|
+
<div className="space-y-1.5">
|
|
79
|
+
<Label htmlFor="username">Username</Label>
|
|
80
|
+
<input
|
|
81
|
+
type="text"
|
|
82
|
+
id="username"
|
|
83
|
+
placeholder="johndoe"
|
|
84
|
+
className="flex h-9 w-full rounded-md border border-divider bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus"
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
87
|
+
<div className="space-y-1.5">
|
|
88
|
+
<Label htmlFor="password">Password</Label>
|
|
89
|
+
<input
|
|
90
|
+
type="password"
|
|
91
|
+
id="password"
|
|
92
|
+
placeholder="Enter password"
|
|
93
|
+
className="flex h-9 w-full rounded-md border border-divider bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus"
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
</form>
|
|
97
|
+
),
|
|
98
|
+
};
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Link } from '../link';
|
|
3
|
+
import { Icon } from '@iconify/react';
|
|
4
|
+
import { Card, CardContent, CardHeader, CardTitle } from '../card';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Link> = {
|
|
7
|
+
title: 'UI/Link',
|
|
8
|
+
component: Link,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
},
|
|
12
|
+
tags: ['autodocs'],
|
|
13
|
+
argTypes: {
|
|
14
|
+
color: {
|
|
15
|
+
control: 'select',
|
|
16
|
+
options: ['default', 'primary', 'secondary', 'success', 'warning', 'danger'],
|
|
17
|
+
description: 'Color variant of the link',
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
control: 'select',
|
|
21
|
+
options: ['sm', 'md', 'lg'],
|
|
22
|
+
description: 'Size of the link text',
|
|
23
|
+
},
|
|
24
|
+
underline: {
|
|
25
|
+
control: 'select',
|
|
26
|
+
options: ['none', 'hover', 'always'],
|
|
27
|
+
description: 'Underline behavior',
|
|
28
|
+
},
|
|
29
|
+
underlineOffset: {
|
|
30
|
+
control: 'select',
|
|
31
|
+
options: [1, 2, 3],
|
|
32
|
+
description: 'Space between text and underline',
|
|
33
|
+
},
|
|
34
|
+
isExternal: {
|
|
35
|
+
control: 'boolean',
|
|
36
|
+
description: 'Shows external link icon and opens in new tab',
|
|
37
|
+
},
|
|
38
|
+
isBlock: {
|
|
39
|
+
control: 'boolean',
|
|
40
|
+
description: 'Full width block style',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default meta;
|
|
46
|
+
type Story = StoryObj<typeof meta>;
|
|
47
|
+
|
|
48
|
+
export const Default: Story = {
|
|
49
|
+
args: {
|
|
50
|
+
href: '#',
|
|
51
|
+
children: 'Click me',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const Colors: Story = {
|
|
56
|
+
render: () => (
|
|
57
|
+
<div className="flex flex-wrap items-center gap-4">
|
|
58
|
+
<Link href="#" color="default">Default</Link>
|
|
59
|
+
<Link href="#" color="primary">Primary</Link>
|
|
60
|
+
<Link href="#" color="secondary">Secondary</Link>
|
|
61
|
+
<Link href="#" color="success">Success</Link>
|
|
62
|
+
<Link href="#" color="warning">Warning</Link>
|
|
63
|
+
<Link href="#" color="danger">Danger</Link>
|
|
64
|
+
</div>
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const Sizes: Story = {
|
|
69
|
+
render: () => (
|
|
70
|
+
<div className="flex items-center gap-4">
|
|
71
|
+
<Link href="#" size="sm">Small</Link>
|
|
72
|
+
<Link href="#" size="md">Medium</Link>
|
|
73
|
+
<Link href="#" size="lg">Large</Link>
|
|
74
|
+
</div>
|
|
75
|
+
),
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const UnderlineVariants: Story = {
|
|
79
|
+
render: () => (
|
|
80
|
+
<div className="flex flex-col gap-4">
|
|
81
|
+
<div className="flex items-center gap-2">
|
|
82
|
+
<span className="w-24 text-sm text-foreground/60">hover:</span>
|
|
83
|
+
<Link href="#" underline="hover">Underline on hover</Link>
|
|
84
|
+
</div>
|
|
85
|
+
<div className="flex items-center gap-2">
|
|
86
|
+
<span className="w-24 text-sm text-foreground/60">always:</span>
|
|
87
|
+
<Link href="#" underline="always">Always underlined</Link>
|
|
88
|
+
</div>
|
|
89
|
+
<div className="flex items-center gap-2">
|
|
90
|
+
<span className="w-24 text-sm text-foreground/60">none:</span>
|
|
91
|
+
<Link href="#" underline="none">No underline</Link>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
),
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export const UnderlineOffset: Story = {
|
|
98
|
+
render: () => (
|
|
99
|
+
<div className="flex flex-col gap-4">
|
|
100
|
+
<div className="flex items-center gap-2">
|
|
101
|
+
<span className="w-24 text-sm text-foreground/60">offset 1:</span>
|
|
102
|
+
<Link href="#" underline="always" underlineOffset={1}>Default offset</Link>
|
|
103
|
+
</div>
|
|
104
|
+
<div className="flex items-center gap-2">
|
|
105
|
+
<span className="w-24 text-sm text-foreground/60">offset 2:</span>
|
|
106
|
+
<Link href="#" underline="always" underlineOffset={2}>Medium offset</Link>
|
|
107
|
+
</div>
|
|
108
|
+
<div className="flex items-center gap-2">
|
|
109
|
+
<span className="w-24 text-sm text-foreground/60">offset 3:</span>
|
|
110
|
+
<Link href="#" underline="always" underlineOffset={3}>Large offset</Link>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
),
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const External: Story = {
|
|
117
|
+
render: () => (
|
|
118
|
+
<div className="flex flex-col gap-3">
|
|
119
|
+
<Link href="https://example.com" isExternal>
|
|
120
|
+
External Link
|
|
121
|
+
</Link>
|
|
122
|
+
<Link href="https://github.com" isExternal color="secondary">
|
|
123
|
+
GitHub
|
|
124
|
+
</Link>
|
|
125
|
+
<Link href="https://google.com" isExternal size="lg">
|
|
126
|
+
Large External Link
|
|
127
|
+
</Link>
|
|
128
|
+
</div>
|
|
129
|
+
),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const WithCustomIcon: Story = {
|
|
133
|
+
render: () => (
|
|
134
|
+
<div className="flex flex-col gap-3">
|
|
135
|
+
<Link href="#" className="gap-2">
|
|
136
|
+
<Icon icon="gravity-ui:envelope" className="size-4" />
|
|
137
|
+
Email Us
|
|
138
|
+
</Link>
|
|
139
|
+
<Link href="#" className="gap-2">
|
|
140
|
+
<Icon icon="gravity-ui:smartphone" className="size-4" />
|
|
141
|
+
Call Us
|
|
142
|
+
</Link>
|
|
143
|
+
<Link href="#" className="gap-2">
|
|
144
|
+
Download
|
|
145
|
+
<Icon icon="gravity-ui:arrow-down-to-line" className="size-4" />
|
|
146
|
+
</Link>
|
|
147
|
+
</div>
|
|
148
|
+
),
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
export const Block: Story = {
|
|
153
|
+
render: () => (
|
|
154
|
+
<div className="w-[250px] space-y-1">
|
|
155
|
+
<Link href="#" isBlock>Dashboard</Link>
|
|
156
|
+
<Link href="#" isBlock>Settings</Link>
|
|
157
|
+
<Link href="#" isBlock>Profile</Link>
|
|
158
|
+
<Link href="#" isBlock color="danger">Logout</Link>
|
|
159
|
+
</div>
|
|
160
|
+
),
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export const InParagraph: Story = {
|
|
164
|
+
render: () => (
|
|
165
|
+
<p className="max-w-md text-foreground/80">
|
|
166
|
+
Learn more about our <Link href="#">privacy policy</Link> and{' '}
|
|
167
|
+
<Link href="#">terms of service</Link>. For questions, visit our{' '}
|
|
168
|
+
<Link href="https://example.com" isExternal>help center</Link>.
|
|
169
|
+
</p>
|
|
170
|
+
),
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
export const Navigation: Story = {
|
|
174
|
+
render: () => (
|
|
175
|
+
<nav className="flex items-center gap-6">
|
|
176
|
+
<Link href="#" underline="none" color="default">Home</Link>
|
|
177
|
+
<Link href="#" underline="none" color="default">Products</Link>
|
|
178
|
+
<Link href="#" underline="none" color="default">About</Link>
|
|
179
|
+
<Link href="#" underline="none" color="default">Contact</Link>
|
|
180
|
+
</nav>
|
|
181
|
+
),
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
export const Footer: Story = {
|
|
185
|
+
render: () => (
|
|
186
|
+
<footer className="flex flex-col gap-4 text-sm">
|
|
187
|
+
<div className="flex gap-4">
|
|
188
|
+
<Link href="#" color="default" size="sm">Privacy</Link>
|
|
189
|
+
<Link href="#" color="default" size="sm">Terms</Link>
|
|
190
|
+
<Link href="#" color="default" size="sm">Cookies</Link>
|
|
191
|
+
</div>
|
|
192
|
+
<div className="flex gap-4">
|
|
193
|
+
<Link href="https://twitter.com" isExternal color="default" size="sm">Twitter</Link>
|
|
194
|
+
<Link href="https://github.com" isExternal color="default" size="sm">GitHub</Link>
|
|
195
|
+
<Link href="https://discord.com" isExternal color="default" size="sm">Discord</Link>
|
|
196
|
+
</div>
|
|
197
|
+
</footer>
|
|
198
|
+
),
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export const OnCard: Story = {
|
|
202
|
+
render: () => (
|
|
203
|
+
<Card className="w-[350px]">
|
|
204
|
+
<CardHeader>
|
|
205
|
+
<CardTitle>Resources</CardTitle>
|
|
206
|
+
</CardHeader>
|
|
207
|
+
<CardContent className="space-y-2">
|
|
208
|
+
<Link href="#" isBlock>
|
|
209
|
+
<Icon icon="gravity-ui:book-open" className="size-4" />
|
|
210
|
+
Documentation
|
|
211
|
+
</Link>
|
|
212
|
+
<Link href="#" isBlock>
|
|
213
|
+
<Icon icon="gravity-ui:code" className="size-4" />
|
|
214
|
+
API Reference
|
|
215
|
+
</Link>
|
|
216
|
+
<Link href="https://github.com" isExternal isBlock>
|
|
217
|
+
<Icon icon="gravity-ui:logo-github" className="size-4" />
|
|
218
|
+
Source Code
|
|
219
|
+
</Link>
|
|
220
|
+
</CardContent>
|
|
221
|
+
</Card>
|
|
222
|
+
),
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
export const AllCombinations: Story = {
|
|
226
|
+
render: () => (
|
|
227
|
+
<div className="space-y-6">
|
|
228
|
+
<div>
|
|
229
|
+
<h3 className="text-sm mb-2 font-label">Colors with Hover Underline</h3>
|
|
230
|
+
<div className="flex flex-wrap gap-4">
|
|
231
|
+
<Link href="#" color="default">Default</Link>
|
|
232
|
+
<Link href="#" color="primary">Primary</Link>
|
|
233
|
+
<Link href="#" color="secondary">Secondary</Link>
|
|
234
|
+
<Link href="#" color="success">Success</Link>
|
|
235
|
+
<Link href="#" color="warning">Warning</Link>
|
|
236
|
+
<Link href="#" color="danger">Danger</Link>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
<div>
|
|
240
|
+
<h3 className="text-sm mb-2 font-label">Colors with Always Underline</h3>
|
|
241
|
+
<div className="flex flex-wrap gap-4">
|
|
242
|
+
<Link href="#" color="default" underline="always">Default</Link>
|
|
243
|
+
<Link href="#" color="primary" underline="always">Primary</Link>
|
|
244
|
+
<Link href="#" color="secondary" underline="always">Secondary</Link>
|
|
245
|
+
<Link href="#" color="success" underline="always">Success</Link>
|
|
246
|
+
<Link href="#" color="warning" underline="always">Warning</Link>
|
|
247
|
+
<Link href="#" color="danger" underline="always">Danger</Link>
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
<div>
|
|
251
|
+
<h3 className="text-sm mb-2 font-label">All Sizes</h3>
|
|
252
|
+
<div className="flex items-end gap-4">
|
|
253
|
+
<Link href="#" size="sm">Small</Link>
|
|
254
|
+
<Link href="#" size="md">Medium</Link>
|
|
255
|
+
<Link href="#" size="lg">Large</Link>
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
),
|
|
260
|
+
};
|