sonance-brand-mcp 1.3.109 → 1.3.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/assets/api/sonance-ai-edit/route.ts +30 -7
  2. package/dist/assets/api/sonance-vision-apply/route.ts +33 -8
  3. package/dist/assets/api/sonance-vision-edit/route.ts +33 -8
  4. package/dist/assets/components/alert.tsx +35 -9
  5. package/dist/assets/components/badge.tsx +49 -20
  6. package/dist/assets/components/button.tsx +29 -20
  7. package/dist/assets/components/card.tsx +87 -33
  8. package/dist/assets/components/checkbox.tsx +36 -12
  9. package/dist/assets/components/dialog.tsx +73 -30
  10. package/dist/assets/components/dropdown-menu.tsx +57 -20
  11. package/dist/assets/components/input.tsx +35 -14
  12. package/dist/assets/components/pagination.tsx +86 -35
  13. package/dist/assets/components/popover.tsx +80 -36
  14. package/dist/assets/components/radio-group.tsx +40 -12
  15. package/dist/assets/components/select.tsx +62 -26
  16. package/dist/assets/components/switch.tsx +41 -13
  17. package/dist/assets/components/tabs.tsx +32 -12
  18. package/dist/assets/components/tooltip.tsx +34 -5
  19. package/dist/assets/dev-tools/SonanceDevTools.tsx +441 -365
  20. package/dist/assets/dev-tools/components/ChatHistory.tsx +141 -0
  21. package/dist/assets/dev-tools/components/ChatInterface.tsx +402 -294
  22. package/dist/assets/dev-tools/components/ChatTabBar.tsx +82 -0
  23. package/dist/assets/dev-tools/components/InlineDiffPreview.tsx +204 -0
  24. package/dist/assets/dev-tools/components/InspectorOverlay.tsx +12 -9
  25. package/dist/assets/dev-tools/components/PropertiesPanel.tsx +695 -0
  26. package/dist/assets/dev-tools/components/VisionModeBorder.tsx +16 -7
  27. package/dist/assets/dev-tools/constants.ts +38 -6
  28. package/dist/assets/dev-tools/hooks/useComputedStyles.ts +365 -0
  29. package/dist/assets/dev-tools/index.ts +3 -0
  30. package/dist/assets/dev-tools/panels/AnalysisPanel.tsx +32 -32
  31. package/dist/assets/dev-tools/panels/ComponentsPanel.tsx +277 -127
  32. package/dist/assets/dev-tools/types.ts +51 -2
  33. package/dist/index.js +22 -3
  34. package/package.json +2 -1
@@ -1,49 +1,90 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
1
2
  import { cn } from "@/lib/utils";
2
3
  import { forwardRef } from "react";
3
4
 
4
5
  export type CardState = "default" | "hover" | "focus";
5
6
 
6
- interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
7
- variant?: "default" | "elevated";
7
+ const cardVariants = cva(
8
+ "bg-card border border-card-border transition-all duration-200",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "hover:border-border-hover hover:bg-card-hover",
13
+ elevated: "shadow-md hover:shadow-lg",
14
+ glass: "bg-card/80 backdrop-blur-sm border-white/10 hover:bg-card/90",
15
+ },
16
+ size: {
17
+ compact: "rounded-lg",
18
+ default: "rounded-xl",
19
+ spacious: "rounded-2xl",
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ variant: "default",
24
+ size: "default",
25
+ },
26
+ }
27
+ );
28
+
29
+ const cardPaddingSizes = {
30
+ compact: "p-3",
31
+ default: "p-4",
32
+ spacious: "p-6",
33
+ };
34
+
35
+ interface CardProps extends React.HTMLAttributes<HTMLDivElement>,
36
+ VariantProps<typeof cardVariants> {
8
37
  /** Visual state for Storybook/Figma documentation */
9
38
  state?: CardState;
10
39
  }
11
40
 
12
41
  // State styles for Storybook/Figma visualization
13
- const getStateStyles = (variant: string, state?: CardState) => {
42
+ const getStateStyles = (variant: string | null | undefined, state?: CardState) => {
14
43
  if (!state || state === "default") return "";
15
44
 
16
45
  if (variant === "elevated") {
17
46
  const stateMap: Record<string, string> = {
18
47
  hover: "shadow-lg",
19
- focus: "ring-2 ring-border-focus ring-offset-2 ring-offset-background",
48
+ focus: "ring-2 ring-primary/20 ring-offset-2 ring-offset-background",
49
+ };
50
+ return stateMap[state] || "";
51
+ }
52
+
53
+ if (variant === "glass") {
54
+ const stateMap: Record<string, string> = {
55
+ hover: "bg-card/90",
56
+ focus: "ring-2 ring-primary/20 ring-offset-2 ring-offset-background",
20
57
  };
21
58
  return stateMap[state] || "";
22
59
  }
23
60
 
24
61
  const stateMap: Record<string, string> = {
25
62
  hover: "border-border-hover bg-card-hover",
26
- focus: "ring-2 ring-border-focus ring-offset-2 ring-offset-background",
63
+ focus: "ring-2 ring-primary/20 ring-offset-2 ring-offset-background",
27
64
  };
28
65
 
29
66
  return stateMap[state] || "";
30
67
  };
31
68
 
69
+ // Create a context for passing size to children
70
+ import { createContext, useContext } from "react";
71
+ const CardSizeContext = createContext<"compact" | "default" | "spacious">("default");
72
+
32
73
  export const Card = forwardRef<HTMLDivElement, CardProps>(
33
- ({ className, variant = "default", state, ...props }, ref) => {
74
+ ({ className, variant, size = "default", state, ...props }, ref) => {
34
75
  return (
35
- <div
36
- data-sonance-name="card"
37
- ref={ref}
38
- className={cn(
39
- "bg-card border border-card-border transition-all duration-200",
40
- variant === "elevated" && "shadow-md hover:shadow-lg",
41
- variant === "default" && "hover:border-border-hover hover:bg-card-hover",
42
- getStateStyles(variant, state),
43
- className
44
- )}
45
- {...props}
46
- />
76
+ <CardSizeContext.Provider value={size || "default"}>
77
+ <div
78
+ data-sonance-name="card"
79
+ ref={ref}
80
+ className={cn(
81
+ cardVariants({ variant, size }),
82
+ getStateStyles(variant, state),
83
+ className
84
+ )}
85
+ {...props}
86
+ />
87
+ </CardSizeContext.Provider>
47
88
  );
48
89
  }
49
90
  );
@@ -53,9 +94,12 @@ Card.displayName = "Card";
53
94
  export const CardHeader = forwardRef<
54
95
  HTMLDivElement,
55
96
  React.HTMLAttributes<HTMLDivElement>
56
- >(({ className, ...props }, ref) => (
57
- <div ref={ref} className={cn("p-6", className)} data-sonance-name="card" {...props} />
58
- ));
97
+ >(({ className, ...props }, ref) => {
98
+ const size = useContext(CardSizeContext);
99
+ return (
100
+ <div ref={ref} className={cn(cardPaddingSizes[size], className)} data-sonance-name="card" {...props} />
101
+ );
102
+ });
59
103
 
60
104
  CardHeader.displayName = "CardHeader";
61
105
 
@@ -66,7 +110,7 @@ export const CardTitle = forwardRef<
66
110
  <h3
67
111
  id="card-title-h3"
68
112
  ref={ref}
69
- className={cn("text-lg font-medium text-foreground", className)}
113
+ className={cn("text-base font-medium text-foreground", className)}
70
114
  {...props}
71
115
  />
72
116
  ));
@@ -91,22 +135,32 @@ CardDescription.displayName = "CardDescription";
91
135
  export const CardContent = forwardRef<
92
136
  HTMLDivElement,
93
137
  React.HTMLAttributes<HTMLDivElement>
94
- >(({ className, ...props }, ref) => (
95
- <div ref={ref} className={cn("p-6 pt-0", className)} data-sonance-name="card" {...props} />
96
- ));
138
+ >(({ className, ...props }, ref) => {
139
+ const size = useContext(CardSizeContext);
140
+ const paddingClass = size === "compact" ? "px-3 pb-3" : size === "spacious" ? "px-6 pb-6" : "px-4 pb-4";
141
+ return (
142
+ <div ref={ref} className={cn(paddingClass, "pt-0", className)} data-sonance-name="card" {...props} />
143
+ );
144
+ });
97
145
 
98
146
  CardContent.displayName = "CardContent";
99
147
 
100
148
  export const CardFooter = forwardRef<
101
149
  HTMLDivElement,
102
150
  React.HTMLAttributes<HTMLDivElement>
103
- >(({ className, ...props }, ref) => (
104
- <div
105
- ref={ref}
106
- className={cn("flex items-center p-6 pt-0", className)}
107
- data-sonance-name="card"
108
- {...props}
109
- />
110
- ));
151
+ >(({ className, ...props }, ref) => {
152
+ const size = useContext(CardSizeContext);
153
+ const paddingClass = size === "compact" ? "px-3 pb-3" : size === "spacious" ? "px-6 pb-6" : "px-4 pb-4";
154
+ return (
155
+ <div
156
+ ref={ref}
157
+ className={cn("flex items-center pt-0", paddingClass, className)}
158
+ data-sonance-name="card"
159
+ {...props}
160
+ />
161
+ );
162
+ });
111
163
 
112
164
  CardFooter.displayName = "CardFooter";
165
+
166
+ export { cardVariants };
@@ -2,11 +2,37 @@
2
2
 
3
3
  import { forwardRef, useId } from "react";
4
4
  import { Check } from "lucide-react";
5
+ import { cva, type VariantProps } from "class-variance-authority";
5
6
  import { cn } from "@/lib/utils";
6
7
 
7
8
  export type CheckboxState = "default" | "hover" | "focus" | "checked" | "disabled";
8
9
 
9
- interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> {
10
+ const checkboxVariants = cva(
11
+ "peer shrink-0 appearance-none border border-border bg-input transition-all duration-150 hover:border-border-hover checked:border-primary checked:bg-primary focus:outline-none focus:ring-2 focus:ring-primary/20 focus:ring-offset-2 focus:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
12
+ {
13
+ variants: {
14
+ size: {
15
+ xs: "h-3.5 w-3.5 rounded",
16
+ sm: "h-4 w-4 rounded-md",
17
+ md: "h-5 w-5 rounded-md",
18
+ lg: "h-6 w-6 rounded-lg",
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ size: "sm",
23
+ },
24
+ }
25
+ );
26
+
27
+ const checkIconSizes = {
28
+ xs: "h-2.5 w-2.5",
29
+ sm: "h-3 w-3",
30
+ md: "h-3.5 w-3.5",
31
+ lg: "h-4 w-4",
32
+ };
33
+
34
+ interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size">,
35
+ VariantProps<typeof checkboxVariants> {
10
36
  label?: string;
11
37
  description?: string;
12
38
  /** Visual state for Storybook/Figma documentation */
@@ -21,7 +47,7 @@ const getStateStyles = (state?: CheckboxState) => {
21
47
 
22
48
  const stateMap: Record<string, string> = {
23
49
  hover: "border-border-hover",
24
- focus: "ring-2 ring-border-focus ring-offset-2 ring-offset-background",
50
+ focus: "ring-2 ring-primary/20 ring-offset-2 ring-offset-background",
25
51
  checked: "border-primary bg-primary",
26
52
  disabled: "opacity-50 cursor-not-allowed",
27
53
  };
@@ -30,7 +56,7 @@ const getStateStyles = (state?: CheckboxState) => {
30
56
  };
31
57
 
32
58
  export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
33
- ({ className, label, description, id, state, disabled, checked, defaultChecked, onChange, onCheckedChange, style, ...props }, ref) => {
59
+ ({ className, label, description, id, state, disabled, checked, defaultChecked, onChange, onCheckedChange, style, size = "sm", ...props }, ref) => {
34
60
  const uniqueId = useId();
35
61
  const inputId = id || `checkbox-${uniqueId}`;
36
62
  const isDisabled = disabled || state === "disabled";
@@ -46,7 +72,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
46
72
  };
47
73
 
48
74
  return (
49
- <label data-sonance-name="checkbox" className="flex items-start gap-3 cursor-pointer">
75
+ <label data-sonance-name="checkbox" className="flex items-start gap-2.5 cursor-pointer">
50
76
  <div className="relative flex items-center justify-center">
51
77
  <input
52
78
  type="checkbox"
@@ -61,12 +87,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
61
87
  )}
62
88
  readOnly={isControlled && !onChange && !onCheckedChange}
63
89
  className={cn(
64
- "peer h-5 w-5 shrink-0 appearance-none border border-border bg-input",
65
- "hover:border-border-hover",
66
- "checked:border-primary checked:bg-primary",
67
- "focus:outline-none focus:ring-2 focus:ring-border-focus focus:ring-offset-2 focus:ring-offset-background",
68
- "disabled:cursor-not-allowed disabled:opacity-50",
69
- "transition-colors duration-150",
90
+ checkboxVariants({ size }),
70
91
  getStateStyles(state),
71
92
  className
72
93
  )}
@@ -74,8 +95,9 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
74
95
  />
75
96
  <Check
76
97
  className={cn(
77
- "pointer-events-none absolute h-3.5 w-3.5 text-primary-foreground opacity-0 peer-checked:opacity-100 transition-opacity",
78
- state === "checked" && "opacity-100"
98
+ "pointer-events-none absolute text-primary-foreground opacity-0 peer-checked:opacity-100 transition-all duration-150 peer-checked:scale-100 scale-75",
99
+ checkIconSizes[size || "sm"],
100
+ state === "checked" && "opacity-100 scale-100"
79
101
  )}
80
102
  />
81
103
  </div>
@@ -100,3 +122,5 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
100
122
 
101
123
  Checkbox.displayName = "Checkbox";
102
124
 
125
+ export { checkboxVariants };
126
+
@@ -7,6 +7,7 @@ import { cn } from "@/lib/utils";
7
7
  interface DialogContextValue {
8
8
  open: boolean;
9
9
  onClose: () => void;
10
+ size: "compact" | "default" | "spacious";
10
11
  }
11
12
 
12
13
  const DialogContext = createContext<DialogContextValue | null>(null);
@@ -15,9 +16,11 @@ interface DialogProps {
15
16
  open: boolean;
16
17
  onClose: () => void;
17
18
  children: React.ReactNode;
19
+ /** Size variant for padding */
20
+ size?: "compact" | "default" | "spacious";
18
21
  }
19
22
 
20
- export function Dialog({ open, onClose, children }: DialogProps) {
23
+ export function Dialog({ open, onClose, children, size = "default" }: DialogProps) {
21
24
  // Close on escape
22
25
  useEffect(() => {
23
26
  const handleEscape = (e: KeyboardEvent) => {
@@ -44,15 +47,15 @@ export function Dialog({ open, onClose, children }: DialogProps) {
44
47
  if (!open) return null;
45
48
 
46
49
  return (
47
- <DialogContext.Provider value={{ open, onClose }}>
50
+ <DialogContext.Provider value={{ open, onClose, size }}>
48
51
  <div className="fixed inset-0 z-50 flex items-center justify-center">
49
- {/* Backdrop */}
52
+ {/* Backdrop with blur */}
50
53
  <div
51
- className="absolute inset-0 bg-overlay animate-in fade-in duration-200"
54
+ className="absolute inset-0 bg-overlay/80 backdrop-blur-sm animate-in fade-in duration-200"
52
55
  onClick={onClose}
53
56
  />
54
57
  {/* Content */}
55
- <div className="relative z-10 animate-in zoom-in-95 fade-in duration-200">
58
+ <div className="relative z-10 animate-in zoom-in-95 fade-in-0 duration-200">
56
59
  {children}
57
60
  </div>
58
61
  </div>
@@ -60,6 +63,12 @@ export function Dialog({ open, onClose, children }: DialogProps) {
60
63
  );
61
64
  }
62
65
 
66
+ const dialogPaddingSizes = {
67
+ compact: { x: "px-4", y: "py-3" },
68
+ default: { x: "px-5", y: "py-4" },
69
+ spacious: { x: "px-6", y: "py-5" },
70
+ };
71
+
63
72
  export const DialogContent = forwardRef<
64
73
  HTMLDivElement,
65
74
  React.HTMLAttributes<HTMLDivElement> & { showClose?: boolean }
@@ -67,15 +76,22 @@ export const DialogContent = forwardRef<
67
76
  const context = useContext(DialogContext);
68
77
 
69
78
  return (
70
- <div data-sonance-name="dialog"
79
+ <div
80
+ data-sonance-name="dialog"
81
+ ref={ref}
82
+ className={cn(
83
+ "relative bg-card/95 backdrop-blur-xl border border-border rounded-2xl shadow-2xl",
84
+ "min-w-[320px] max-w-lg",
85
+ className
86
+ )}
71
87
  {...props}
72
88
  >
73
89
  {showClose && context && (
74
90
  <button
75
91
  onClick={context.onClose}
76
- className="absolute right-4 top-4 p-1 text-foreground-muted hover:text-foreground transition-colors"
92
+ className="absolute right-3 top-3 p-1.5 rounded-lg text-foreground-muted hover:text-foreground hover:bg-secondary-hover transition-all duration-150"
77
93
  >
78
- <X className="h-5 w-5" />
94
+ <X className="h-4 w-4" />
79
95
  <span id="dialog-content-span-close" className="sr-only">Close</span>
80
96
  </button>
81
97
  )}
@@ -89,13 +105,20 @@ DialogContent.displayName = "DialogContent";
89
105
  export const DialogHeader = forwardRef<
90
106
  HTMLDivElement,
91
107
  React.HTMLAttributes<HTMLDivElement>
92
- >(({ className, ...props }, ref) => (
93
- <div
94
- ref={ref}
95
- className={cn("px-6 py-4 border-b border-border", className)} data-sonance-name="dialog"
96
- {...props}
97
- />
98
- ));
108
+ >(({ className, ...props }, ref) => {
109
+ const context = useContext(DialogContext);
110
+ const size = context?.size || "default";
111
+ const padding = dialogPaddingSizes[size];
112
+
113
+ return (
114
+ <div
115
+ ref={ref}
116
+ className={cn(padding.x, padding.y, "border-b border-border", className)}
117
+ data-sonance-name="dialog"
118
+ {...props}
119
+ />
120
+ );
121
+ });
99
122
 
100
123
  DialogHeader.displayName = "DialogHeader";
101
124
 
@@ -106,7 +129,7 @@ export const DialogTitle = forwardRef<
106
129
  <h2
107
130
  id="dialog-title-h2"
108
131
  ref={ref}
109
- className={cn("text-lg font-medium text-foreground", className)}
132
+ className={cn("text-base font-medium text-foreground", className)}
110
133
  {...props}
111
134
  />
112
135
  ));
@@ -120,7 +143,8 @@ export const DialogDescription = forwardRef<
120
143
  <p
121
144
  id="dialog-description-p"
122
145
  ref={ref}
123
- className={cn("mt-1 text-sm text-foreground-secondary", className)} data-sonance-name="dialog"
146
+ className={cn("mt-1 text-sm text-foreground-muted", className)}
147
+ data-sonance-name="dialog"
124
148
  {...props}
125
149
  />
126
150
  ));
@@ -130,25 +154,44 @@ DialogDescription.displayName = "DialogDescription";
130
154
  export const DialogBody = forwardRef<
131
155
  HTMLDivElement,
132
156
  React.HTMLAttributes<HTMLDivElement>
133
- >(({ className, ...props }, ref) => (
134
- <div ref={ref} className={cn("px-6 py-4", className)} data-sonance-name="dialog" {...props} />
135
- ));
157
+ >(({ className, ...props }, ref) => {
158
+ const context = useContext(DialogContext);
159
+ const size = context?.size || "default";
160
+ const padding = dialogPaddingSizes[size];
161
+
162
+ return (
163
+ <div
164
+ ref={ref}
165
+ className={cn(padding.x, padding.y, className)}
166
+ data-sonance-name="dialog"
167
+ {...props}
168
+ />
169
+ );
170
+ });
136
171
 
137
172
  DialogBody.displayName = "DialogBody";
138
173
 
139
174
  export const DialogFooter = forwardRef<
140
175
  HTMLDivElement,
141
176
  React.HTMLAttributes<HTMLDivElement>
142
- >(({ className, ...props }, ref) => (
143
- <div
144
- ref={ref}
145
- className={cn(
146
- "flex items-center justify-end gap-3 px-6 py-4 border-t border-border",
147
- className
148
- )} data-sonance-name="dialog"
149
- {...props}
150
- />
151
- ));
177
+ >(({ className, ...props }, ref) => {
178
+ const context = useContext(DialogContext);
179
+ const size = context?.size || "default";
180
+ const padding = dialogPaddingSizes[size];
181
+
182
+ return (
183
+ <div
184
+ ref={ref}
185
+ className={cn(
186
+ "flex items-center justify-end gap-2.5 border-t border-border",
187
+ padding.x, padding.y,
188
+ className
189
+ )}
190
+ data-sonance-name="dialog"
191
+ {...props}
192
+ />
193
+ );
194
+ });
152
195
 
153
196
  DialogFooter.displayName = "DialogFooter";
154
197
 
@@ -3,8 +3,48 @@
3
3
  import * as React from "react";
4
4
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
5
5
  import { Check, ChevronRight, Circle } from "lucide-react";
6
+ import { cva, type VariantProps } from "class-variance-authority";
6
7
  import { cn } from "@/lib/utils";
7
8
 
9
+ const dropdownMenuContentVariants = cva(
10
+ "z-50 min-w-[8rem] overflow-hidden border p-1 text-foreground shadow-xl data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
11
+ {
12
+ variants: {
13
+ size: {
14
+ xs: "rounded-lg text-xs",
15
+ sm: "rounded-xl text-xs",
16
+ md: "rounded-xl text-sm",
17
+ lg: "rounded-2xl text-sm",
18
+ },
19
+ menuVariant: {
20
+ default: "bg-card border-border",
21
+ glass: "bg-card/95 border-border/50 backdrop-blur-xl",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ size: "sm",
26
+ menuVariant: "glass",
27
+ },
28
+ }
29
+ );
30
+
31
+ const dropdownMenuItemVariants = cva(
32
+ "relative flex cursor-default select-none items-center outline-none transition-all duration-150 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
33
+ {
34
+ variants: {
35
+ size: {
36
+ xs: "rounded-md px-2 py-1 text-xs",
37
+ sm: "rounded-lg px-2.5 py-1.5 text-xs",
38
+ md: "rounded-lg px-3 py-2 text-sm",
39
+ lg: "rounded-xl px-3.5 py-2.5 text-sm",
40
+ },
41
+ },
42
+ defaultVariants: {
43
+ size: "sm",
44
+ },
45
+ }
46
+ );
47
+
8
48
  const DropdownMenu = DropdownMenuPrimitive.Root;
9
49
  const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
10
50
  const DropdownMenuGroup = DropdownMenuPrimitive.Group;
@@ -21,7 +61,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
21
61
  <DropdownMenuPrimitive.SubTrigger
22
62
  ref={ref}
23
63
  className={cn(
24
- "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
64
+ "flex cursor-default select-none items-center rounded-lg px-2.5 py-1.5 text-xs outline-none transition-colors duration-150",
25
65
  "focus:bg-secondary-hover focus:text-foreground",
26
66
  "data-[state=open]:bg-secondary-hover data-[state=open]:text-foreground",
27
67
  inset && "pl-8",
@@ -30,7 +70,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
30
70
  {...props}
31
71
  >
32
72
  {children}
33
- <ChevronRight className="ml-auto h-4 w-4" />
73
+ <ChevronRight className="ml-auto h-3.5 w-3.5" />
34
74
  </DropdownMenuPrimitive.SubTrigger>
35
75
  ));
36
76
  DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
@@ -42,7 +82,7 @@ const DropdownMenuSubContent = React.forwardRef<
42
82
  <DropdownMenuPrimitive.SubContent
43
83
  ref={ref}
44
84
  className={cn(
45
- "z-50 min-w-[8rem] overflow-hidden rounded-sm border border-border bg-card p-1 text-foreground shadow-lg",
85
+ "z-50 min-w-[8rem] overflow-hidden rounded-xl border border-border/50 bg-card/95 backdrop-blur-xl p-1 text-foreground shadow-xl",
46
86
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
47
87
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
48
88
  "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
@@ -57,23 +97,20 @@ const DropdownMenuSubContent = React.forwardRef<
57
97
  ));
58
98
  DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
59
99
 
100
+ interface DropdownMenuContentProps
101
+ extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>,
102
+ VariantProps<typeof dropdownMenuContentVariants> {}
103
+
60
104
  const DropdownMenuContent = React.forwardRef<
61
105
  React.ElementRef<typeof DropdownMenuPrimitive.Content>,
62
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
63
- >(({ className, sideOffset = 4, ...props }, ref) => (
106
+ DropdownMenuContentProps
107
+ >(({ className, sideOffset = 4, size, menuVariant, ...props }, ref) => (
64
108
  <DropdownMenuPrimitive.Portal>
65
109
  <DropdownMenuPrimitive.Content
66
110
  ref={ref}
67
111
  sideOffset={sideOffset}
68
112
  className={cn(
69
- "z-50 min-w-[8rem] overflow-hidden rounded-sm border border-border bg-card p-1 text-foreground shadow-md",
70
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
71
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
72
- "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
73
- "data-[side=bottom]:slide-in-from-top-2",
74
- "data-[side=left]:slide-in-from-right-2",
75
- "data-[side=right]:slide-in-from-left-2",
76
- "data-[side=top]:slide-in-from-bottom-2",
113
+ dropdownMenuContentVariants({ size, menuVariant }),
77
114
  className
78
115
  )}
79
116
  {...props}
@@ -91,9 +128,8 @@ const DropdownMenuItem = React.forwardRef<
91
128
  <DropdownMenuPrimitive.Item
92
129
  ref={ref}
93
130
  className={cn(
94
- "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors",
131
+ dropdownMenuItemVariants({ size: "sm" }),
95
132
  "focus:bg-secondary-hover focus:text-foreground",
96
- "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
97
133
  inset && "pl-8",
98
134
  className
99
135
  )}
@@ -109,7 +145,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
109
145
  <DropdownMenuPrimitive.CheckboxItem
110
146
  ref={ref}
111
147
  className={cn(
112
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors",
148
+ "relative flex cursor-default select-none items-center rounded-lg py-1.5 pl-8 pr-2.5 text-xs outline-none transition-all duration-150",
113
149
  "focus:bg-secondary-hover focus:text-foreground",
114
150
  "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
115
151
  className
@@ -119,7 +155,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
119
155
  >
120
156
  <span id="dropdown-menu-checkbox-item-span" className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
121
157
  <DropdownMenuPrimitive.ItemIndicator>
122
- <Check className="h-4 w-4" />
158
+ <Check className="h-3.5 w-3.5" />
123
159
  </DropdownMenuPrimitive.ItemIndicator>
124
160
  </span>
125
161
  {children}
@@ -134,7 +170,7 @@ const DropdownMenuRadioItem = React.forwardRef<
134
170
  <DropdownMenuPrimitive.RadioItem
135
171
  ref={ref}
136
172
  className={cn(
137
- "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors",
173
+ "relative flex cursor-default select-none items-center rounded-lg py-1.5 pl-8 pr-2.5 text-xs outline-none transition-all duration-150",
138
174
  "focus:bg-secondary-hover focus:text-foreground",
139
175
  "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
140
176
  className
@@ -160,7 +196,7 @@ const DropdownMenuLabel = React.forwardRef<
160
196
  <DropdownMenuPrimitive.Label
161
197
  ref={ref}
162
198
  className={cn(
163
- "px-2 py-1.5 text-xs font-medium uppercase tracking-widest text-foreground-muted",
199
+ "px-2.5 py-1.5 text-[10px] font-medium uppercase tracking-wide text-foreground-muted",
164
200
  inset && "pl-8",
165
201
  className
166
202
  )}
@@ -209,5 +245,6 @@ export {
209
245
  DropdownMenuSubContent,
210
246
  DropdownMenuSubTrigger,
211
247
  DropdownMenuRadioGroup,
248
+ dropdownMenuContentVariants,
249
+ dropdownMenuItemVariants,
212
250
  };
213
-