sonance-brand-mcp 1.2.5 → 1.3.2
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/dist/assets/api/sonance-analyze/route.ts +1116 -0
- package/dist/assets/api/sonance-assets/route.ts +113 -0
- package/dist/assets/api/sonance-components/route.ts +41 -0
- package/dist/assets/api/sonance-inject-id/route.ts +363 -0
- package/dist/assets/api/sonance-save-logo/route.ts +426 -0
- package/dist/assets/api/sonance-theme/route.ts +106 -0
- package/dist/assets/brand-system.ts +1265 -0
- package/dist/assets/components/accordion.stories.tsx +26 -26
- package/dist/assets/components/accordion.tsx +3 -3
- package/dist/assets/components/alert-dialog.stories.tsx +142 -0
- package/dist/assets/components/alert-dialog.tsx +143 -0
- package/dist/assets/components/alert.stories.tsx +3 -3
- package/dist/assets/components/alert.tsx +4 -3
- package/dist/assets/components/aspect-ratio.stories.tsx +70 -0
- package/dist/assets/components/aspect-ratio.tsx +8 -0
- package/dist/assets/components/autocomplete.stories.tsx +9 -9
- package/dist/assets/components/autocomplete.tsx +3 -3
- package/dist/assets/components/avatar.stories.tsx +5 -5
- package/dist/assets/components/avatar.tsx +67 -23
- package/dist/assets/components/badge.stories.tsx +10 -10
- package/dist/assets/components/badge.tsx +3 -3
- package/dist/assets/components/breadcrumbs.stories.tsx +7 -7
- package/dist/assets/components/breadcrumbs.tsx +13 -8
- package/dist/assets/components/button.stories.tsx +74 -74
- package/dist/assets/components/button.tsx +2 -0
- package/dist/assets/components/calendar.stories.tsx +11 -11
- package/dist/assets/components/calendar.tsx +4 -4
- package/dist/assets/components/card.stories.tsx +22 -22
- package/dist/assets/components/card.tsx +7 -3
- package/dist/assets/components/carousel.stories.tsx +158 -0
- package/dist/assets/components/carousel.tsx +264 -0
- package/dist/assets/components/chart.stories.tsx +376 -0
- package/dist/assets/components/chart.tsx +384 -0
- package/dist/assets/components/checkbox-group.stories.tsx +6 -6
- package/dist/assets/components/checkbox-group.tsx +3 -3
- package/dist/assets/components/checkbox.stories.tsx +23 -20
- package/dist/assets/components/checkbox.tsx +13 -6
- package/dist/assets/components/code.stories.tsx +24 -24
- package/dist/assets/components/code.tsx +22 -27
- package/dist/assets/components/collapsible.stories.tsx +128 -0
- package/dist/assets/components/collapsible.tsx +10 -0
- package/dist/assets/components/command.stories.tsx +183 -0
- package/dist/assets/components/command.tsx +171 -0
- package/dist/assets/components/context-menu.stories.tsx +159 -0
- package/dist/assets/components/context-menu.tsx +214 -0
- package/dist/assets/components/date-input.stories.tsx +9 -9
- package/dist/assets/components/date-input.tsx +2 -2
- package/dist/assets/components/date-picker.stories.tsx +9 -9
- package/dist/assets/components/date-picker.tsx +3 -3
- package/dist/assets/components/date-range-picker.stories.tsx +12 -12
- package/dist/assets/components/date-range-picker.tsx +3 -3
- package/dist/assets/components/dialog.stories.tsx +40 -40
- package/dist/assets/components/dialog.tsx +8 -12
- package/dist/assets/components/divider.stories.tsx +30 -30
- package/dist/assets/components/divider.tsx +34 -35
- package/dist/assets/components/drawer.stories.tsx +32 -31
- package/dist/assets/components/drawer.tsx +7 -6
- package/dist/assets/components/dropdown-menu.tsx +213 -0
- package/dist/assets/components/dropdown.stories.tsx +12 -12
- package/dist/assets/components/dropdown.tsx +5 -5
- package/dist/assets/components/form.stories.tsx +30 -29
- package/dist/assets/components/form.tsx +5 -5
- package/dist/assets/components/hover-card.stories.tsx +115 -0
- package/dist/assets/components/hover-card.tsx +35 -0
- package/dist/assets/components/image.stories.tsx +48 -25
- package/dist/assets/components/image.tsx +8 -5
- package/dist/assets/components/input-otp.stories.tsx +15 -15
- package/dist/assets/components/input-otp.tsx +5 -5
- package/dist/assets/components/input.stories.tsx +30 -25
- package/dist/assets/components/input.tsx +7 -4
- package/dist/assets/components/kbd.stories.tsx +34 -34
- package/dist/assets/components/kbd.tsx +9 -9
- package/dist/assets/components/link.stories.tsx +36 -36
- package/dist/assets/components/link.tsx +4 -0
- package/dist/assets/components/listbox.stories.tsx +5 -5
- package/dist/assets/components/listbox.tsx +4 -4
- package/dist/assets/components/menubar.stories.tsx +208 -0
- package/dist/assets/components/menubar.tsx +247 -0
- package/dist/assets/components/navbar.stories.tsx +24 -24
- package/dist/assets/components/navbar.tsx +8 -14
- package/dist/assets/components/navigation-menu.stories.tsx +239 -0
- package/dist/assets/components/navigation-menu.tsx +135 -0
- package/dist/assets/components/number-input.stories.tsx +11 -11
- package/dist/assets/components/number-input.tsx +3 -3
- package/dist/assets/components/pagination.stories.tsx +13 -13
- package/dist/assets/components/pagination.tsx +6 -6
- package/dist/assets/components/popover.stories.tsx +35 -35
- package/dist/assets/components/popover.tsx +98 -15
- package/dist/assets/components/progress.stories.tsx +5 -5
- package/dist/assets/components/progress.tsx +5 -5
- package/dist/assets/components/radio-group.stories.tsx +7 -7
- package/dist/assets/components/radio-group.tsx +3 -3
- package/dist/assets/components/range-calendar.stories.tsx +18 -18
- package/dist/assets/components/range-calendar.tsx +3 -3
- package/dist/assets/components/resizable.stories.tsx +197 -0
- package/dist/assets/components/resizable.tsx +47 -0
- package/dist/assets/components/scroll-area.stories.tsx +123 -0
- package/dist/assets/components/scroll-area.tsx +48 -0
- package/dist/assets/components/scroll-shadow.stories.tsx +17 -17
- package/dist/assets/components/scroll-shadow.tsx +31 -9
- package/dist/assets/components/select.stories.tsx +20 -19
- package/dist/assets/components/select.tsx +10 -6
- package/dist/assets/components/separator.tsx +32 -0
- package/dist/assets/components/sheet.tsx +137 -0
- package/dist/assets/components/sidebar.stories.tsx +351 -0
- package/dist/assets/components/sidebar.tsx +757 -0
- package/dist/assets/components/skeleton.stories.tsx +3 -3
- package/dist/assets/components/skeleton.tsx +2 -2
- package/dist/assets/components/slider.stories.tsx +6 -6
- package/dist/assets/components/slider.tsx +3 -3
- package/dist/assets/components/spacer.stories.tsx +11 -11
- package/dist/assets/components/spacer.tsx +2 -2
- package/dist/assets/components/spinner.stories.tsx +8 -8
- package/dist/assets/components/spinner.tsx +5 -5
- package/dist/assets/components/switch.stories.tsx +24 -20
- package/dist/assets/components/switch.tsx +14 -6
- package/dist/assets/components/table.stories.tsx +7 -7
- package/dist/assets/components/table.tsx +8 -8
- package/dist/assets/components/tabs.stories.tsx +37 -37
- package/dist/assets/components/tabs.tsx +3 -3
- package/dist/assets/components/textarea.stories.tsx +13 -12
- package/dist/assets/components/textarea.tsx +3 -3
- package/dist/assets/components/theme-toggle.stories.tsx +31 -30
- package/dist/assets/components/theme-toggle.tsx +2 -2
- package/dist/assets/components/time-input.stories.tsx +16 -16
- package/dist/assets/components/time-input.tsx +2 -2
- package/dist/assets/components/toast.stories.tsx +8 -5
- package/dist/assets/components/toast.tsx +6 -6
- package/dist/assets/components/toggle-group.stories.tsx +153 -0
- package/dist/assets/components/toggle-group.tsx +61 -0
- package/dist/assets/components/toggle.stories.tsx +77 -0
- package/dist/assets/components/toggle.tsx +46 -0
- package/dist/assets/components/tooltip.stories.tsx +49 -27
- package/dist/assets/components/tooltip.tsx +23 -90
- package/dist/assets/components/user.stories.tsx +23 -23
- package/dist/assets/components/user.tsx +7 -4
- package/dist/assets/dev-tools/SonanceDevTools.tsx +4201 -0
- package/dist/assets/dev-tools/index.ts +10 -0
- package/dist/assets/globals.css +39 -0
- package/dist/assets/logos/40th-anniversary/Sonance_40_Logo_CMYK_BEAM_BLUE_40_AND_BEAM_DARK.png +0 -0
- package/dist/assets/logos/Sonance logo dark mode.png +0 -0
- package/dist/assets/logos/Sonance logo light mode.png +0 -0
- package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_2C_Light_RGB_05162025.png +0 -0
- package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_3C_Dark_RGB_05162025.png +0 -0
- package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_White_RGB_05162025.png +0 -0
- package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Dark_RGB.png +0 -0
- package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Light_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_Black_CMYK.png +0 -0
- package/dist/assets/logos/james/James_Logo_Black_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_LtGray_CMYK.png +0 -0
- package/dist/assets/logos/james/James_Logo_LtGray_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_Polished_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_Reverse_CMYK.png +0 -0
- package/dist/assets/logos/james/James_Logo_Reverse_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_White_CMYK.png +0 -0
- package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Dark_RGB.png +0 -0
- package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Light_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Dark_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Light_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Reverse_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_Black_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_2C_Dark_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_2C_Light_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_2C_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_Black_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_Grayscale_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Dark_CMYK.png +0 -0
- package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Light_CMYK.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Dark_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Light_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Black_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Grayscale_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Dark.png +0 -0
- package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Light.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Dark.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Light.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Dark.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Light.png +0 -0
- package/dist/assets/logos/trufig/TrufigLogo_Black.png +0 -0
- package/dist/assets/logos/trufig/TrufigLogo_Light.png +0 -0
- package/dist/assets/logos/trufig/TrufigWatermark_Black.png +0 -0
- package/dist/assets/logos/trufig/TrufigWatermark_Light.png +0 -0
- package/dist/assets/styles/brand-overrides.css +37 -0
- package/dist/index.js +2055 -15
- package/package.json +1 -1
|
@@ -41,8 +41,8 @@ type Story = StoryObj<typeof meta>;
|
|
|
41
41
|
|
|
42
42
|
const sampleContent = Array.from({ length: 20 }, (_, i) => (
|
|
43
43
|
<div key={i} className="p-4 border-b border-border">
|
|
44
|
-
<h4 className="font-medium">Item {i + 1}</h4>
|
|
45
|
-
<p className="text-sm text-foreground-muted">
|
|
44
|
+
<h4 id="h4-item-i-1" className="font-medium">Item {i + 1}</h4>
|
|
45
|
+
<p id="p-this-is-sample-conte" className="text-sm text-foreground-muted">
|
|
46
46
|
This is sample content for item {i + 1}. Scroll to see the shadow effect.
|
|
47
47
|
</p>
|
|
48
48
|
</div>
|
|
@@ -53,8 +53,8 @@ const horizontalItems = Array.from({ length: 15 }, (_, i) => (
|
|
|
53
53
|
key={i}
|
|
54
54
|
className="flex-shrink-0 w-48 h-32 p-4 border border-border rounded-sm bg-card"
|
|
55
55
|
>
|
|
56
|
-
<h4 className="font-medium">Card {i + 1}</h4>
|
|
57
|
-
<p className="text-sm text-foreground-muted">Scroll horizontally</p>
|
|
56
|
+
<h4 id="h4-card-i-1" className="font-medium">Card {i + 1}</h4>
|
|
57
|
+
<p id="p-scroll-horizontally" className="text-sm text-foreground-muted">Scroll horizontally</p>
|
|
58
58
|
</div>
|
|
59
59
|
));
|
|
60
60
|
|
|
@@ -141,7 +141,7 @@ export const LargeShadow: Story = {
|
|
|
141
141
|
export const HiddenScrollbar: Story = {
|
|
142
142
|
render: () => (
|
|
143
143
|
<div className="space-y-4">
|
|
144
|
-
<p className="text-sm text-foreground-muted">
|
|
144
|
+
<p id="hidden-scrollbar-p-scrollbar-is-hidden-" className="text-sm text-foreground-muted">
|
|
145
145
|
Scrollbar is hidden but scrolling still works
|
|
146
146
|
</p>
|
|
147
147
|
<ScrollShadow
|
|
@@ -171,19 +171,19 @@ export const ProductListExample: Story = {
|
|
|
171
171
|
];
|
|
172
172
|
|
|
173
173
|
return (
|
|
174
|
-
<div className="w-80 border border-border rounded-sm">
|
|
174
|
+
<div data-sonance-name="scroll-shadow.stories" className="w-80 border border-border rounded-sm">
|
|
175
175
|
<div className="p-4 border-b border-border">
|
|
176
|
-
<h3 className="font-medium">Products ({products.length})</h3>
|
|
176
|
+
<h3 id="product-list-example-h3-products-productslen" className="font-medium">Products ({products.length})</h3>
|
|
177
177
|
</div>
|
|
178
178
|
<ScrollShadow className="h-64">
|
|
179
179
|
{products.map((product, i) => (
|
|
180
180
|
<div key={i} className="p-4 border-b border-border hover:bg-secondary-hover transition-colors cursor-pointer">
|
|
181
181
|
<div className="flex justify-between items-start">
|
|
182
182
|
<div>
|
|
183
|
-
<h4 className="font-medium text-sm">{product.name}</h4>
|
|
184
|
-
<p className="text-xs text-foreground-muted">{product.category}</p>
|
|
183
|
+
<h4 id="product-list-example-h4-productname" className="font-medium text-sm">{product.name}</h4>
|
|
184
|
+
<p id="product-list-example-p-productcategory" className="text-xs text-foreground-muted">{product.category}</p>
|
|
185
185
|
</div>
|
|
186
|
-
<span className="font-medium">{product.price}</span>
|
|
186
|
+
<span id="product-list-example-span-productprice" className="font-medium">{product.price}</span>
|
|
187
187
|
</div>
|
|
188
188
|
</div>
|
|
189
189
|
))}
|
|
@@ -203,7 +203,7 @@ export const ImageGalleryExample: Story = {
|
|
|
203
203
|
|
|
204
204
|
return (
|
|
205
205
|
<div className="space-y-2">
|
|
206
|
-
<h3 className="font-medium">Gallery</h3>
|
|
206
|
+
<h3 id="image-gallery-example-h3-gallery" className="font-medium">Gallery</h3>
|
|
207
207
|
<ScrollShadow
|
|
208
208
|
orientation="horizontal"
|
|
209
209
|
hideScrollbar
|
|
@@ -265,19 +265,19 @@ export const AllSizesComparison: Story = {
|
|
|
265
265
|
render: () => (
|
|
266
266
|
<div className="flex gap-8">
|
|
267
267
|
<div className="space-y-2">
|
|
268
|
-
<p className="text-sm font-medium">Small</p>
|
|
268
|
+
<p id="all-sizes-comparison-p-small" className="text-sm font-medium">Small</p>
|
|
269
269
|
<ScrollShadow size="sm" className="h-48 w-64 border border-border rounded-sm">
|
|
270
270
|
{sampleContent.slice(0, 10)}
|
|
271
271
|
</ScrollShadow>
|
|
272
272
|
</div>
|
|
273
273
|
<div className="space-y-2">
|
|
274
|
-
<p className="text-sm font-medium">Medium</p>
|
|
274
|
+
<p id="all-sizes-comparison-p-medium" className="text-sm font-medium">Medium</p>
|
|
275
275
|
<ScrollShadow size="md" className="h-48 w-64 border border-border rounded-sm">
|
|
276
276
|
{sampleContent.slice(0, 10)}
|
|
277
277
|
</ScrollShadow>
|
|
278
278
|
</div>
|
|
279
279
|
<div className="space-y-2">
|
|
280
|
-
<p className="text-sm font-medium">Large</p>
|
|
280
|
+
<p id="all-sizes-comparison-p-large" className="text-sm font-medium">Large</p>
|
|
281
281
|
<ScrollShadow size="lg" className="h-48 w-64 border border-border rounded-sm">
|
|
282
282
|
{sampleContent.slice(0, 10)}
|
|
283
283
|
</ScrollShadow>
|
|
@@ -292,7 +292,7 @@ export const ResponsiveMatrix: Story = {
|
|
|
292
292
|
<div className="space-y-8">
|
|
293
293
|
{/* Mobile */}
|
|
294
294
|
<div>
|
|
295
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
|
|
295
|
+
<h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
|
|
296
296
|
<div className="w-[375px] border border-dashed border-border p-4">
|
|
297
297
|
<ScrollShadow className="h-48 border border-border rounded-sm">
|
|
298
298
|
{sampleContent.slice(0, 8)}
|
|
@@ -301,7 +301,7 @@ export const ResponsiveMatrix: Story = {
|
|
|
301
301
|
</div>
|
|
302
302
|
{/* Tablet */}
|
|
303
303
|
<div>
|
|
304
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
|
|
304
|
+
<h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
|
|
305
305
|
<div className="w-[768px] border border-dashed border-border p-4">
|
|
306
306
|
<ScrollShadow
|
|
307
307
|
orientation="horizontal"
|
|
@@ -315,7 +315,7 @@ export const ResponsiveMatrix: Story = {
|
|
|
315
315
|
</div>
|
|
316
316
|
{/* Desktop */}
|
|
317
317
|
<div>
|
|
318
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
|
|
318
|
+
<h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
|
|
319
319
|
<div className="w-[1280px] border border-dashed border-border p-4">
|
|
320
320
|
<div className="grid grid-cols-3 gap-4">
|
|
321
321
|
<ScrollShadow size="sm" className="h-48 border border-border rounded-sm">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useRef, useState, useEffect, ReactNode } from "react";
|
|
3
|
+
import { useRef, useState, useEffect, ReactNode, useMemo } from "react";
|
|
4
4
|
import { cn } from "@/lib/utils";
|
|
5
5
|
|
|
6
6
|
interface ScrollShadowProps {
|
|
@@ -12,6 +12,19 @@ interface ScrollShadowProps {
|
|
|
12
12
|
style?: React.CSSProperties;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
// Responsive size maps for different screen sizes
|
|
16
|
+
const mobileSizeMap = {
|
|
17
|
+
sm: 12,
|
|
18
|
+
md: 24,
|
|
19
|
+
lg: 36,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const desktopSizeMap = {
|
|
23
|
+
sm: 20,
|
|
24
|
+
md: 40,
|
|
25
|
+
lg: 60,
|
|
26
|
+
};
|
|
27
|
+
|
|
15
28
|
export function ScrollShadow({
|
|
16
29
|
children,
|
|
17
30
|
orientation = "vertical",
|
|
@@ -23,14 +36,23 @@ export function ScrollShadow({
|
|
|
23
36
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
24
37
|
const [showStartShadow, setShowStartShadow] = useState(false);
|
|
25
38
|
const [showEndShadow, setShowEndShadow] = useState(false);
|
|
39
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
26
40
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
// Detect mobile screen size
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const checkMobile = () => {
|
|
44
|
+
setIsMobile(window.innerWidth < 640); // sm breakpoint
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
checkMobile();
|
|
48
|
+
window.addEventListener("resize", checkMobile);
|
|
49
|
+
return () => window.removeEventListener("resize", checkMobile);
|
|
50
|
+
}, []);
|
|
32
51
|
|
|
33
|
-
const shadowSize =
|
|
52
|
+
const shadowSize = useMemo(() => {
|
|
53
|
+
const sizeMap = isMobile ? mobileSizeMap : desktopSizeMap;
|
|
54
|
+
return sizeMap[size];
|
|
55
|
+
}, [isMobile, size]);
|
|
34
56
|
|
|
35
57
|
const updateShadows = () => {
|
|
36
58
|
const element = scrollRef.current;
|
|
@@ -70,9 +92,9 @@ export function ScrollShadow({
|
|
|
70
92
|
const isHorizontal = orientation === "horizontal" || orientation === "both";
|
|
71
93
|
|
|
72
94
|
return (
|
|
73
|
-
<div className={cn("relative", className)} style={style}>
|
|
95
|
+
<div data-sonance-name="scroll-shadow" className={cn("relative", className)} style={style}>
|
|
74
96
|
{/* Start shadow (top/left) */}
|
|
75
|
-
<div
|
|
97
|
+
<div data-sonance-name="scroll-shadow"
|
|
76
98
|
className={cn(
|
|
77
99
|
"pointer-events-none absolute z-10 transition-opacity duration-200",
|
|
78
100
|
isVertical && "inset-x-0 top-0",
|
|
@@ -101,11 +101,11 @@ export const WithDisabledOption: Story = {
|
|
|
101
101
|
export const AllStates: Story = {
|
|
102
102
|
render: () => (
|
|
103
103
|
<div className="space-y-6 w-72">
|
|
104
|
-
<Select options={defaultOptions} placeholder="Default select" />
|
|
105
|
-
<Select options={countryOptions} label="With Label" placeholder="Select..." />
|
|
106
|
-
<Select options={countryOptions} label="With Value" defaultValue="uk" />
|
|
107
|
-
<Select options={countryOptions} label="With Error" error="Required field" />
|
|
108
|
-
<Select options={countryOptions} label="Disabled" defaultValue="us" disabled />
|
|
104
|
+
<Select id="all-states-select-default-select" options={defaultOptions} placeholder="Default select" />
|
|
105
|
+
<Select id="all-states-select" options={countryOptions} label="With Label" placeholder="Select..." />
|
|
106
|
+
<Select id="all-states-select" options={countryOptions} label="With Value" defaultValue="uk" />
|
|
107
|
+
<Select id="all-states-select" options={countryOptions} label="With Error" error="Required field" />
|
|
108
|
+
<Select id="all-states-select" options={countryOptions} label="Disabled" defaultValue="us" disabled />
|
|
109
109
|
</div>
|
|
110
110
|
),
|
|
111
111
|
};
|
|
@@ -132,13 +132,14 @@ export const StateMatrix: Story = {
|
|
|
132
132
|
render: () => {
|
|
133
133
|
const states: SelectState[] = ['default', 'hover', 'focus', 'open', 'error', 'disabled'];
|
|
134
134
|
return (
|
|
135
|
-
<div className="space-y-6 w-80">
|
|
136
|
-
<h3 className="text-sm font-medium text-foreground-muted">Select States</h3>
|
|
135
|
+
<div data-sonance-name="select.stories" className="space-y-6 w-80">
|
|
136
|
+
<h3 id="state-matrix-h3-select-states" className="text-sm font-medium text-foreground-muted">Select States</h3>
|
|
137
137
|
<div className="grid grid-cols-1 gap-4">
|
|
138
138
|
{states.map((state) => (
|
|
139
139
|
<div key={state} className="flex items-center gap-4">
|
|
140
|
-
<span className="text-xs font-medium text-foreground-muted uppercase w-20">{state}</span>
|
|
140
|
+
<span id="state-matrix-span-state" className="text-xs font-medium text-foreground-muted uppercase w-20">{state}</span>
|
|
141
141
|
<Select
|
|
142
|
+
id="state-matrix-select-select-option"
|
|
142
143
|
state={state}
|
|
143
144
|
options={defaultOptions}
|
|
144
145
|
placeholder="Select option"
|
|
@@ -159,31 +160,31 @@ export const ResponsiveMatrix: Story = {
|
|
|
159
160
|
<div className="space-y-8">
|
|
160
161
|
{/* Mobile */}
|
|
161
162
|
<div>
|
|
162
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
|
|
163
|
+
<h4 id="responsive-matrix-h4-mobile-375px" className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
|
|
163
164
|
<div className="w-[375px] border border-dashed border-border p-4 space-y-4">
|
|
164
|
-
<Select options={countryOptions} label="Country" placeholder="Select..." />
|
|
165
|
-
<Select options={defaultOptions} label="Option" placeholder="Choose..." />
|
|
165
|
+
<Select id="responsive-matrix-select" options={countryOptions} label="Country" placeholder="Select..." />
|
|
166
|
+
<Select id="responsive-matrix-select-choose" options={defaultOptions} label="Option" placeholder="Choose..." />
|
|
166
167
|
</div>
|
|
167
168
|
</div>
|
|
168
169
|
{/* Tablet */}
|
|
169
170
|
<div>
|
|
170
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
|
|
171
|
+
<h4 id="responsive-matrix-h4-tablet-768px" className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
|
|
171
172
|
<div className="w-[768px] border border-dashed border-border p-4">
|
|
172
173
|
<div className="grid grid-cols-2 gap-4">
|
|
173
|
-
<Select options={countryOptions} label="Country" placeholder="Select country..." />
|
|
174
|
-
<Select options={defaultOptions} label="Category" placeholder="Select category..." />
|
|
174
|
+
<Select id="responsive-matrix-select-select-country" options={countryOptions} label="Country" placeholder="Select country..." />
|
|
175
|
+
<Select id="responsive-matrix-select-select-category" options={defaultOptions} label="Category" placeholder="Select category..." />
|
|
175
176
|
</div>
|
|
176
177
|
</div>
|
|
177
178
|
</div>
|
|
178
179
|
{/* Desktop */}
|
|
179
180
|
<div>
|
|
180
|
-
<h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
|
|
181
|
+
<h4 id="responsive-matrix-h4-desktop-1280px" className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
|
|
181
182
|
<div className="w-[1280px] border border-dashed border-border p-4">
|
|
182
183
|
<div className="grid grid-cols-4 gap-4">
|
|
183
|
-
<Select options={countryOptions} label="Country" defaultValue="us" />
|
|
184
|
-
<Select options={defaultOptions} label="Default" placeholder="Select..." />
|
|
185
|
-
<Select options={countryOptions} label="With Error" error="Required" />
|
|
186
|
-
<Select options={countryOptions} label="Disabled" defaultValue="uk" disabled />
|
|
184
|
+
<Select id="responsive-matrix-select" options={countryOptions} label="Country" defaultValue="us" />
|
|
185
|
+
<Select id="responsive-matrix-select" options={defaultOptions} label="Default" placeholder="Select..." />
|
|
186
|
+
<Select id="responsive-matrix-select" options={countryOptions} label="With Error" error="Required" />
|
|
187
|
+
<Select id="responsive-matrix-select" options={countryOptions} label="Disabled" defaultValue="uk" disabled />
|
|
187
188
|
</div>
|
|
188
189
|
</div>
|
|
189
190
|
</div>
|
|
@@ -39,6 +39,8 @@ interface SelectProps {
|
|
|
39
39
|
className?: string;
|
|
40
40
|
/** Visual state for Storybook/Figma documentation */
|
|
41
41
|
state?: SelectState;
|
|
42
|
+
/** Style for the select button */
|
|
43
|
+
style?: React.CSSProperties;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
export function Select({
|
|
@@ -52,6 +54,7 @@ export function Select({
|
|
|
52
54
|
disabled = false,
|
|
53
55
|
className,
|
|
54
56
|
state,
|
|
57
|
+
style,
|
|
55
58
|
}: SelectProps) {
|
|
56
59
|
const isDisabled = disabled || state === "disabled";
|
|
57
60
|
const hasError = error || state === "error";
|
|
@@ -94,7 +97,7 @@ export function Select({
|
|
|
94
97
|
}, []);
|
|
95
98
|
|
|
96
99
|
return (
|
|
97
|
-
<div className={cn("w-full", className)} ref={containerRef}>
|
|
100
|
+
<div data-sonance-name="select" className={cn("w-full", className)} ref={containerRef}>
|
|
98
101
|
{label && (
|
|
99
102
|
<label className="mb-2 block text-xs font-medium uppercase tracking-widest text-foreground-muted">
|
|
100
103
|
{label}
|
|
@@ -105,6 +108,7 @@ export function Select({
|
|
|
105
108
|
type="button"
|
|
106
109
|
onClick={() => !isDisabled && setIsOpen(!isOpen)}
|
|
107
110
|
disabled={isDisabled}
|
|
111
|
+
style={style}
|
|
108
112
|
className={cn(
|
|
109
113
|
"flex w-full items-center justify-between border border-input-border bg-input px-4 py-3",
|
|
110
114
|
"text-left text-foreground transition-colors duration-200",
|
|
@@ -115,7 +119,7 @@ export function Select({
|
|
|
115
119
|
getStateStyles(state)
|
|
116
120
|
)}
|
|
117
121
|
>
|
|
118
|
-
<span className={cn(!selectedOption && "text-input-placeholder")}>
|
|
122
|
+
<span id="span-selectedoptionlabel-" className={cn(!selectedOption && "text-input-placeholder")}>
|
|
119
123
|
{selectedOption?.label || placeholder}
|
|
120
124
|
</span>
|
|
121
125
|
<ChevronDown
|
|
@@ -155,7 +159,7 @@ export function Select({
|
|
|
155
159
|
</div>
|
|
156
160
|
)}
|
|
157
161
|
</div>
|
|
158
|
-
{error && <p className="mt-1 text-sm text-error">{error}</p>}
|
|
162
|
+
{error && <p id="p-error" className="mt-1 text-sm text-error">{error}</p>}
|
|
159
163
|
</div>
|
|
160
164
|
);
|
|
161
165
|
}
|
|
@@ -191,7 +195,7 @@ export const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
|
|
|
191
195
|
const hasError = error || state === "error";
|
|
192
196
|
|
|
193
197
|
return (
|
|
194
|
-
<div className="w-full">
|
|
198
|
+
<div data-sonance-name="select" className="w-full">
|
|
195
199
|
{label && (
|
|
196
200
|
<label className="mb-2 block text-xs font-medium uppercase tracking-widest text-foreground-muted">
|
|
197
201
|
{label}
|
|
@@ -209,7 +213,7 @@ export const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
|
|
|
209
213
|
hasError && "border-error",
|
|
210
214
|
getNativeSelectStateStyles(state),
|
|
211
215
|
className
|
|
212
|
-
)}
|
|
216
|
+
)} data-sonance-name="select"
|
|
213
217
|
{...props}
|
|
214
218
|
>
|
|
215
219
|
{options.map((option) => (
|
|
@@ -220,7 +224,7 @@ export const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
|
|
|
220
224
|
</select>
|
|
221
225
|
<ChevronDown className="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-foreground-muted" />
|
|
222
226
|
</div>
|
|
223
|
-
{error && <p className="mt-1 text-sm text-error">{error}</p>}
|
|
227
|
+
{error && <p id="native-select-p-error" className="mt-1 text-sm text-error">{error}</p>}
|
|
224
228
|
</div>
|
|
225
229
|
);
|
|
226
230
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
const Separator = React.forwardRef<
|
|
9
|
+
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
|
10
|
+
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
|
11
|
+
>(
|
|
12
|
+
(
|
|
13
|
+
{ className, orientation = "horizontal", decorative = true, ...props },
|
|
14
|
+
ref
|
|
15
|
+
) => (
|
|
16
|
+
<SeparatorPrimitive.Root data-sonance-name="separator"
|
|
17
|
+
ref={ref}
|
|
18
|
+
decorative={decorative}
|
|
19
|
+
orientation={orientation}
|
|
20
|
+
className={cn(
|
|
21
|
+
"shrink-0 bg-border",
|
|
22
|
+
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
23
|
+
className
|
|
24
|
+
)}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
Separator.displayName = SeparatorPrimitive.Root.displayName
|
|
30
|
+
|
|
31
|
+
export { Separator }
|
|
32
|
+
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as SheetPrimitive from "@radix-ui/react-dialog"
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
6
|
+
import { X } from "lucide-react"
|
|
7
|
+
|
|
8
|
+
import { cn } from "@/lib/utils"
|
|
9
|
+
|
|
10
|
+
const Sheet = SheetPrimitive.Root
|
|
11
|
+
|
|
12
|
+
const SheetTrigger = SheetPrimitive.Trigger
|
|
13
|
+
|
|
14
|
+
const SheetClose = SheetPrimitive.Close
|
|
15
|
+
|
|
16
|
+
const SheetPortal = SheetPrimitive.Portal
|
|
17
|
+
|
|
18
|
+
const SheetOverlay = React.forwardRef<
|
|
19
|
+
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
|
20
|
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
|
21
|
+
>(({ className, ...props }, ref) => (
|
|
22
|
+
<SheetPrimitive.Overlay
|
|
23
|
+
className={cn(
|
|
24
|
+
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
25
|
+
className
|
|
26
|
+
)}
|
|
27
|
+
{...props}
|
|
28
|
+
ref={ref}
|
|
29
|
+
/>
|
|
30
|
+
))
|
|
31
|
+
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
|
|
32
|
+
|
|
33
|
+
const sheetVariants = cva(
|
|
34
|
+
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
|
35
|
+
{
|
|
36
|
+
variants: {
|
|
37
|
+
side: {
|
|
38
|
+
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
|
39
|
+
bottom:
|
|
40
|
+
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
|
41
|
+
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
|
42
|
+
right:
|
|
43
|
+
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
defaultVariants: {
|
|
47
|
+
side: "right",
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
interface SheetContentProps
|
|
53
|
+
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
|
54
|
+
VariantProps<typeof sheetVariants> {}
|
|
55
|
+
|
|
56
|
+
const SheetContent = React.forwardRef<
|
|
57
|
+
React.ElementRef<typeof SheetPrimitive.Content>,
|
|
58
|
+
SheetContentProps
|
|
59
|
+
>(({ side = "right", className, children, ...props }, ref) => (
|
|
60
|
+
<SheetPortal>
|
|
61
|
+
<SheetOverlay />
|
|
62
|
+
<SheetPrimitive.Content
|
|
63
|
+
ref={ref}
|
|
64
|
+
className={cn(sheetVariants({ side }), className)}
|
|
65
|
+
{...props}
|
|
66
|
+
>
|
|
67
|
+
{children}
|
|
68
|
+
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
|
69
|
+
<X className="h-4 w-4" />
|
|
70
|
+
<span id="sheet-content-span-close" className="sr-only">Close</span>
|
|
71
|
+
</SheetPrimitive.Close>
|
|
72
|
+
</SheetPrimitive.Content>
|
|
73
|
+
</SheetPortal>
|
|
74
|
+
))
|
|
75
|
+
SheetContent.displayName = SheetPrimitive.Content.displayName
|
|
76
|
+
|
|
77
|
+
const SheetHeader = ({
|
|
78
|
+
className,
|
|
79
|
+
...props
|
|
80
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
81
|
+
<div data-sonance-name="sheet"
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
)
|
|
85
|
+
SheetHeader.displayName = "SheetHeader"
|
|
86
|
+
|
|
87
|
+
const SheetFooter = ({
|
|
88
|
+
className,
|
|
89
|
+
...props
|
|
90
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
91
|
+
<div
|
|
92
|
+
className={cn(
|
|
93
|
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
|
94
|
+
className
|
|
95
|
+
)} data-sonance-name="sheet"
|
|
96
|
+
{...props}
|
|
97
|
+
/>
|
|
98
|
+
)
|
|
99
|
+
SheetFooter.displayName = "SheetFooter"
|
|
100
|
+
|
|
101
|
+
const SheetTitle = React.forwardRef<
|
|
102
|
+
React.ElementRef<typeof SheetPrimitive.Title>,
|
|
103
|
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
|
104
|
+
>(({ className, ...props }, ref) => (
|
|
105
|
+
<SheetPrimitive.Title
|
|
106
|
+
ref={ref}
|
|
107
|
+
className={cn("text-lg font-semibold text-foreground", className)}
|
|
108
|
+
{...props}
|
|
109
|
+
/>
|
|
110
|
+
))
|
|
111
|
+
SheetTitle.displayName = SheetPrimitive.Title.displayName
|
|
112
|
+
|
|
113
|
+
const SheetDescription = React.forwardRef<
|
|
114
|
+
React.ElementRef<typeof SheetPrimitive.Description>,
|
|
115
|
+
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
|
116
|
+
>(({ className, ...props }, ref) => (
|
|
117
|
+
<SheetPrimitive.Description
|
|
118
|
+
ref={ref}
|
|
119
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
120
|
+
{...props}
|
|
121
|
+
/>
|
|
122
|
+
))
|
|
123
|
+
SheetDescription.displayName = SheetPrimitive.Description.displayName
|
|
124
|
+
|
|
125
|
+
export {
|
|
126
|
+
Sheet,
|
|
127
|
+
SheetPortal,
|
|
128
|
+
SheetOverlay,
|
|
129
|
+
SheetTrigger,
|
|
130
|
+
SheetClose,
|
|
131
|
+
SheetContent,
|
|
132
|
+
SheetHeader,
|
|
133
|
+
SheetFooter,
|
|
134
|
+
SheetTitle,
|
|
135
|
+
SheetDescription,
|
|
136
|
+
}
|
|
137
|
+
|