sonance-brand-mcp 1.3.110 → 1.3.112
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-ai-edit/route.ts +30 -7
- package/dist/assets/api/sonance-save-image/route.ts +625 -0
- package/dist/assets/api/sonance-vision-apply/image-styling-detection.ts +1360 -0
- package/dist/assets/api/sonance-vision-apply/route.ts +1020 -64
- package/dist/assets/api/sonance-vision-apply/styling-detection.ts +730 -0
- package/dist/assets/api/sonance-vision-apply/theme-discovery.ts +1 -1
- package/dist/assets/api/sonance-vision-edit/route.ts +33 -8
- package/dist/assets/brand-system.ts +13 -12
- package/dist/assets/components/accordion.tsx +15 -7
- package/dist/assets/components/alert-dialog.tsx +35 -10
- package/dist/assets/components/alert.tsx +11 -10
- package/dist/assets/components/avatar.tsx +4 -4
- package/dist/assets/components/badge.tsx +16 -12
- package/dist/assets/components/button.stories.tsx +3 -3
- package/dist/assets/components/button.tsx +50 -31
- package/dist/assets/components/calendar.tsx +12 -8
- package/dist/assets/components/card.tsx +35 -29
- package/dist/assets/components/checkbox.tsx +9 -8
- package/dist/assets/components/code.tsx +19 -11
- package/dist/assets/components/command.tsx +32 -13
- package/dist/assets/components/context-menu.tsx +37 -16
- package/dist/assets/components/dialog.tsx +8 -5
- package/dist/assets/components/divider.tsx +15 -5
- package/dist/assets/components/drawer.tsx +4 -3
- package/dist/assets/components/dropdown-menu.tsx +15 -13
- package/dist/assets/components/hover-card.tsx +4 -1
- package/dist/assets/components/image.tsx +1 -1
- package/dist/assets/components/input.tsx +29 -14
- package/dist/assets/components/kbd.stories.tsx +3 -3
- package/dist/assets/components/kbd.tsx +29 -13
- package/dist/assets/components/listbox.tsx +8 -8
- package/dist/assets/components/menubar.tsx +50 -23
- package/dist/assets/components/navbar.stories.tsx +140 -13
- package/dist/assets/components/navbar.tsx +22 -5
- package/dist/assets/components/navigation-menu.tsx +28 -6
- package/dist/assets/components/pagination.tsx +10 -10
- package/dist/assets/components/popover.tsx +10 -8
- package/dist/assets/components/progress.tsx +6 -4
- package/dist/assets/components/radio-group.tsx +5 -5
- package/dist/assets/components/select.tsx +49 -29
- package/dist/assets/components/separator.tsx +3 -3
- package/dist/assets/components/sheet.tsx +4 -4
- package/dist/assets/components/sidebar.tsx +10 -10
- package/dist/assets/components/skeleton.tsx +13 -5
- package/dist/assets/components/slider.tsx +12 -10
- package/dist/assets/components/switch.tsx +4 -4
- package/dist/assets/components/table.tsx +5 -5
- package/dist/assets/components/tabs.tsx +8 -8
- package/dist/assets/components/textarea.tsx +11 -9
- package/dist/assets/components/toast.tsx +7 -7
- package/dist/assets/components/toggle.tsx +27 -7
- package/dist/assets/components/tooltip.tsx +10 -8
- package/dist/assets/components/user.tsx +8 -6
- package/dist/assets/dev-tools/SonanceDevTools.tsx +851 -708
- package/dist/assets/dev-tools/components/ApplyFirstPreview.tsx +10 -10
- package/dist/assets/dev-tools/components/ChatHistory.tsx +145 -0
- package/dist/assets/dev-tools/components/ChatInterface.tsx +444 -295
- package/dist/assets/dev-tools/components/ChatTabBar.tsx +82 -0
- package/dist/assets/dev-tools/components/DiffPreview.tsx +1 -1
- package/dist/assets/dev-tools/components/InlineDiffPreview.tsx +528 -0
- package/dist/assets/dev-tools/components/InspectorOverlay.tsx +21 -18
- package/dist/assets/dev-tools/components/PropertiesPanel.tsx +1345 -0
- package/dist/assets/dev-tools/components/ScreenshotAnnotator.tsx +1 -1
- package/dist/assets/dev-tools/components/SectionHighlight.tsx +1 -1
- package/dist/assets/dev-tools/components/VisionDiffPreview.tsx +7 -7
- package/dist/assets/dev-tools/components/VisionModeBorder.tsx +12 -63
- package/dist/assets/dev-tools/constants.ts +38 -6
- package/dist/assets/dev-tools/hooks/index.ts +69 -0
- package/dist/assets/dev-tools/hooks/useComponentDetection.ts +132 -0
- package/dist/assets/dev-tools/hooks/useComputedStyles.ts +471 -0
- package/dist/assets/dev-tools/hooks/useContentHash.ts +212 -0
- package/dist/assets/dev-tools/hooks/useElementScanner.ts +398 -0
- package/dist/assets/dev-tools/hooks/useImageDetection.ts +162 -0
- package/dist/assets/dev-tools/hooks/useTextDetection.ts +217 -0
- package/dist/assets/dev-tools/index.ts +3 -0
- package/dist/assets/dev-tools/panels/AnalysisPanel.tsx +32 -32
- package/dist/assets/dev-tools/panels/ComponentsPanel.tsx +384 -131
- package/dist/assets/dev-tools/panels/TextPanel.tsx +10 -10
- package/dist/assets/dev-tools/types.ts +93 -2
- package/dist/assets/globals.css +225 -9
- package/dist/assets/styles/brand-overrides.css +3 -2
- package/dist/assets/utils.ts +2 -1
- package/dist/index.js +22 -3
- package/package.json +2 -1
|
@@ -13,14 +13,30 @@ interface NavbarProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
13
13
|
export const Navbar = forwardRef<HTMLElement, NavbarProps>(
|
|
14
14
|
({ className, variant = "default", sticky = false, bordered = true, children, ...props }, ref) => {
|
|
15
15
|
const variantClasses = {
|
|
16
|
-
default: "bg-
|
|
16
|
+
default: "bg-white/70 dark:bg-white/[0.03] backdrop-blur-lg",
|
|
17
17
|
dark: "bg-sonance-charcoal text-sonance-white",
|
|
18
18
|
transparent: "bg-transparent",
|
|
19
|
-
blur: "bg-
|
|
19
|
+
blur: "bg-white/60 dark:bg-black/40 backdrop-blur-xl",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const borderClasses = {
|
|
23
|
+
default: "border-b border-black/8 dark:border-white/8",
|
|
24
|
+
dark: "border-b border-white/10",
|
|
25
|
+
transparent: "",
|
|
26
|
+
blur: "border-b border-black/8 dark:border-white/8",
|
|
20
27
|
};
|
|
21
28
|
|
|
22
29
|
return (
|
|
23
|
-
<nav
|
|
30
|
+
<nav
|
|
31
|
+
ref={ref}
|
|
32
|
+
data-sonance-name="navbar"
|
|
33
|
+
className={cn(
|
|
34
|
+
"w-full px-4 md:px-6 py-3",
|
|
35
|
+
variantClasses[variant],
|
|
36
|
+
bordered && borderClasses[variant],
|
|
37
|
+
sticky && "sticky top-0 z-50",
|
|
38
|
+
className
|
|
39
|
+
)}
|
|
24
40
|
{...props}
|
|
25
41
|
>
|
|
26
42
|
{children}
|
|
@@ -133,7 +149,8 @@ export function NavbarMobileMenu({ isOpen, children, className }: NavbarMobileMe
|
|
|
133
149
|
<div
|
|
134
150
|
className={cn(
|
|
135
151
|
"md:hidden absolute left-0 right-0 top-full",
|
|
136
|
-
"bg-
|
|
152
|
+
"bg-white/90 dark:bg-black/80 backdrop-blur-xl",
|
|
153
|
+
"border-b border-black/10 dark:border-white/10 shadow-xl",
|
|
137
154
|
"animate-in slide-in-from-top-2 duration-200",
|
|
138
155
|
className
|
|
139
156
|
)}
|
|
@@ -198,7 +215,7 @@ export function ResponsiveNavbar({
|
|
|
198
215
|
{item.label}
|
|
199
216
|
</a>
|
|
200
217
|
))}
|
|
201
|
-
{actions && <div className="pt-4 border-t border-border">{actions}</div>}
|
|
218
|
+
{actions && <div className="pt-4 border-t border-black/8 dark:border-white/8">{actions}</div>}
|
|
202
219
|
</NavbarMobileMenu>
|
|
203
220
|
</Navbar>
|
|
204
221
|
);
|
|
@@ -12,6 +12,7 @@ const NavigationMenu = React.forwardRef<
|
|
|
12
12
|
>(({ className, children, ...props }, ref) => (
|
|
13
13
|
<NavigationMenuPrimitive.Root
|
|
14
14
|
ref={ref}
|
|
15
|
+
data-sonance-name="navigation-menu"
|
|
15
16
|
className={cn(
|
|
16
17
|
"relative z-10 flex max-w-max flex-1 items-center justify-center",
|
|
17
18
|
className
|
|
@@ -42,7 +43,16 @@ NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
|
|
|
42
43
|
const NavigationMenuItem = NavigationMenuPrimitive.Item;
|
|
43
44
|
|
|
44
45
|
const navigationMenuTriggerStyle = cva(
|
|
45
|
-
|
|
46
|
+
cn(
|
|
47
|
+
"group inline-flex h-10 w-max items-center justify-center rounded-xl px-4 py-2 text-sm font-medium",
|
|
48
|
+
"transition-all duration-150",
|
|
49
|
+
"bg-transparent backdrop-blur-sm",
|
|
50
|
+
"hover:bg-white/60 dark:hover:bg-white/10 hover:text-foreground",
|
|
51
|
+
"focus:bg-white/60 dark:focus:bg-white/10 focus:text-foreground focus:outline-none",
|
|
52
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
53
|
+
"data-[active]:bg-white/50 dark:data-[active]:bg-white/8",
|
|
54
|
+
"data-[state=open]:bg-white/60 dark:data-[state=open]:bg-white/10"
|
|
55
|
+
)
|
|
46
56
|
);
|
|
47
57
|
|
|
48
58
|
const NavigationMenuTrigger = React.forwardRef<
|
|
@@ -70,7 +80,12 @@ const NavigationMenuContent = React.forwardRef<
|
|
|
70
80
|
<NavigationMenuPrimitive.Content
|
|
71
81
|
ref={ref}
|
|
72
82
|
className={cn(
|
|
73
|
-
"left-0 top-0 w-full
|
|
83
|
+
"left-0 top-0 w-full",
|
|
84
|
+
"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out",
|
|
85
|
+
"data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out",
|
|
86
|
+
"data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52",
|
|
87
|
+
"data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52",
|
|
88
|
+
"md:absolute md:w-auto",
|
|
74
89
|
className
|
|
75
90
|
)}
|
|
76
91
|
{...props}
|
|
@@ -84,10 +99,18 @@ const NavigationMenuViewport = React.forwardRef<
|
|
|
84
99
|
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
|
|
85
100
|
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
|
|
86
101
|
>(({ className, ...props }, ref) => (
|
|
87
|
-
<div
|
|
102
|
+
<div
|
|
103
|
+
data-sonance-name="navigation-menu"
|
|
104
|
+
className={cn("absolute left-0 top-full flex justify-center")}
|
|
105
|
+
>
|
|
88
106
|
<NavigationMenuPrimitive.Viewport
|
|
89
107
|
className={cn(
|
|
90
|
-
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden
|
|
108
|
+
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden",
|
|
109
|
+
"rounded-xl backdrop-blur-xl",
|
|
110
|
+
"bg-white/90 dark:bg-black/80",
|
|
111
|
+
"border border-black/10 dark:border-white/10",
|
|
112
|
+
"shadow-[0_8px_32px_rgba(0,0,0,0.12)] dark:shadow-[0_8px_32px_rgba(0,0,0,0.4)]",
|
|
113
|
+
"text-foreground",
|
|
91
114
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
92
115
|
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90",
|
|
93
116
|
"md:w-[var(--radix-navigation-menu-viewport-width)]",
|
|
@@ -115,7 +138,7 @@ const NavigationMenuIndicator = React.forwardRef<
|
|
|
115
138
|
)}
|
|
116
139
|
{...props}
|
|
117
140
|
>
|
|
118
|
-
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-
|
|
141
|
+
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-white/80 dark:bg-white/10 shadow-md" />
|
|
119
142
|
</NavigationMenuPrimitive.Indicator>
|
|
120
143
|
));
|
|
121
144
|
NavigationMenuIndicator.displayName =
|
|
@@ -132,4 +155,3 @@ export {
|
|
|
132
155
|
NavigationMenuIndicator,
|
|
133
156
|
NavigationMenuViewport,
|
|
134
157
|
};
|
|
135
|
-
|
|
@@ -8,14 +8,14 @@ import { cn } from "@/lib/utils";
|
|
|
8
8
|
export type PaginationButtonState = "default" | "hover" | "focus" | "active" | "disabled";
|
|
9
9
|
|
|
10
10
|
const paginationButtonVariants = cva(
|
|
11
|
-
"flex items-center justify-center font-medium border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-
|
|
11
|
+
"flex items-center justify-center font-medium border transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-[color:var(--sonance-blue)]/30 focus:ring-offset-2 backdrop-blur-sm",
|
|
12
12
|
{
|
|
13
13
|
variants: {
|
|
14
14
|
size: {
|
|
15
|
-
xs: "h-6 min-w-6 px-1.5 text-[10px] rounded-
|
|
16
|
-
sm: "h-7 min-w-7 px-2 text-xs rounded-
|
|
17
|
-
md: "h-8 min-w-8 px-2.5 text-sm rounded-
|
|
18
|
-
lg: "h-9 min-w-9 px-3 text-sm rounded-
|
|
15
|
+
xs: "h-6 min-w-6 px-1.5 text-[10px] rounded-lg",
|
|
16
|
+
sm: "h-7 min-w-7 px-2 text-xs rounded-xl",
|
|
17
|
+
md: "h-8 min-w-8 px-2.5 text-sm rounded-xl",
|
|
18
|
+
lg: "h-9 min-w-9 px-3 text-sm rounded-2xl",
|
|
19
19
|
},
|
|
20
20
|
},
|
|
21
21
|
defaultVariants: {
|
|
@@ -29,9 +29,9 @@ const getButtonStateStyles = (state?: PaginationButtonState) => {
|
|
|
29
29
|
if (!state || state === "default") return "";
|
|
30
30
|
|
|
31
31
|
const stateMap: Record<string, string> = {
|
|
32
|
-
hover: "bg-
|
|
33
|
-
focus: "ring-2 ring-
|
|
34
|
-
active: "bg-
|
|
32
|
+
hover: "bg-white/50 dark:bg-white/10",
|
|
33
|
+
focus: "ring-2 ring-[color:var(--sonance-blue)]/30 ring-offset-2",
|
|
34
|
+
active: "bg-[color:var(--sonance-blue)] text-white border-[color:var(--sonance-blue)]",
|
|
35
35
|
disabled: "opacity-50 cursor-not-allowed",
|
|
36
36
|
};
|
|
37
37
|
|
|
@@ -194,10 +194,10 @@ const PaginationButton = forwardRef<HTMLButtonElement, PaginationButtonProps>(
|
|
|
194
194
|
className={cn(
|
|
195
195
|
paginationButtonVariants({ size }),
|
|
196
196
|
isActive
|
|
197
|
-
? "bg-
|
|
197
|
+
? "bg-[color:var(--sonance-blue)] text-white border-[color:var(--sonance-blue)]"
|
|
198
198
|
: isDisabled
|
|
199
199
|
? "bg-transparent text-foreground-subtle border-transparent cursor-not-allowed"
|
|
200
|
-
: "bg-
|
|
200
|
+
: "bg-white/60 dark:bg-white/5 text-foreground border-black/8 dark:border-white/8 hover:bg-white/70 dark:hover:bg-white/10 hover:border-black/12 dark:hover:border-white/12",
|
|
201
201
|
getButtonStateStyles(state),
|
|
202
202
|
className
|
|
203
203
|
)} data-sonance-name="pagination"
|
|
@@ -16,18 +16,20 @@ const popoverVariants = cva(
|
|
|
16
16
|
{
|
|
17
17
|
variants: {
|
|
18
18
|
size: {
|
|
19
|
-
compact: "rounded-
|
|
20
|
-
default: "rounded-
|
|
21
|
-
spacious: "rounded-
|
|
19
|
+
compact: "rounded-xl",
|
|
20
|
+
default: "rounded-2xl",
|
|
21
|
+
spacious: "rounded-3xl",
|
|
22
22
|
},
|
|
23
23
|
popoverVariant: {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
// Glass morphism - default style
|
|
25
|
+
default: "bg-white/90 dark:bg-black/70 border-black/10 dark:border-white/10 backdrop-blur-xl shadow-[0_8px_32px_rgba(0,0,0,0.12)] dark:shadow-[0_8px_32px_rgba(0,0,0,0.4)]",
|
|
26
|
+
// Non-glass solid variant
|
|
27
|
+
solid: "bg-card border-border backdrop-blur-none",
|
|
26
28
|
},
|
|
27
29
|
},
|
|
28
30
|
defaultVariants: {
|
|
29
31
|
size: "default",
|
|
30
|
-
popoverVariant: "
|
|
32
|
+
popoverVariant: "default",
|
|
31
33
|
},
|
|
32
34
|
}
|
|
33
35
|
);
|
|
@@ -58,7 +60,7 @@ export function Popover({
|
|
|
58
60
|
triggerOn = "click",
|
|
59
61
|
className,
|
|
60
62
|
size = "default",
|
|
61
|
-
popoverVariant = "
|
|
63
|
+
popoverVariant = "default",
|
|
62
64
|
}: PopoverProps) {
|
|
63
65
|
const [isOpen, setIsOpen] = useState(false);
|
|
64
66
|
const [portalPosition, setPortalPosition] = useState<PortalPosition>({ top: 0, left: 0 });
|
|
@@ -178,7 +180,7 @@ export function Popover({
|
|
|
178
180
|
};
|
|
179
181
|
|
|
180
182
|
return (
|
|
181
|
-
<PopoverContext.Provider value={{ size }}>
|
|
183
|
+
<PopoverContext.Provider value={{ size: size ?? "default" }}>
|
|
182
184
|
<div data-sonance-name="popover"
|
|
183
185
|
ref={containerRef}
|
|
184
186
|
className="relative inline-block"
|
|
@@ -42,12 +42,14 @@ export const Progress = forwardRef<HTMLDivElement, ProgressProps>(
|
|
|
42
42
|
aria-valuemax={max}
|
|
43
43
|
aria-valuenow={value}
|
|
44
44
|
className={cn(
|
|
45
|
-
"w-full overflow-hidden rounded-full
|
|
45
|
+
"w-full overflow-hidden rounded-full",
|
|
46
|
+
"bg-white/60 dark:bg-white/[0.05] backdrop-blur-sm",
|
|
47
|
+
"border border-black/5 dark:border-white/5",
|
|
46
48
|
heightClasses[size]
|
|
47
49
|
)}
|
|
48
50
|
>
|
|
49
51
|
<div
|
|
50
|
-
className="h-full bg-
|
|
52
|
+
className="h-full bg-[color:var(--sonance-blue)] transition-all duration-300 ease-out"
|
|
51
53
|
style={{ width: `${percentage}%` }}
|
|
52
54
|
/>
|
|
53
55
|
</div>
|
|
@@ -99,7 +101,7 @@ export function CircularProgress({
|
|
|
99
101
|
fill="none"
|
|
100
102
|
stroke="currentColor"
|
|
101
103
|
strokeWidth={strokeWidth}
|
|
102
|
-
className="text-
|
|
104
|
+
className="text-black/10 dark:text-white/10"
|
|
103
105
|
/>
|
|
104
106
|
{/* Progress circle */}
|
|
105
107
|
<circle
|
|
@@ -112,7 +114,7 @@ export function CircularProgress({
|
|
|
112
114
|
strokeLinecap="round"
|
|
113
115
|
strokeDasharray={circumference}
|
|
114
116
|
strokeDashoffset={strokeDashoffset}
|
|
115
|
-
className="text-
|
|
117
|
+
className="text-[color:var(--sonance-blue)] transition-all duration-300 ease-out"
|
|
116
118
|
/>
|
|
117
119
|
</svg>
|
|
118
120
|
{showValue && (
|
|
@@ -7,7 +7,7 @@ import { cn } from "@/lib/utils";
|
|
|
7
7
|
export type RadioGroupItemState = "default" | "hover" | "focus" | "checked" | "disabled";
|
|
8
8
|
|
|
9
9
|
const radioItemVariants = cva(
|
|
10
|
-
"peer shrink-0 appearance-none rounded-full border
|
|
10
|
+
"peer shrink-0 appearance-none rounded-full border transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-[color:var(--sonance-blue)]/30 focus:ring-offset-2 focus:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 backdrop-blur-sm bg-white/60 dark:bg-white/5 border-black/8 dark:border-white/8 hover:border-black/15 dark:hover:border-white/15 checked:border-[color:var(--sonance-blue)]",
|
|
11
11
|
{
|
|
12
12
|
variants: {
|
|
13
13
|
size: {
|
|
@@ -35,9 +35,9 @@ const getStateStyles = (state?: RadioGroupItemState) => {
|
|
|
35
35
|
if (!state || state === "default") return "";
|
|
36
36
|
|
|
37
37
|
const stateMap: Record<string, string> = {
|
|
38
|
-
hover: "border-border-
|
|
39
|
-
focus: "ring-2 ring-
|
|
40
|
-
checked: "border-
|
|
38
|
+
hover: "border-black/15 dark:border-white/15",
|
|
39
|
+
focus: "ring-2 ring-[color:var(--sonance-blue)]/30 ring-offset-2 ring-offset-background",
|
|
40
|
+
checked: "border-[color:var(--sonance-blue)]",
|
|
41
41
|
disabled: "opacity-50 cursor-not-allowed",
|
|
42
42
|
};
|
|
43
43
|
|
|
@@ -142,7 +142,7 @@ export const RadioGroupItem = forwardRef<HTMLInputElement, RadioGroupItemProps>(
|
|
|
142
142
|
/>
|
|
143
143
|
<div data-sonance-name="radio-group"
|
|
144
144
|
className={cn(
|
|
145
|
-
"pointer-events-none absolute rounded-full bg-
|
|
145
|
+
"pointer-events-none absolute rounded-full bg-[color:var(--sonance-blue)]",
|
|
146
146
|
"scale-0 transition-all duration-150",
|
|
147
147
|
radioIndicatorSizes[size],
|
|
148
148
|
isChecked && "scale-100"
|
|
@@ -8,18 +8,22 @@ import { cn } from "@/lib/utils";
|
|
|
8
8
|
export type SelectState = "default" | "hover" | "focus" | "open" | "error" | "disabled";
|
|
9
9
|
|
|
10
10
|
const selectTriggerVariants = cva(
|
|
11
|
-
"flex w-full items-center justify-between
|
|
11
|
+
"flex w-full items-center justify-between text-left text-foreground transition-all duration-200 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 backdrop-blur-sm",
|
|
12
12
|
{
|
|
13
13
|
variants: {
|
|
14
14
|
size: {
|
|
15
|
-
xs: "h-7 px-
|
|
16
|
-
sm: "h-8 px-3 text-sm rounded-
|
|
17
|
-
md: "h-9 px-
|
|
18
|
-
lg: "h-10 px-4 text-sm rounded-
|
|
15
|
+
xs: "h-7 px-3 text-xs rounded-lg",
|
|
16
|
+
sm: "h-8 px-3.5 text-sm rounded-xl",
|
|
17
|
+
md: "h-9 px-4 text-sm rounded-xl",
|
|
18
|
+
lg: "h-10 px-4 text-sm rounded-2xl",
|
|
19
19
|
},
|
|
20
20
|
selectVariant: {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
// Glass morphism - default style
|
|
22
|
+
default:
|
|
23
|
+
"bg-white/60 dark:bg-white/[0.03] border border-black/8 dark:border-white/8 hover:border-black/12 dark:hover:border-white/12 focus:border-[color:var(--sonance-blue)] focus:shadow-[0_0_20px_var(--glow-primary)] focus:ring-0",
|
|
24
|
+
// Non-glass solid variant for fallback
|
|
25
|
+
solid:
|
|
26
|
+
"bg-input border border-input-border hover:border-border-hover focus:border-input-focus focus:ring-2 focus:ring-primary/10 backdrop-blur-none",
|
|
23
27
|
},
|
|
24
28
|
},
|
|
25
29
|
defaultVariants: {
|
|
@@ -30,14 +34,26 @@ const selectTriggerVariants = cva(
|
|
|
30
34
|
);
|
|
31
35
|
|
|
32
36
|
// State styles for Storybook/Figma visualization
|
|
33
|
-
const getStateStyles = (state?: SelectState) => {
|
|
37
|
+
const getStateStyles = (state?: SelectState, selectVariant?: string | null) => {
|
|
34
38
|
if (!state || state === "default") return "";
|
|
35
39
|
|
|
40
|
+
if (selectVariant === "solid") {
|
|
41
|
+
const stateMap: Record<string, string> = {
|
|
42
|
+
hover: "border-border-hover",
|
|
43
|
+
focus: "border-input-focus ring-2 ring-primary/10",
|
|
44
|
+
open: "border-input-focus ring-2 ring-primary/10",
|
|
45
|
+
error: "border-error ring-2 ring-error/10",
|
|
46
|
+
disabled: "opacity-50 cursor-not-allowed",
|
|
47
|
+
};
|
|
48
|
+
return stateMap[state] || "";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Glass variant states
|
|
36
52
|
const stateMap: Record<string, string> = {
|
|
37
|
-
hover: "border-border-
|
|
38
|
-
focus: "border-
|
|
39
|
-
open: "border-
|
|
40
|
-
error: "border-error
|
|
53
|
+
hover: "border-black/12 dark:border-white/12",
|
|
54
|
+
focus: "border-[color:var(--sonance-blue)] shadow-[0_0_20px_var(--glow-primary)]",
|
|
55
|
+
open: "border-[color:var(--sonance-blue)] shadow-[0_0_20px_var(--glow-primary)]",
|
|
56
|
+
error: "border-error shadow-[0_0_15px_rgba(198,40,40,0.2)]",
|
|
41
57
|
disabled: "opacity-50 cursor-not-allowed",
|
|
42
58
|
};
|
|
43
59
|
|
|
@@ -139,9 +155,9 @@ export function Select({
|
|
|
139
155
|
style={style}
|
|
140
156
|
className={cn(
|
|
141
157
|
selectTriggerVariants({ size, selectVariant }),
|
|
142
|
-
hasError && "border-error ring-2 ring-error/10",
|
|
143
|
-
(isOpen || isOpenState) && "border-input-focus ring-2 ring-primary/10",
|
|
144
|
-
getStateStyles(state)
|
|
158
|
+
hasError && (selectVariant === "solid" ? "border-error ring-2 ring-error/10" : "border-error shadow-[0_0_15px_rgba(198,40,40,0.2)]"),
|
|
159
|
+
(isOpen || isOpenState) && (selectVariant === "solid" ? "border-input-focus ring-2 ring-primary/10" : "border-[color:var(--sonance-blue)] shadow-[0_0_20px_var(--glow-primary)]"),
|
|
160
|
+
getStateStyles(state, selectVariant)
|
|
145
161
|
)}
|
|
146
162
|
>
|
|
147
163
|
<span id="span-selectedoptionlabel-" className={cn(!selectedOption && "text-input-placeholder")}>
|
|
@@ -158,8 +174,11 @@ export function Select({
|
|
|
158
174
|
{isOpen && (
|
|
159
175
|
<div
|
|
160
176
|
className={cn(
|
|
161
|
-
"absolute z-50 mt-
|
|
162
|
-
"
|
|
177
|
+
"absolute z-50 mt-2 w-full rounded-2xl backdrop-blur-xl",
|
|
178
|
+
"bg-white/90 dark:bg-black/80",
|
|
179
|
+
"border border-black/10 dark:border-white/10",
|
|
180
|
+
"shadow-[0_8px_32px_rgba(0,0,0,0.12)] dark:shadow-[0_8px_32px_rgba(0,0,0,0.4)]",
|
|
181
|
+
"max-h-60 overflow-auto p-1.5",
|
|
163
182
|
"animate-in fade-in-0 zoom-in-95 duration-150"
|
|
164
183
|
)}
|
|
165
184
|
>
|
|
@@ -170,11 +189,11 @@ export function Select({
|
|
|
170
189
|
onClick={() => !option.disabled && handleSelect(option.value)}
|
|
171
190
|
disabled={option.disabled}
|
|
172
191
|
className={cn(
|
|
173
|
-
"flex w-full items-center justify-between px-3 py-2 text-left text-sm rounded-
|
|
174
|
-
"transition-
|
|
192
|
+
"flex w-full items-center justify-between px-3 py-2 text-left text-sm rounded-xl",
|
|
193
|
+
"transition-all duration-150",
|
|
175
194
|
option.value === value
|
|
176
|
-
? "bg-
|
|
177
|
-
: "text-foreground hover:bg-
|
|
195
|
+
? "bg-[color:var(--sonance-blue)] text-white"
|
|
196
|
+
: "text-foreground hover:bg-white/50 dark:hover:bg-white/10",
|
|
178
197
|
option.disabled && "cursor-not-allowed opacity-50"
|
|
179
198
|
)}
|
|
180
199
|
>
|
|
@@ -223,10 +242,10 @@ export const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
|
|
|
223
242
|
const hasError = error || state === "error";
|
|
224
243
|
|
|
225
244
|
const sizeClasses = {
|
|
226
|
-
xs: "h-7 px-
|
|
227
|
-
sm: "h-8 px-3 pr-9 text-sm rounded-
|
|
228
|
-
md: "h-9 px-
|
|
229
|
-
lg: "h-10 px-4 pr-10 text-sm rounded-
|
|
245
|
+
xs: "h-7 px-3 pr-8 text-xs rounded-lg",
|
|
246
|
+
sm: "h-8 px-3.5 pr-9 text-sm rounded-xl",
|
|
247
|
+
md: "h-9 px-4 pr-9 text-sm rounded-xl",
|
|
248
|
+
lg: "h-10 px-4 pr-10 text-sm rounded-2xl",
|
|
230
249
|
};
|
|
231
250
|
|
|
232
251
|
return (
|
|
@@ -241,13 +260,14 @@ export const NativeSelect = forwardRef<HTMLSelectElement, NativeSelectProps>(
|
|
|
241
260
|
ref={ref}
|
|
242
261
|
disabled={isDisabled}
|
|
243
262
|
className={cn(
|
|
244
|
-
"w-full appearance-none
|
|
263
|
+
"w-full appearance-none backdrop-blur-sm",
|
|
264
|
+
"bg-white/60 dark:bg-white/[0.03] border border-black/8 dark:border-white/8",
|
|
245
265
|
sizeClasses[size],
|
|
246
266
|
"text-foreground transition-all duration-200",
|
|
247
|
-
"hover:border-border-
|
|
248
|
-
"focus:border-
|
|
267
|
+
"hover:border-black/12 dark:hover:border-white/12",
|
|
268
|
+
"focus:border-[color:var(--sonance-blue)] focus:outline-none focus:shadow-[0_0_20px_var(--glow-primary)]",
|
|
249
269
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
250
|
-
hasError && "border-error
|
|
270
|
+
hasError && "border-error shadow-[0_0_15px_rgba(198,40,40,0.2)]",
|
|
251
271
|
getNativeSelectStateStyles(state),
|
|
252
272
|
className
|
|
253
273
|
)} data-sonance-name="select"
|
|
@@ -13,12 +13,13 @@ const Separator = React.forwardRef<
|
|
|
13
13
|
{ className, orientation = "horizontal", decorative = true, ...props },
|
|
14
14
|
ref
|
|
15
15
|
) => (
|
|
16
|
-
<SeparatorPrimitive.Root
|
|
16
|
+
<SeparatorPrimitive.Root
|
|
17
|
+
data-sonance-name="separator"
|
|
17
18
|
ref={ref}
|
|
18
19
|
decorative={decorative}
|
|
19
20
|
orientation={orientation}
|
|
20
21
|
className={cn(
|
|
21
|
-
"shrink-0 bg-
|
|
22
|
+
"shrink-0 bg-black/8 dark:bg-white/8",
|
|
22
23
|
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
23
24
|
className
|
|
24
25
|
)}
|
|
@@ -29,4 +30,3 @@ const Separator = React.forwardRef<
|
|
|
29
30
|
Separator.displayName = SeparatorPrimitive.Root.displayName
|
|
30
31
|
|
|
31
32
|
export { Separator }
|
|
32
|
-
|
|
@@ -21,7 +21,7 @@ const SheetOverlay = React.forwardRef<
|
|
|
21
21
|
>(({ className, ...props }, ref) => (
|
|
22
22
|
<SheetPrimitive.Overlay
|
|
23
23
|
className={cn(
|
|
24
|
-
"fixed inset-0 z-50 bg-black/
|
|
24
|
+
"fixed inset-0 z-50 bg-black/60 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
25
25
|
className
|
|
26
26
|
)}
|
|
27
27
|
{...props}
|
|
@@ -31,7 +31,7 @@ const SheetOverlay = React.forwardRef<
|
|
|
31
31
|
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
|
|
32
32
|
|
|
33
33
|
const sheetVariants = cva(
|
|
34
|
-
"fixed z-50 gap-4 bg-
|
|
34
|
+
"fixed z-50 gap-4 bg-white/90 dark:bg-black/80 backdrop-blur-xl p-6 shadow-xl transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500 border-black/10 dark:border-white/10",
|
|
35
35
|
{
|
|
36
36
|
variants: {
|
|
37
37
|
side: {
|
|
@@ -65,7 +65,7 @@ const SheetContent = React.forwardRef<
|
|
|
65
65
|
{...props}
|
|
66
66
|
>
|
|
67
67
|
{children}
|
|
68
|
-
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-
|
|
68
|
+
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-xl p-1.5 opacity-70 transition-all hover:opacity-100 hover:bg-white/50 dark:hover:bg-white/10 focus:outline-none focus:ring-2 focus:ring-[color:var(--sonance-blue)]/30 disabled:pointer-events-none">
|
|
69
69
|
<X className="h-4 w-4" />
|
|
70
70
|
<span id="sheet-content-span-close" className="sr-only">Close</span>
|
|
71
71
|
</SheetPrimitive.Close>
|
|
@@ -116,7 +116,7 @@ const SheetDescription = React.forwardRef<
|
|
|
116
116
|
>(({ className, ...props }, ref) => (
|
|
117
117
|
<SheetPrimitive.Description
|
|
118
118
|
ref={ref}
|
|
119
|
-
className={cn("text-sm text-muted
|
|
119
|
+
className={cn("text-sm text-foreground-muted", className)}
|
|
120
120
|
{...props}
|
|
121
121
|
/>
|
|
122
122
|
))
|
|
@@ -240,7 +240,7 @@ const Sidebar = React.forwardRef<
|
|
|
240
240
|
>
|
|
241
241
|
<div
|
|
242
242
|
data-sidebar="sidebar"
|
|
243
|
-
className="flex h-full w-full flex-col bg-sidebar-background group-data-[variant=floating]:rounded-
|
|
243
|
+
className="flex h-full w-full flex-col bg-sidebar-background group-data-[variant=floating]:rounded-2xl group-data-[variant=floating]:border group-data-[variant=floating]:border-black/8 dark:group-data-[variant=floating]:border-white/8 group-data-[variant=floating]:shadow-xl group-data-[variant=floating]:backdrop-blur-lg"
|
|
244
244
|
>
|
|
245
245
|
{children}
|
|
246
246
|
</div>
|
|
@@ -433,7 +433,7 @@ const SidebarGroupLabel = React.forwardRef<
|
|
|
433
433
|
ref={ref}
|
|
434
434
|
data-sidebar="group-label"
|
|
435
435
|
className={cn(
|
|
436
|
-
"duration-200 flex h-8 shrink-0 items-center rounded-
|
|
436
|
+
"duration-200 flex h-8 shrink-0 items-center rounded-xl px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opa] ease-linear focus-visible:ring-2 focus-visible:ring-[color:var(--sonance-blue)]/30 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
437
437
|
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
|
|
438
438
|
className
|
|
439
439
|
)}
|
|
@@ -454,7 +454,7 @@ const SidebarGroupAction = React.forwardRef<
|
|
|
454
454
|
ref={ref}
|
|
455
455
|
data-sidebar="group-action"
|
|
456
456
|
className={cn(
|
|
457
|
-
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-
|
|
457
|
+
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-lg p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-all hover:bg-white/50 dark:hover:bg-white/10 hover:text-sidebar-accent-foreground focus-visible:ring-2 focus-visible:ring-[color:var(--sonance-blue)]/30 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
458
458
|
// Increases the hit area of the button on mobile.
|
|
459
459
|
"after:absolute after:-inset-2 after:md:hidden",
|
|
460
460
|
"group-data-[collapsible=icon]:hidden",
|
|
@@ -506,13 +506,13 @@ const SidebarMenuItem = React.forwardRef<
|
|
|
506
506
|
SidebarMenuItem.displayName = "SidebarMenuItem"
|
|
507
507
|
|
|
508
508
|
const sidebarMenuButtonVariants = cva(
|
|
509
|
-
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-
|
|
509
|
+
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-xl p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding,background-color] hover:bg-white/50 dark:hover:bg-white/10 hover:text-sidebar-accent-foreground focus-visible:ring-2 focus-visible:ring-[color:var(--sonance-blue)]/30 active:bg-white/60 dark:active:bg-white/15 active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-white/50 dark:data-[active=true]:bg-white/10 data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-white/50 dark:data-[state=open]:hover:bg-white/10 data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
|
|
510
510
|
{
|
|
511
511
|
variants: {
|
|
512
512
|
variant: {
|
|
513
|
-
default: "hover:bg-
|
|
513
|
+
default: "hover:bg-white/50 dark:hover:bg-white/10 hover:text-sidebar-accent-foreground",
|
|
514
514
|
outline:
|
|
515
|
-
"bg-
|
|
515
|
+
"bg-white/60 dark:bg-white/5 border border-black/8 dark:border-white/8 hover:bg-white/70 dark:hover:bg-white/10 hover:text-sidebar-accent-foreground",
|
|
516
516
|
},
|
|
517
517
|
size: {
|
|
518
518
|
default: "h-8 text-sm",
|
|
@@ -600,7 +600,7 @@ const SidebarMenuAction = React.forwardRef<
|
|
|
600
600
|
ref={ref}
|
|
601
601
|
data-sidebar="menu-action"
|
|
602
602
|
className={cn(
|
|
603
|
-
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-
|
|
603
|
+
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-lg p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-all hover:bg-white/50 dark:hover:bg-white/10 hover:text-sidebar-accent-foreground focus-visible:ring-2 focus-visible:ring-[color:var(--sonance-blue)]/30 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
|
|
604
604
|
// Increases the hit area of the button on mobile.
|
|
605
605
|
"after:absolute after:-inset-2 after:md:hidden",
|
|
606
606
|
"peer-data-[size=sm]/menu-button:top-1",
|
|
@@ -684,7 +684,7 @@ const SidebarMenuSub = React.forwardRef<
|
|
|
684
684
|
ref={ref}
|
|
685
685
|
data-sidebar="menu-sub"
|
|
686
686
|
className={cn(
|
|
687
|
-
"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-
|
|
687
|
+
"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-black/8 dark:border-white/8 px-2.5 py-0.5",
|
|
688
688
|
"group-data-[collapsible=icon]:hidden",
|
|
689
689
|
className
|
|
690
690
|
)} data-sonance-name="sidebar"
|
|
@@ -716,8 +716,8 @@ const SidebarMenuSubButton = React.forwardRef<
|
|
|
716
716
|
data-size={size}
|
|
717
717
|
data-active={isActive}
|
|
718
718
|
className={cn(
|
|
719
|
-
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-
|
|
720
|
-
"data-[active=true]:bg-
|
|
719
|
+
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-xl px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-white/50 dark:hover:bg-white/10 hover:text-sidebar-accent-foreground focus-visible:ring-2 focus-visible:ring-[color:var(--sonance-blue)]/30 active:bg-white/60 dark:active:bg-white/15 active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
|
|
720
|
+
"data-[active=true]:bg-white/50 dark:data-[active=true]:bg-white/10 data-[active=true]:text-sidebar-accent-foreground",
|
|
721
721
|
size === "sm" && "text-xs",
|
|
722
722
|
size === "md" && "text-sm",
|
|
723
723
|
"group-data-[collapsible=icon]:hidden",
|
|
@@ -15,16 +15,18 @@ export function Skeleton({
|
|
|
15
15
|
...props
|
|
16
16
|
}: SkeletonProps) {
|
|
17
17
|
const variantClasses = {
|
|
18
|
-
text: "rounded",
|
|
18
|
+
text: "rounded-lg",
|
|
19
19
|
circular: "rounded-full",
|
|
20
|
-
rectangular: "rounded-
|
|
20
|
+
rectangular: "rounded-xl",
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
24
|
<div
|
|
25
25
|
data-sonance-name="skeleton"
|
|
26
26
|
className={cn(
|
|
27
|
-
"animate-pulse
|
|
27
|
+
"animate-pulse",
|
|
28
|
+
"bg-white/50 dark:bg-white/[0.03]",
|
|
29
|
+
"backdrop-blur-sm",
|
|
28
30
|
variantClasses[variant],
|
|
29
31
|
className
|
|
30
32
|
)}
|
|
@@ -74,7 +76,13 @@ export function SkeletonAvatar({
|
|
|
74
76
|
|
|
75
77
|
export function SkeletonCard({ className }: { className?: string }) {
|
|
76
78
|
return (
|
|
77
|
-
<div
|
|
79
|
+
<div
|
|
80
|
+
className={cn(
|
|
81
|
+
"border border-black/8 dark:border-white/8 rounded-2xl p-4 space-y-4",
|
|
82
|
+
"bg-white/30 dark:bg-white/[0.02] backdrop-blur-sm",
|
|
83
|
+
className
|
|
84
|
+
)}
|
|
85
|
+
>
|
|
78
86
|
<Skeleton className="h-40 w-full" />
|
|
79
87
|
<div className="space-y-2">
|
|
80
88
|
<Skeleton className="h-4 w-3/4" />
|
|
@@ -96,7 +104,7 @@ export function SkeletonTable({
|
|
|
96
104
|
return (
|
|
97
105
|
<div className={cn("w-full space-y-2", className)}>
|
|
98
106
|
{/* Header */}
|
|
99
|
-
<div className="flex gap-4 border-b border-border pb-2">
|
|
107
|
+
<div className="flex gap-4 border-b border-black/8 dark:border-white/8 pb-2">
|
|
100
108
|
{Array.from({ length: columns }).map((_, i) => (
|
|
101
109
|
<Skeleton key={i} className="h-4 flex-1" />
|
|
102
110
|
))}
|