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,183 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
4
|
+
import { useState, useEffect } from "react";
|
|
5
|
+
import {
|
|
6
|
+
Calculator,
|
|
7
|
+
Calendar,
|
|
8
|
+
CreditCard,
|
|
9
|
+
Settings,
|
|
10
|
+
Smile,
|
|
11
|
+
User,
|
|
12
|
+
} from "lucide-react";
|
|
13
|
+
import {
|
|
14
|
+
Command,
|
|
15
|
+
CommandDialog,
|
|
16
|
+
CommandEmpty,
|
|
17
|
+
CommandGroup,
|
|
18
|
+
CommandInput,
|
|
19
|
+
CommandItem,
|
|
20
|
+
CommandList,
|
|
21
|
+
CommandSeparator,
|
|
22
|
+
CommandShortcut,
|
|
23
|
+
} from "./command";
|
|
24
|
+
|
|
25
|
+
const meta: Meta<typeof Command> = {
|
|
26
|
+
title: "Components/Forms/Command",
|
|
27
|
+
component: Command,
|
|
28
|
+
parameters: {
|
|
29
|
+
layout: "centered",
|
|
30
|
+
},
|
|
31
|
+
tags: ["autodocs"],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default meta;
|
|
35
|
+
type Story = StoryObj<typeof Command>;
|
|
36
|
+
|
|
37
|
+
export const Default: Story = {
|
|
38
|
+
render: () => (
|
|
39
|
+
<Command className="rounded-sm border border-border shadow-md w-[400px]">
|
|
40
|
+
<CommandInput placeholder="Type a command or search..." />
|
|
41
|
+
<CommandList>
|
|
42
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
43
|
+
<CommandGroup heading="Suggestions">
|
|
44
|
+
<CommandItem>
|
|
45
|
+
<Calendar className="mr-2 h-4 w-4" />
|
|
46
|
+
<span>Calendar</span>
|
|
47
|
+
</CommandItem>
|
|
48
|
+
<CommandItem>
|
|
49
|
+
<Smile className="mr-2 h-4 w-4" />
|
|
50
|
+
<span>Search Emoji</span>
|
|
51
|
+
</CommandItem>
|
|
52
|
+
<CommandItem>
|
|
53
|
+
<Calculator className="mr-2 h-4 w-4" />
|
|
54
|
+
<span>Calculator</span>
|
|
55
|
+
</CommandItem>
|
|
56
|
+
</CommandGroup>
|
|
57
|
+
<CommandSeparator />
|
|
58
|
+
<CommandGroup heading="Settings">
|
|
59
|
+
<CommandItem>
|
|
60
|
+
<User className="mr-2 h-4 w-4" />
|
|
61
|
+
<span>Profile</span>
|
|
62
|
+
<CommandShortcut>⌘P</CommandShortcut>
|
|
63
|
+
</CommandItem>
|
|
64
|
+
<CommandItem>
|
|
65
|
+
<CreditCard className="mr-2 h-4 w-4" />
|
|
66
|
+
<span>Billing</span>
|
|
67
|
+
<CommandShortcut>⌘B</CommandShortcut>
|
|
68
|
+
</CommandItem>
|
|
69
|
+
<CommandItem>
|
|
70
|
+
<Settings className="mr-2 h-4 w-4" />
|
|
71
|
+
<span>Settings</span>
|
|
72
|
+
<CommandShortcut>⌘S</CommandShortcut>
|
|
73
|
+
</CommandItem>
|
|
74
|
+
</CommandGroup>
|
|
75
|
+
</CommandList>
|
|
76
|
+
</Command>
|
|
77
|
+
),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
function CommandDialogDemo() {
|
|
81
|
+
const [open, setOpen] = useState(false);
|
|
82
|
+
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
const down = (e: KeyboardEvent) => {
|
|
85
|
+
if (e.key === "k" && (e.metaKey || e.ctrlKey)) {
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
setOpen((open) => !open);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
document.addEventListener("keydown", down);
|
|
92
|
+
return () => document.removeEventListener("keydown", down);
|
|
93
|
+
}, []);
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<>
|
|
97
|
+
<p className="text-sm text-foreground-muted">
|
|
98
|
+
Press{" "}
|
|
99
|
+
<kbd className="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border border-border bg-card px-1.5 font-mono text-[10px] font-medium text-foreground-muted opacity-100">
|
|
100
|
+
<span className="text-xs">⌘</span>K
|
|
101
|
+
</kbd>
|
|
102
|
+
</p>
|
|
103
|
+
<CommandDialog open={open} onOpenChange={setOpen}>
|
|
104
|
+
<CommandInput placeholder="Type a command or search..." />
|
|
105
|
+
<CommandList>
|
|
106
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
107
|
+
<CommandGroup heading="Suggestions">
|
|
108
|
+
<CommandItem>
|
|
109
|
+
<Calendar className="mr-2 h-4 w-4" />
|
|
110
|
+
<span>Calendar</span>
|
|
111
|
+
</CommandItem>
|
|
112
|
+
<CommandItem>
|
|
113
|
+
<Smile className="mr-2 h-4 w-4" />
|
|
114
|
+
<span>Search Emoji</span>
|
|
115
|
+
</CommandItem>
|
|
116
|
+
<CommandItem>
|
|
117
|
+
<Calculator className="mr-2 h-4 w-4" />
|
|
118
|
+
<span>Calculator</span>
|
|
119
|
+
</CommandItem>
|
|
120
|
+
</CommandGroup>
|
|
121
|
+
<CommandSeparator />
|
|
122
|
+
<CommandGroup heading="Settings">
|
|
123
|
+
<CommandItem>
|
|
124
|
+
<User className="mr-2 h-4 w-4" />
|
|
125
|
+
<span>Profile</span>
|
|
126
|
+
<CommandShortcut>⌘P</CommandShortcut>
|
|
127
|
+
</CommandItem>
|
|
128
|
+
<CommandItem>
|
|
129
|
+
<CreditCard className="mr-2 h-4 w-4" />
|
|
130
|
+
<span>Billing</span>
|
|
131
|
+
<CommandShortcut>⌘B</CommandShortcut>
|
|
132
|
+
</CommandItem>
|
|
133
|
+
<CommandItem>
|
|
134
|
+
<Settings className="mr-2 h-4 w-4" />
|
|
135
|
+
<span>Settings</span>
|
|
136
|
+
<CommandShortcut>⌘S</CommandShortcut>
|
|
137
|
+
</CommandItem>
|
|
138
|
+
</CommandGroup>
|
|
139
|
+
</CommandList>
|
|
140
|
+
</CommandDialog>
|
|
141
|
+
</>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const Dialog: Story = {
|
|
146
|
+
render: () => <CommandDialogDemo />,
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const Simple: Story = {
|
|
150
|
+
render: () => (
|
|
151
|
+
<Command className="rounded-sm border border-border shadow-md w-[300px]">
|
|
152
|
+
<CommandInput placeholder="Search products..." />
|
|
153
|
+
<CommandList>
|
|
154
|
+
<CommandEmpty>No products found.</CommandEmpty>
|
|
155
|
+
<CommandGroup heading="Products">
|
|
156
|
+
<CommandItem>Architectural Speakers</CommandItem>
|
|
157
|
+
<CommandItem>Outdoor Speakers</CommandItem>
|
|
158
|
+
<CommandItem>Subwoofers</CommandItem>
|
|
159
|
+
<CommandItem>Amplifiers</CommandItem>
|
|
160
|
+
<CommandItem>Accessories</CommandItem>
|
|
161
|
+
</CommandGroup>
|
|
162
|
+
</CommandList>
|
|
163
|
+
</Command>
|
|
164
|
+
),
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export const WithDisabledItems: Story = {
|
|
168
|
+
render: () => (
|
|
169
|
+
<Command className="rounded-sm border border-border shadow-md w-[350px]">
|
|
170
|
+
<CommandInput placeholder="Search..." />
|
|
171
|
+
<CommandList>
|
|
172
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
173
|
+
<CommandGroup heading="Actions">
|
|
174
|
+
<CommandItem>Create new project</CommandItem>
|
|
175
|
+
<CommandItem>Open existing project</CommandItem>
|
|
176
|
+
<CommandItem disabled>Import from Figma (Pro)</CommandItem>
|
|
177
|
+
<CommandItem disabled>Export to PDF (Pro)</CommandItem>
|
|
178
|
+
</CommandGroup>
|
|
179
|
+
</CommandList>
|
|
180
|
+
</Command>
|
|
181
|
+
),
|
|
182
|
+
};
|
|
183
|
+
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Command as CommandPrimitive } from "cmdk";
|
|
5
|
+
import { Search } from "lucide-react";
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
import {
|
|
8
|
+
Dialog,
|
|
9
|
+
DialogContent,
|
|
10
|
+
DialogTitle,
|
|
11
|
+
} from "@/components/ui/dialog";
|
|
12
|
+
|
|
13
|
+
const Command = React.forwardRef<
|
|
14
|
+
React.ElementRef<typeof CommandPrimitive>,
|
|
15
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
|
16
|
+
>(({ className, ...props }, ref) => (
|
|
17
|
+
<CommandPrimitive
|
|
18
|
+
ref={ref}
|
|
19
|
+
className={cn(
|
|
20
|
+
"flex h-full w-full flex-col overflow-hidden rounded-sm bg-card text-foreground",
|
|
21
|
+
className
|
|
22
|
+
)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
));
|
|
26
|
+
Command.displayName = CommandPrimitive.displayName;
|
|
27
|
+
|
|
28
|
+
interface CommandDialogProps {
|
|
29
|
+
open?: boolean;
|
|
30
|
+
onOpenChange?: (open: boolean) => void;
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const CommandDialog = ({ children, open, onOpenChange }: CommandDialogProps) => {
|
|
35
|
+
const handleClose = React.useCallback(() => {
|
|
36
|
+
onOpenChange?.(false);
|
|
37
|
+
}, [onOpenChange]);
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<Dialog open={open ?? false} onClose={handleClose}>
|
|
41
|
+
<DialogContent className="overflow-hidden p-0 shadow-lg" showClose={false}>
|
|
42
|
+
<DialogTitle className="sr-only">Command Menu</DialogTitle>
|
|
43
|
+
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-foreground-muted [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
|
44
|
+
{children}
|
|
45
|
+
</Command>
|
|
46
|
+
</DialogContent>
|
|
47
|
+
</Dialog>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const CommandInput = React.forwardRef<
|
|
52
|
+
React.ElementRef<typeof CommandPrimitive.Input>,
|
|
53
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
|
54
|
+
>(({ className, ...props }, ref) => (
|
|
55
|
+
<div className="flex items-center border-b border-border px-3" cmdk-input-wrapper="">
|
|
56
|
+
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
57
|
+
<CommandPrimitive.Input
|
|
58
|
+
ref={ref}
|
|
59
|
+
className={cn(
|
|
60
|
+
"flex h-11 w-full rounded-sm bg-transparent py-3 text-sm outline-none placeholder:text-foreground-muted disabled:cursor-not-allowed disabled:opacity-50",
|
|
61
|
+
className
|
|
62
|
+
)}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
</div>
|
|
66
|
+
));
|
|
67
|
+
|
|
68
|
+
CommandInput.displayName = CommandPrimitive.Input.displayName;
|
|
69
|
+
|
|
70
|
+
const CommandList = React.forwardRef<
|
|
71
|
+
React.ElementRef<typeof CommandPrimitive.List>,
|
|
72
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
|
73
|
+
>(({ className, ...props }, ref) => (
|
|
74
|
+
<CommandPrimitive.List
|
|
75
|
+
ref={ref}
|
|
76
|
+
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
));
|
|
80
|
+
|
|
81
|
+
CommandList.displayName = CommandPrimitive.List.displayName;
|
|
82
|
+
|
|
83
|
+
const CommandEmpty = React.forwardRef<
|
|
84
|
+
React.ElementRef<typeof CommandPrimitive.Empty>,
|
|
85
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
|
86
|
+
>((props, ref) => (
|
|
87
|
+
<CommandPrimitive.Empty
|
|
88
|
+
ref={ref}
|
|
89
|
+
className="py-6 text-center text-sm text-foreground-muted"
|
|
90
|
+
{...props}
|
|
91
|
+
/>
|
|
92
|
+
));
|
|
93
|
+
|
|
94
|
+
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
|
95
|
+
|
|
96
|
+
const CommandGroup = React.forwardRef<
|
|
97
|
+
React.ElementRef<typeof CommandPrimitive.Group>,
|
|
98
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
|
99
|
+
>(({ className, ...props }, ref) => (
|
|
100
|
+
<CommandPrimitive.Group
|
|
101
|
+
ref={ref}
|
|
102
|
+
className={cn(
|
|
103
|
+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-widest [&_[cmdk-group-heading]]:text-foreground-muted",
|
|
104
|
+
className
|
|
105
|
+
)}
|
|
106
|
+
{...props}
|
|
107
|
+
/>
|
|
108
|
+
));
|
|
109
|
+
|
|
110
|
+
CommandGroup.displayName = CommandPrimitive.Group.displayName;
|
|
111
|
+
|
|
112
|
+
const CommandSeparator = React.forwardRef<
|
|
113
|
+
React.ElementRef<typeof CommandPrimitive.Separator>,
|
|
114
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
|
115
|
+
>(({ className, ...props }, ref) => (
|
|
116
|
+
<CommandPrimitive.Separator
|
|
117
|
+
ref={ref}
|
|
118
|
+
className={cn("-mx-1 h-px bg-border", className)}
|
|
119
|
+
{...props}
|
|
120
|
+
/>
|
|
121
|
+
));
|
|
122
|
+
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
|
123
|
+
|
|
124
|
+
const CommandItem = React.forwardRef<
|
|
125
|
+
React.ElementRef<typeof CommandPrimitive.Item>,
|
|
126
|
+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
|
127
|
+
>(({ className, ...props }, ref) => (
|
|
128
|
+
<CommandPrimitive.Item
|
|
129
|
+
ref={ref}
|
|
130
|
+
className={cn(
|
|
131
|
+
"relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none",
|
|
132
|
+
"data-[selected=true]:bg-secondary-hover data-[selected=true]:text-foreground",
|
|
133
|
+
"data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50",
|
|
134
|
+
"[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
135
|
+
className
|
|
136
|
+
)}
|
|
137
|
+
{...props}
|
|
138
|
+
/>
|
|
139
|
+
));
|
|
140
|
+
|
|
141
|
+
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
|
142
|
+
|
|
143
|
+
const CommandShortcut = ({
|
|
144
|
+
className,
|
|
145
|
+
...props
|
|
146
|
+
}: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
147
|
+
return (
|
|
148
|
+
<span
|
|
149
|
+
className={cn(
|
|
150
|
+
"ml-auto text-xs tracking-widest text-foreground-muted",
|
|
151
|
+
className
|
|
152
|
+
)}
|
|
153
|
+
{...props}
|
|
154
|
+
/>
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
CommandShortcut.displayName = "CommandShortcut";
|
|
158
|
+
|
|
159
|
+
export {
|
|
160
|
+
Command,
|
|
161
|
+
CommandDialog,
|
|
162
|
+
CommandInput,
|
|
163
|
+
CommandList,
|
|
164
|
+
CommandEmpty,
|
|
165
|
+
CommandGroup,
|
|
166
|
+
CommandItem,
|
|
167
|
+
CommandShortcut,
|
|
168
|
+
CommandSeparator,
|
|
169
|
+
};
|
|
170
|
+
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import {
|
|
6
|
+
ContextMenu,
|
|
7
|
+
ContextMenuCheckboxItem,
|
|
8
|
+
ContextMenuContent,
|
|
9
|
+
ContextMenuItem,
|
|
10
|
+
ContextMenuLabel,
|
|
11
|
+
ContextMenuRadioGroup,
|
|
12
|
+
ContextMenuRadioItem,
|
|
13
|
+
ContextMenuSeparator,
|
|
14
|
+
ContextMenuShortcut,
|
|
15
|
+
ContextMenuSub,
|
|
16
|
+
ContextMenuSubContent,
|
|
17
|
+
ContextMenuSubTrigger,
|
|
18
|
+
ContextMenuTrigger,
|
|
19
|
+
} from "./context-menu";
|
|
20
|
+
|
|
21
|
+
const meta: Meta<typeof ContextMenu> = {
|
|
22
|
+
title: "Components/Navigation/ContextMenu",
|
|
23
|
+
component: ContextMenu,
|
|
24
|
+
parameters: {
|
|
25
|
+
layout: "centered",
|
|
26
|
+
},
|
|
27
|
+
tags: ["autodocs"],
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default meta;
|
|
31
|
+
type Story = StoryObj<typeof ContextMenu>;
|
|
32
|
+
|
|
33
|
+
export const Default: Story = {
|
|
34
|
+
render: () => (
|
|
35
|
+
<ContextMenu>
|
|
36
|
+
<ContextMenuTrigger className="flex h-[150px] w-[300px] items-center justify-center rounded-sm border border-dashed border-border text-sm text-foreground-muted">
|
|
37
|
+
Right click here
|
|
38
|
+
</ContextMenuTrigger>
|
|
39
|
+
<ContextMenuContent className="w-64">
|
|
40
|
+
<ContextMenuItem>
|
|
41
|
+
Back
|
|
42
|
+
<ContextMenuShortcut>⌘[</ContextMenuShortcut>
|
|
43
|
+
</ContextMenuItem>
|
|
44
|
+
<ContextMenuItem disabled>
|
|
45
|
+
Forward
|
|
46
|
+
<ContextMenuShortcut>⌘]</ContextMenuShortcut>
|
|
47
|
+
</ContextMenuItem>
|
|
48
|
+
<ContextMenuItem>
|
|
49
|
+
Reload
|
|
50
|
+
<ContextMenuShortcut>⌘R</ContextMenuShortcut>
|
|
51
|
+
</ContextMenuItem>
|
|
52
|
+
<ContextMenuSub>
|
|
53
|
+
<ContextMenuSubTrigger>More Tools</ContextMenuSubTrigger>
|
|
54
|
+
<ContextMenuSubContent className="w-48">
|
|
55
|
+
<ContextMenuItem>
|
|
56
|
+
Save Page As...
|
|
57
|
+
<ContextMenuShortcut>⇧⌘S</ContextMenuShortcut>
|
|
58
|
+
</ContextMenuItem>
|
|
59
|
+
<ContextMenuItem>Create Shortcut...</ContextMenuItem>
|
|
60
|
+
<ContextMenuItem>Name Window...</ContextMenuItem>
|
|
61
|
+
<ContextMenuSeparator />
|
|
62
|
+
<ContextMenuItem>Developer Tools</ContextMenuItem>
|
|
63
|
+
</ContextMenuSubContent>
|
|
64
|
+
</ContextMenuSub>
|
|
65
|
+
<ContextMenuSeparator />
|
|
66
|
+
<ContextMenuCheckboxItem checked>
|
|
67
|
+
Show Bookmarks Bar
|
|
68
|
+
<ContextMenuShortcut>⌘⇧B</ContextMenuShortcut>
|
|
69
|
+
</ContextMenuCheckboxItem>
|
|
70
|
+
<ContextMenuCheckboxItem>Show Full URLs</ContextMenuCheckboxItem>
|
|
71
|
+
<ContextMenuSeparator />
|
|
72
|
+
<ContextMenuRadioGroup value="pedro">
|
|
73
|
+
<ContextMenuLabel inset>People</ContextMenuLabel>
|
|
74
|
+
<ContextMenuRadioItem value="pedro">
|
|
75
|
+
Pedro Duarte
|
|
76
|
+
</ContextMenuRadioItem>
|
|
77
|
+
<ContextMenuRadioItem value="colm">Colm Tuite</ContextMenuRadioItem>
|
|
78
|
+
</ContextMenuRadioGroup>
|
|
79
|
+
</ContextMenuContent>
|
|
80
|
+
</ContextMenu>
|
|
81
|
+
),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
function ContextMenuWithStateDemo() {
|
|
85
|
+
const [bookmarksChecked, setBookmarksChecked] = useState(true);
|
|
86
|
+
const [urlsChecked, setUrlsChecked] = useState(false);
|
|
87
|
+
const [person, setPerson] = useState("pedro");
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<ContextMenu>
|
|
91
|
+
<ContextMenuTrigger className="flex h-[150px] w-[300px] items-center justify-center rounded-sm border border-dashed border-border text-sm text-foreground-muted">
|
|
92
|
+
Right click here
|
|
93
|
+
</ContextMenuTrigger>
|
|
94
|
+
<ContextMenuContent className="w-64">
|
|
95
|
+
<ContextMenuItem>New Tab</ContextMenuItem>
|
|
96
|
+
<ContextMenuItem>New Window</ContextMenuItem>
|
|
97
|
+
<ContextMenuSeparator />
|
|
98
|
+
<ContextMenuCheckboxItem
|
|
99
|
+
checked={bookmarksChecked}
|
|
100
|
+
onCheckedChange={setBookmarksChecked}
|
|
101
|
+
>
|
|
102
|
+
Show Bookmarks
|
|
103
|
+
</ContextMenuCheckboxItem>
|
|
104
|
+
<ContextMenuCheckboxItem
|
|
105
|
+
checked={urlsChecked}
|
|
106
|
+
onCheckedChange={setUrlsChecked}
|
|
107
|
+
>
|
|
108
|
+
Show Full URLs
|
|
109
|
+
</ContextMenuCheckboxItem>
|
|
110
|
+
<ContextMenuSeparator />
|
|
111
|
+
<ContextMenuLabel>Switch User</ContextMenuLabel>
|
|
112
|
+
<ContextMenuRadioGroup value={person} onValueChange={setPerson}>
|
|
113
|
+
<ContextMenuRadioItem value="pedro">Pedro</ContextMenuRadioItem>
|
|
114
|
+
<ContextMenuRadioItem value="colm">Colm</ContextMenuRadioItem>
|
|
115
|
+
<ContextMenuRadioItem value="guest">Guest</ContextMenuRadioItem>
|
|
116
|
+
</ContextMenuRadioGroup>
|
|
117
|
+
</ContextMenuContent>
|
|
118
|
+
</ContextMenu>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const WithState: Story = {
|
|
123
|
+
render: () => <ContextMenuWithStateDemo />,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export const FileContextMenu: Story = {
|
|
127
|
+
render: () => (
|
|
128
|
+
<ContextMenu>
|
|
129
|
+
<ContextMenuTrigger className="flex h-[100px] w-[200px] flex-col items-center justify-center gap-2 rounded-sm border border-border bg-card p-4">
|
|
130
|
+
<div className="h-12 w-12 rounded-sm bg-secondary-hover" />
|
|
131
|
+
<span className="text-sm text-foreground">Document.pdf</span>
|
|
132
|
+
</ContextMenuTrigger>
|
|
133
|
+
<ContextMenuContent className="w-48">
|
|
134
|
+
<ContextMenuItem>
|
|
135
|
+
Open
|
|
136
|
+
<ContextMenuShortcut>⌘O</ContextMenuShortcut>
|
|
137
|
+
</ContextMenuItem>
|
|
138
|
+
<ContextMenuItem>Open With...</ContextMenuItem>
|
|
139
|
+
<ContextMenuSeparator />
|
|
140
|
+
<ContextMenuItem>
|
|
141
|
+
Copy
|
|
142
|
+
<ContextMenuShortcut>⌘C</ContextMenuShortcut>
|
|
143
|
+
</ContextMenuItem>
|
|
144
|
+
<ContextMenuItem>
|
|
145
|
+
Cut
|
|
146
|
+
<ContextMenuShortcut>⌘X</ContextMenuShortcut>
|
|
147
|
+
</ContextMenuItem>
|
|
148
|
+
<ContextMenuItem>Rename</ContextMenuItem>
|
|
149
|
+
<ContextMenuSeparator />
|
|
150
|
+
<ContextMenuItem>Share...</ContextMenuItem>
|
|
151
|
+
<ContextMenuItem className="text-error">
|
|
152
|
+
Delete
|
|
153
|
+
<ContextMenuShortcut>⌘⌫</ContextMenuShortcut>
|
|
154
|
+
</ContextMenuItem>
|
|
155
|
+
</ContextMenuContent>
|
|
156
|
+
</ContextMenu>
|
|
157
|
+
),
|
|
158
|
+
};
|
|
159
|
+
|