sonance-brand-mcp 1.2.4 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/components/alert-dialog.stories.tsx +142 -0
- package/dist/assets/components/alert-dialog.tsx +142 -0
- package/dist/assets/components/aspect-ratio.stories.tsx +67 -0
- package/dist/assets/components/aspect-ratio.tsx +8 -0
- package/dist/assets/components/avatar.tsx +64 -20
- package/dist/assets/components/carousel.stories.tsx +158 -0
- package/dist/assets/components/carousel.tsx +262 -0
- package/dist/assets/components/chart.stories.tsx +376 -0
- package/dist/assets/components/chart.tsx +384 -0
- package/dist/assets/components/checkbox.tsx +12 -2
- package/dist/assets/components/code.tsx +22 -20
- 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 +170 -0
- package/dist/assets/components/context-menu.stories.tsx +159 -0
- package/dist/assets/components/context-menu.tsx +218 -0
- package/dist/assets/components/divider.tsx +38 -35
- package/dist/assets/components/dropdown-menu.tsx +217 -0
- package/dist/assets/components/hover-card.stories.tsx +113 -0
- package/dist/assets/components/hover-card.tsx +35 -0
- package/dist/assets/components/kbd.tsx +6 -6
- package/dist/assets/components/menubar.stories.tsx +208 -0
- package/dist/assets/components/menubar.tsx +251 -0
- package/dist/assets/components/navigation-menu.stories.tsx +237 -0
- package/dist/assets/components/navigation-menu.tsx +135 -0
- 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.tsx +29 -7
- package/dist/assets/components/separator.tsx +32 -0
- package/dist/assets/components/sheet.tsx +141 -0
- package/dist/assets/components/sidebar.stories.tsx +351 -0
- package/dist/assets/components/sidebar.tsx +760 -0
- 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.tsx +23 -90
- package/dist/assets/globals.css +30 -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/index.js +416 -17
- package/package.json +1 -1
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
|
|
5
|
+
import { Check, ChevronRight, Circle } from "lucide-react";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
const ContextMenu = ContextMenuPrimitive.Root;
|
|
9
|
+
const ContextMenuTrigger = ContextMenuPrimitive.Trigger;
|
|
10
|
+
const ContextMenuGroup = ContextMenuPrimitive.Group;
|
|
11
|
+
const ContextMenuPortal = ContextMenuPrimitive.Portal;
|
|
12
|
+
const ContextMenuSub = ContextMenuPrimitive.Sub;
|
|
13
|
+
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
|
|
14
|
+
|
|
15
|
+
const ContextMenuSubTrigger = React.forwardRef<
|
|
16
|
+
React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
|
|
17
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
|
|
18
|
+
inset?: boolean;
|
|
19
|
+
}
|
|
20
|
+
>(({ className, inset, children, ...props }, ref) => (
|
|
21
|
+
<ContextMenuPrimitive.SubTrigger
|
|
22
|
+
ref={ref}
|
|
23
|
+
className={cn(
|
|
24
|
+
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
|
|
25
|
+
"focus:bg-secondary-hover focus:text-foreground",
|
|
26
|
+
"data-[state=open]:bg-secondary-hover data-[state=open]:text-foreground",
|
|
27
|
+
inset && "pl-8",
|
|
28
|
+
className
|
|
29
|
+
)}
|
|
30
|
+
{...props}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
<ChevronRight className="ml-auto h-4 w-4" />
|
|
34
|
+
</ContextMenuPrimitive.SubTrigger>
|
|
35
|
+
));
|
|
36
|
+
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
|
|
37
|
+
|
|
38
|
+
const ContextMenuSubContent = React.forwardRef<
|
|
39
|
+
React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
|
|
40
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
|
|
41
|
+
>(({ className, ...props }, ref) => (
|
|
42
|
+
<ContextMenuPrimitive.SubContent
|
|
43
|
+
ref={ref}
|
|
44
|
+
className={cn(
|
|
45
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-sm border border-border bg-card p-1 text-foreground shadow-md",
|
|
46
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
47
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
48
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
49
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
50
|
+
"data-[side=left]:slide-in-from-right-2",
|
|
51
|
+
"data-[side=right]:slide-in-from-left-2",
|
|
52
|
+
"data-[side=top]:slide-in-from-bottom-2",
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
55
|
+
{...props}
|
|
56
|
+
/>
|
|
57
|
+
));
|
|
58
|
+
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
|
59
|
+
|
|
60
|
+
const ContextMenuContent = React.forwardRef<
|
|
61
|
+
React.ElementRef<typeof ContextMenuPrimitive.Content>,
|
|
62
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
|
|
63
|
+
>(({ className, ...props }, ref) => (
|
|
64
|
+
<ContextMenuPrimitive.Portal>
|
|
65
|
+
<ContextMenuPrimitive.Content
|
|
66
|
+
ref={ref}
|
|
67
|
+
className={cn(
|
|
68
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-sm border border-border bg-card p-1 text-foreground shadow-md",
|
|
69
|
+
"animate-in fade-in-80",
|
|
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",
|
|
77
|
+
className
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
</ContextMenuPrimitive.Portal>
|
|
82
|
+
));
|
|
83
|
+
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
|
84
|
+
|
|
85
|
+
const ContextMenuItem = React.forwardRef<
|
|
86
|
+
React.ElementRef<typeof ContextMenuPrimitive.Item>,
|
|
87
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
|
|
88
|
+
inset?: boolean;
|
|
89
|
+
}
|
|
90
|
+
>(({ className, inset, ...props }, ref) => (
|
|
91
|
+
<ContextMenuPrimitive.Item
|
|
92
|
+
ref={ref}
|
|
93
|
+
className={cn(
|
|
94
|
+
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
|
|
95
|
+
"focus:bg-secondary-hover focus:text-foreground",
|
|
96
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
97
|
+
inset && "pl-8",
|
|
98
|
+
className
|
|
99
|
+
)}
|
|
100
|
+
{...props}
|
|
101
|
+
/>
|
|
102
|
+
));
|
|
103
|
+
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
|
|
104
|
+
|
|
105
|
+
const ContextMenuCheckboxItem = React.forwardRef<
|
|
106
|
+
React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
|
|
107
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>
|
|
108
|
+
>(({ className, children, checked, ...props }, ref) => (
|
|
109
|
+
<ContextMenuPrimitive.CheckboxItem
|
|
110
|
+
ref={ref}
|
|
111
|
+
className={cn(
|
|
112
|
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
|
|
113
|
+
"focus:bg-secondary-hover focus:text-foreground",
|
|
114
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
115
|
+
className
|
|
116
|
+
)}
|
|
117
|
+
checked={checked}
|
|
118
|
+
{...props}
|
|
119
|
+
>
|
|
120
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
121
|
+
<ContextMenuPrimitive.ItemIndicator>
|
|
122
|
+
<Check className="h-4 w-4" />
|
|
123
|
+
</ContextMenuPrimitive.ItemIndicator>
|
|
124
|
+
</span>
|
|
125
|
+
{children}
|
|
126
|
+
</ContextMenuPrimitive.CheckboxItem>
|
|
127
|
+
));
|
|
128
|
+
ContextMenuCheckboxItem.displayName =
|
|
129
|
+
ContextMenuPrimitive.CheckboxItem.displayName;
|
|
130
|
+
|
|
131
|
+
const ContextMenuRadioItem = React.forwardRef<
|
|
132
|
+
React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
|
|
133
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>
|
|
134
|
+
>(({ className, children, ...props }, ref) => (
|
|
135
|
+
<ContextMenuPrimitive.RadioItem
|
|
136
|
+
ref={ref}
|
|
137
|
+
className={cn(
|
|
138
|
+
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
|
|
139
|
+
"focus:bg-secondary-hover focus:text-foreground",
|
|
140
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
141
|
+
className
|
|
142
|
+
)}
|
|
143
|
+
{...props}
|
|
144
|
+
>
|
|
145
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
146
|
+
<ContextMenuPrimitive.ItemIndicator>
|
|
147
|
+
<Circle className="h-2 w-2 fill-current" />
|
|
148
|
+
</ContextMenuPrimitive.ItemIndicator>
|
|
149
|
+
</span>
|
|
150
|
+
{children}
|
|
151
|
+
</ContextMenuPrimitive.RadioItem>
|
|
152
|
+
));
|
|
153
|
+
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
|
|
154
|
+
|
|
155
|
+
const ContextMenuLabel = React.forwardRef<
|
|
156
|
+
React.ElementRef<typeof ContextMenuPrimitive.Label>,
|
|
157
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
|
|
158
|
+
inset?: boolean;
|
|
159
|
+
}
|
|
160
|
+
>(({ className, inset, ...props }, ref) => (
|
|
161
|
+
<ContextMenuPrimitive.Label
|
|
162
|
+
ref={ref}
|
|
163
|
+
className={cn(
|
|
164
|
+
"px-2 py-1.5 text-xs font-medium uppercase tracking-widest text-foreground-muted",
|
|
165
|
+
inset && "pl-8",
|
|
166
|
+
className
|
|
167
|
+
)}
|
|
168
|
+
{...props}
|
|
169
|
+
/>
|
|
170
|
+
));
|
|
171
|
+
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
|
|
172
|
+
|
|
173
|
+
const ContextMenuSeparator = React.forwardRef<
|
|
174
|
+
React.ElementRef<typeof ContextMenuPrimitive.Separator>,
|
|
175
|
+
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
|
|
176
|
+
>(({ className, ...props }, ref) => (
|
|
177
|
+
<ContextMenuPrimitive.Separator
|
|
178
|
+
ref={ref}
|
|
179
|
+
className={cn("-mx-1 my-1 h-px bg-border", className)}
|
|
180
|
+
{...props}
|
|
181
|
+
/>
|
|
182
|
+
));
|
|
183
|
+
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
|
|
184
|
+
|
|
185
|
+
const ContextMenuShortcut = ({
|
|
186
|
+
className,
|
|
187
|
+
...props
|
|
188
|
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
189
|
+
return (
|
|
190
|
+
<span
|
|
191
|
+
className={cn(
|
|
192
|
+
"ml-auto text-xs tracking-widest text-foreground-muted",
|
|
193
|
+
className
|
|
194
|
+
)}
|
|
195
|
+
{...props}
|
|
196
|
+
/>
|
|
197
|
+
);
|
|
198
|
+
};
|
|
199
|
+
ContextMenuShortcut.displayName = "ContextMenuShortcut";
|
|
200
|
+
|
|
201
|
+
export {
|
|
202
|
+
ContextMenu,
|
|
203
|
+
ContextMenuTrigger,
|
|
204
|
+
ContextMenuContent,
|
|
205
|
+
ContextMenuItem,
|
|
206
|
+
ContextMenuCheckboxItem,
|
|
207
|
+
ContextMenuRadioItem,
|
|
208
|
+
ContextMenuLabel,
|
|
209
|
+
ContextMenuSeparator,
|
|
210
|
+
ContextMenuShortcut,
|
|
211
|
+
ContextMenuGroup,
|
|
212
|
+
ContextMenuPortal,
|
|
213
|
+
ContextMenuSub,
|
|
214
|
+
ContextMenuSubContent,
|
|
215
|
+
ContextMenuSubTrigger,
|
|
216
|
+
ContextMenuRadioGroup,
|
|
217
|
+
};
|
|
218
|
+
|
|
@@ -1,50 +1,53 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
1
2
|
import { cn } from "@/lib/utils";
|
|
2
3
|
|
|
3
|
-
interface DividerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
export interface DividerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
5
|
orientation?: "horizontal" | "vertical";
|
|
5
6
|
label?: string;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
export
|
|
9
|
-
orientation = "horizontal",
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
)
|
|
23
|
-
|
|
9
|
+
export const Divider = forwardRef<HTMLDivElement, DividerProps>(
|
|
10
|
+
({ orientation = "horizontal", label, className, ...props }, ref) => {
|
|
11
|
+
if (orientation === "vertical") {
|
|
12
|
+
return (
|
|
13
|
+
<div
|
|
14
|
+
ref={ref}
|
|
15
|
+
role="separator"
|
|
16
|
+
aria-orientation="vertical"
|
|
17
|
+
className={cn("h-full w-px bg-border", className)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (label) {
|
|
24
|
+
return (
|
|
25
|
+
<div
|
|
26
|
+
ref={ref}
|
|
27
|
+
role="separator"
|
|
28
|
+
className={cn("flex items-center gap-4", className)}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
<div className="h-px flex-1 bg-border" />
|
|
32
|
+
<span className="text-xs font-medium uppercase tracking-widest text-foreground-muted">
|
|
33
|
+
{label}
|
|
34
|
+
</span>
|
|
35
|
+
<div className="h-px flex-1 bg-border" />
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
24
39
|
|
|
25
|
-
if (label) {
|
|
26
40
|
return (
|
|
27
41
|
<div
|
|
42
|
+
ref={ref}
|
|
28
43
|
role="separator"
|
|
29
|
-
|
|
44
|
+
aria-orientation="horizontal"
|
|
45
|
+
className={cn("h-px w-full bg-border", className)}
|
|
30
46
|
{...props}
|
|
31
|
-
|
|
32
|
-
<div className="h-px flex-1 bg-border" />
|
|
33
|
-
<span className="text-xs font-medium uppercase tracking-widest text-foreground-muted">
|
|
34
|
-
{label}
|
|
35
|
-
</span>
|
|
36
|
-
<div className="h-px flex-1 bg-border" />
|
|
37
|
-
</div>
|
|
47
|
+
/>
|
|
38
48
|
);
|
|
39
49
|
}
|
|
50
|
+
);
|
|
40
51
|
|
|
41
|
-
|
|
42
|
-
<div
|
|
43
|
-
role="separator"
|
|
44
|
-
aria-orientation="horizontal"
|
|
45
|
-
className={cn("h-px w-full bg-border", className)}
|
|
46
|
-
{...props}
|
|
47
|
-
/>
|
|
48
|
-
);
|
|
49
|
-
}
|
|
52
|
+
Divider.displayName = "Divider";
|
|
50
53
|
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
5
|
+
import { Check, ChevronRight, Circle } from "lucide-react";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
9
|
+
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
10
|
+
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
11
|
+
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
|
12
|
+
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
13
|
+
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
14
|
+
|
|
15
|
+
const DropdownMenuSubTrigger = React.forwardRef<
|
|
16
|
+
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
|
17
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
18
|
+
inset?: boolean;
|
|
19
|
+
}
|
|
20
|
+
>(({ className, inset, children, ...props }, ref) => (
|
|
21
|
+
<DropdownMenuPrimitive.SubTrigger
|
|
22
|
+
ref={ref}
|
|
23
|
+
className={cn(
|
|
24
|
+
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
|
|
25
|
+
"focus:bg-secondary-hover focus:text-foreground",
|
|
26
|
+
"data-[state=open]:bg-secondary-hover data-[state=open]:text-foreground",
|
|
27
|
+
inset && "pl-8",
|
|
28
|
+
className
|
|
29
|
+
)}
|
|
30
|
+
{...props}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
<ChevronRight className="ml-auto h-4 w-4" />
|
|
34
|
+
</DropdownMenuPrimitive.SubTrigger>
|
|
35
|
+
));
|
|
36
|
+
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
|
|
37
|
+
|
|
38
|
+
const DropdownMenuSubContent = React.forwardRef<
|
|
39
|
+
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
|
40
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
|
41
|
+
>(({ className, ...props }, ref) => (
|
|
42
|
+
<DropdownMenuPrimitive.SubContent
|
|
43
|
+
ref={ref}
|
|
44
|
+
className={cn(
|
|
45
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-sm border border-border bg-card p-1 text-foreground shadow-lg",
|
|
46
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
47
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
48
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
49
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
50
|
+
"data-[side=left]:slide-in-from-right-2",
|
|
51
|
+
"data-[side=right]:slide-in-from-left-2",
|
|
52
|
+
"data-[side=top]:slide-in-from-bottom-2",
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
55
|
+
{...props}
|
|
56
|
+
/>
|
|
57
|
+
));
|
|
58
|
+
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
|
|
59
|
+
|
|
60
|
+
const DropdownMenuContent = React.forwardRef<
|
|
61
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
|
62
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
|
63
|
+
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
64
|
+
<DropdownMenuPrimitive.Portal>
|
|
65
|
+
<DropdownMenuPrimitive.Content
|
|
66
|
+
ref={ref}
|
|
67
|
+
sideOffset={sideOffset}
|
|
68
|
+
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",
|
|
77
|
+
className
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
</DropdownMenuPrimitive.Portal>
|
|
82
|
+
));
|
|
83
|
+
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
84
|
+
|
|
85
|
+
const DropdownMenuItem = React.forwardRef<
|
|
86
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
|
87
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
|
88
|
+
inset?: boolean;
|
|
89
|
+
}
|
|
90
|
+
>(({ className, inset, ...props }, ref) => (
|
|
91
|
+
<DropdownMenuPrimitive.Item
|
|
92
|
+
ref={ref}
|
|
93
|
+
className={cn(
|
|
94
|
+
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors",
|
|
95
|
+
"focus:bg-secondary-hover focus:text-foreground",
|
|
96
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
97
|
+
inset && "pl-8",
|
|
98
|
+
className
|
|
99
|
+
)}
|
|
100
|
+
{...props}
|
|
101
|
+
/>
|
|
102
|
+
));
|
|
103
|
+
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
104
|
+
|
|
105
|
+
const DropdownMenuCheckboxItem = React.forwardRef<
|
|
106
|
+
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
|
107
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
|
108
|
+
>(({ className, children, checked, ...props }, ref) => (
|
|
109
|
+
<DropdownMenuPrimitive.CheckboxItem
|
|
110
|
+
ref={ref}
|
|
111
|
+
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",
|
|
113
|
+
"focus:bg-secondary-hover focus:text-foreground",
|
|
114
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
115
|
+
className
|
|
116
|
+
)}
|
|
117
|
+
checked={checked}
|
|
118
|
+
{...props}
|
|
119
|
+
>
|
|
120
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
121
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
122
|
+
<Check className="h-4 w-4" />
|
|
123
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
124
|
+
</span>
|
|
125
|
+
{children}
|
|
126
|
+
</DropdownMenuPrimitive.CheckboxItem>
|
|
127
|
+
));
|
|
128
|
+
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
|
|
129
|
+
|
|
130
|
+
const DropdownMenuRadioItem = React.forwardRef<
|
|
131
|
+
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
|
132
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
|
133
|
+
>(({ className, children, ...props }, ref) => (
|
|
134
|
+
<DropdownMenuPrimitive.RadioItem
|
|
135
|
+
ref={ref}
|
|
136
|
+
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",
|
|
138
|
+
"focus:bg-secondary-hover focus:text-foreground",
|
|
139
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
140
|
+
className
|
|
141
|
+
)}
|
|
142
|
+
{...props}
|
|
143
|
+
>
|
|
144
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
145
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
146
|
+
<Circle className="h-2 w-2 fill-current" />
|
|
147
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
148
|
+
</span>
|
|
149
|
+
{children}
|
|
150
|
+
</DropdownMenuPrimitive.RadioItem>
|
|
151
|
+
));
|
|
152
|
+
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
|
153
|
+
|
|
154
|
+
const DropdownMenuLabel = React.forwardRef<
|
|
155
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
|
156
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
|
157
|
+
inset?: boolean;
|
|
158
|
+
}
|
|
159
|
+
>(({ className, inset, ...props }, ref) => (
|
|
160
|
+
<DropdownMenuPrimitive.Label
|
|
161
|
+
ref={ref}
|
|
162
|
+
className={cn(
|
|
163
|
+
"px-2 py-1.5 text-xs font-medium uppercase tracking-widest text-foreground-muted",
|
|
164
|
+
inset && "pl-8",
|
|
165
|
+
className
|
|
166
|
+
)}
|
|
167
|
+
{...props}
|
|
168
|
+
/>
|
|
169
|
+
));
|
|
170
|
+
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
|
171
|
+
|
|
172
|
+
const DropdownMenuSeparator = React.forwardRef<
|
|
173
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
|
174
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
|
175
|
+
>(({ className, ...props }, ref) => (
|
|
176
|
+
<DropdownMenuPrimitive.Separator
|
|
177
|
+
ref={ref}
|
|
178
|
+
className={cn("-mx-1 my-1 h-px bg-border", className)}
|
|
179
|
+
{...props}
|
|
180
|
+
/>
|
|
181
|
+
));
|
|
182
|
+
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
|
183
|
+
|
|
184
|
+
const DropdownMenuShortcut = ({
|
|
185
|
+
className,
|
|
186
|
+
...props
|
|
187
|
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
188
|
+
return (
|
|
189
|
+
<span
|
|
190
|
+
className={cn(
|
|
191
|
+
"ml-auto text-xs tracking-widest text-foreground-muted",
|
|
192
|
+
className
|
|
193
|
+
)}
|
|
194
|
+
{...props}
|
|
195
|
+
/>
|
|
196
|
+
);
|
|
197
|
+
};
|
|
198
|
+
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
|
199
|
+
|
|
200
|
+
export {
|
|
201
|
+
DropdownMenu,
|
|
202
|
+
DropdownMenuTrigger,
|
|
203
|
+
DropdownMenuContent,
|
|
204
|
+
DropdownMenuItem,
|
|
205
|
+
DropdownMenuCheckboxItem,
|
|
206
|
+
DropdownMenuRadioItem,
|
|
207
|
+
DropdownMenuLabel,
|
|
208
|
+
DropdownMenuSeparator,
|
|
209
|
+
DropdownMenuShortcut,
|
|
210
|
+
DropdownMenuGroup,
|
|
211
|
+
DropdownMenuPortal,
|
|
212
|
+
DropdownMenuSub,
|
|
213
|
+
DropdownMenuSubContent,
|
|
214
|
+
DropdownMenuSubTrigger,
|
|
215
|
+
DropdownMenuRadioGroup,
|
|
216
|
+
};
|
|
217
|
+
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { CalendarDays } from "lucide-react";
|
|
3
|
+
import { HoverCard, HoverCardContent, HoverCardTrigger } from "./hover-card";
|
|
4
|
+
import { Avatar } from "./avatar";
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof HoverCard> = {
|
|
7
|
+
title: "Components/Overlays/HoverCard",
|
|
8
|
+
component: HoverCard,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "centered",
|
|
11
|
+
},
|
|
12
|
+
tags: ["autodocs"],
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
type Story = StoryObj<typeof HoverCard>;
|
|
17
|
+
|
|
18
|
+
export const Default: Story = {
|
|
19
|
+
render: () => (
|
|
20
|
+
<HoverCard>
|
|
21
|
+
<HoverCardTrigger asChild>
|
|
22
|
+
<a
|
|
23
|
+
href="#"
|
|
24
|
+
className="text-sm font-medium text-primary underline underline-offset-4"
|
|
25
|
+
>
|
|
26
|
+
@sonance
|
|
27
|
+
</a>
|
|
28
|
+
</HoverCardTrigger>
|
|
29
|
+
<HoverCardContent className="w-80">
|
|
30
|
+
<div className="flex justify-between space-x-4">
|
|
31
|
+
<Avatar
|
|
32
|
+
fallback="Sonance"
|
|
33
|
+
size="md"
|
|
34
|
+
/>
|
|
35
|
+
<div className="space-y-1">
|
|
36
|
+
<h4 className="text-sm font-medium text-foreground">@sonance</h4>
|
|
37
|
+
<p className="text-sm text-foreground-secondary">
|
|
38
|
+
Premium architectural speakers and outdoor audio solutions.
|
|
39
|
+
</p>
|
|
40
|
+
<div className="flex items-center pt-2">
|
|
41
|
+
<CalendarDays className="mr-2 h-4 w-4 opacity-70" />{" "}
|
|
42
|
+
<span className="text-xs text-foreground-muted">
|
|
43
|
+
Joined December 2021
|
|
44
|
+
</span>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</HoverCardContent>
|
|
49
|
+
</HoverCard>
|
|
50
|
+
),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const ProductPreview: Story = {
|
|
54
|
+
render: () => (
|
|
55
|
+
<HoverCard>
|
|
56
|
+
<HoverCardTrigger asChild>
|
|
57
|
+
<button className="text-sm font-medium underline underline-offset-4">
|
|
58
|
+
View Sonance Landscape Series
|
|
59
|
+
</button>
|
|
60
|
+
</HoverCardTrigger>
|
|
61
|
+
<HoverCardContent className="w-80">
|
|
62
|
+
<div className="space-y-3">
|
|
63
|
+
<div className="h-32 rounded-sm bg-secondary-hover flex items-center justify-center">
|
|
64
|
+
<span className="text-foreground-muted text-xs">Product Image</span>
|
|
65
|
+
</div>
|
|
66
|
+
<div className="space-y-1">
|
|
67
|
+
<h4 className="text-sm font-medium text-foreground">
|
|
68
|
+
Landscape Series
|
|
69
|
+
</h4>
|
|
70
|
+
<p className="text-sm text-foreground-secondary">
|
|
71
|
+
Outdoor speakers designed to blend seamlessly into your landscape
|
|
72
|
+
while delivering exceptional audio quality.
|
|
73
|
+
</p>
|
|
74
|
+
<p className="text-xs text-foreground-muted pt-1">
|
|
75
|
+
Starting at $599
|
|
76
|
+
</p>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</HoverCardContent>
|
|
80
|
+
</HoverCard>
|
|
81
|
+
),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const LinkPreview: Story = {
|
|
85
|
+
render: () => (
|
|
86
|
+
<p className="text-sm text-foreground-secondary">
|
|
87
|
+
Learn more about our{" "}
|
|
88
|
+
<HoverCard>
|
|
89
|
+
<HoverCardTrigger asChild>
|
|
90
|
+
<a
|
|
91
|
+
href="#"
|
|
92
|
+
className="font-medium text-foreground underline underline-offset-4"
|
|
93
|
+
>
|
|
94
|
+
installation services
|
|
95
|
+
</a>
|
|
96
|
+
</HoverCardTrigger>
|
|
97
|
+
<HoverCardContent>
|
|
98
|
+
<div className="space-y-2">
|
|
99
|
+
<h4 className="text-sm font-medium text-foreground">
|
|
100
|
+
Professional Installation
|
|
101
|
+
</h4>
|
|
102
|
+
<p className="text-sm text-foreground-secondary">
|
|
103
|
+
Our certified integrators ensure your audio system is installed
|
|
104
|
+
correctly for optimal performance.
|
|
105
|
+
</p>
|
|
106
|
+
</div>
|
|
107
|
+
</HoverCardContent>
|
|
108
|
+
</HoverCard>{" "}
|
|
109
|
+
for your home.
|
|
110
|
+
</p>
|
|
111
|
+
),
|
|
112
|
+
};
|
|
113
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
const HoverCard = HoverCardPrimitive.Root;
|
|
8
|
+
const HoverCardTrigger = HoverCardPrimitive.Trigger;
|
|
9
|
+
|
|
10
|
+
const HoverCardContent = React.forwardRef<
|
|
11
|
+
React.ElementRef<typeof HoverCardPrimitive.Content>,
|
|
12
|
+
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
|
|
13
|
+
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
|
14
|
+
<HoverCardPrimitive.Content
|
|
15
|
+
ref={ref}
|
|
16
|
+
align={align}
|
|
17
|
+
sideOffset={sideOffset}
|
|
18
|
+
className={cn(
|
|
19
|
+
"z-50 w-64 rounded-sm border border-border bg-card p-4 text-foreground shadow-md outline-none",
|
|
20
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
21
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
22
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
23
|
+
"data-[side=bottom]:slide-in-from-top-2",
|
|
24
|
+
"data-[side=left]:slide-in-from-right-2",
|
|
25
|
+
"data-[side=right]:slide-in-from-left-2",
|
|
26
|
+
"data-[side=top]:slide-in-from-bottom-2",
|
|
27
|
+
className
|
|
28
|
+
)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
));
|
|
32
|
+
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
|
|
33
|
+
|
|
34
|
+
export { HoverCard, HoverCardTrigger, HoverCardContent };
|
|
35
|
+
|