main
tsx 207 lines 7.68 KB
Raw
1 import * as React from "react";
2 import * as MenubarPrimitive from "@radix-ui/react-menubar";
3 import { Check, ChevronRight, Circle } from "lucide-react";
4
5 import { cn } from "@/lib/utils";
6
7 const MenubarMenu = MenubarPrimitive.Menu;
8
9 const MenubarGroup = MenubarPrimitive.Group;
10
11 const MenubarPortal = MenubarPrimitive.Portal;
12
13 const MenubarSub = MenubarPrimitive.Sub;
14
15 const MenubarRadioGroup = MenubarPrimitive.RadioGroup;
16
17 const Menubar = React.forwardRef<
18 React.ElementRef<typeof MenubarPrimitive.Root>,
19 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
20 >(({ className, ...props }, ref) => (
21 <MenubarPrimitive.Root
22 ref={ref}
23 className={cn("flex h-10 items-center space-x-1 rounded-md border bg-background p-1", className)}
24 {...props}
25 />
26 ));
27 Menubar.displayName = MenubarPrimitive.Root.displayName;
28
29 const MenubarTrigger = React.forwardRef<
30 React.ElementRef<typeof MenubarPrimitive.Trigger>,
31 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
32 >(({ className, ...props }, ref) => (
33 <MenubarPrimitive.Trigger
34 ref={ref}
35 className={cn(
36 "flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none data-[state=open]:bg-accent data-[state=open]:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
37 className,
38 )}
39 {...props}
40 />
41 ));
42 MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
43
44 const MenubarSubTrigger = React.forwardRef<
45 React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
46 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
47 inset?: boolean;
48 }
49 >(({ className, inset, children, ...props }, ref) => (
50 <MenubarPrimitive.SubTrigger
51 ref={ref}
52 className={cn(
53 "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[state=open]:bg-accent data-[state=open]:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
54 inset && "pl-8",
55 className,
56 )}
57 {...props}
58 >
59 {children}
60 <ChevronRight className="ml-auto h-4 w-4" />
61 </MenubarPrimitive.SubTrigger>
62 ));
63 MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
64
65 const MenubarSubContent = React.forwardRef<
66 React.ElementRef<typeof MenubarPrimitive.SubContent>,
67 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
68 >(({ className, ...props }, ref) => (
69 <MenubarPrimitive.SubContent
70 ref={ref}
71 className={cn(
72 "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground 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",
73 className,
74 )}
75 {...props}
76 />
77 ));
78 MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
79
80 const MenubarContent = React.forwardRef<
81 React.ElementRef<typeof MenubarPrimitive.Content>,
82 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
83 >(({ className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, ref) => (
84 <MenubarPrimitive.Portal>
85 <MenubarPrimitive.Content
86 ref={ref}
87 align={align}
88 alignOffset={alignOffset}
89 sideOffset={sideOffset}
90 className={cn(
91 "z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in 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",
92 className,
93 )}
94 {...props}
95 />
96 </MenubarPrimitive.Portal>
97 ));
98 MenubarContent.displayName = MenubarPrimitive.Content.displayName;
99
100 const MenubarItem = React.forwardRef<
101 React.ElementRef<typeof MenubarPrimitive.Item>,
102 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
103 inset?: boolean;
104 }
105 >(({ className, inset, ...props }, ref) => (
106 <MenubarPrimitive.Item
107 ref={ref}
108 className={cn(
109 "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
110 inset && "pl-8",
111 className,
112 )}
113 {...props}
114 />
115 ));
116 MenubarItem.displayName = MenubarPrimitive.Item.displayName;
117
118 const MenubarCheckboxItem = React.forwardRef<
119 React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
120 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
121 >(({ className, children, checked, ...props }, ref) => (
122 <MenubarPrimitive.CheckboxItem
123 ref={ref}
124 className={cn(
125 "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
126 className,
127 )}
128 checked={checked}
129 {...props}
130 >
131 <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
132 <MenubarPrimitive.ItemIndicator>
133 <Check className="h-4 w-4" />
134 </MenubarPrimitive.ItemIndicator>
135 </span>
136 {children}
137 </MenubarPrimitive.CheckboxItem>
138 ));
139 MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;
140
141 const MenubarRadioItem = React.forwardRef<
142 React.ElementRef<typeof MenubarPrimitive.RadioItem>,
143 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
144 >(({ className, children, ...props }, ref) => (
145 <MenubarPrimitive.RadioItem
146 ref={ref}
147 className={cn(
148 "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
149 className,
150 )}
151 {...props}
152 >
153 <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
154 <MenubarPrimitive.ItemIndicator>
155 <Circle className="h-2 w-2 fill-current" />
156 </MenubarPrimitive.ItemIndicator>
157 </span>
158 {children}
159 </MenubarPrimitive.RadioItem>
160 ));
161 MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;
162
163 const MenubarLabel = React.forwardRef<
164 React.ElementRef<typeof MenubarPrimitive.Label>,
165 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
166 inset?: boolean;
167 }
168 >(({ className, inset, ...props }, ref) => (
169 <MenubarPrimitive.Label
170 ref={ref}
171 className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
172 {...props}
173 />
174 ));
175 MenubarLabel.displayName = MenubarPrimitive.Label.displayName;
176
177 const MenubarSeparator = React.forwardRef<
178 React.ElementRef<typeof MenubarPrimitive.Separator>,
179 React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
180 >(({ className, ...props }, ref) => (
181 <MenubarPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} />
182 ));
183 MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;
184
185 const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
186 return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />;
187 };
188 MenubarShortcut.displayname = "MenubarShortcut";
189
190 export {
191 Menubar,
192 MenubarMenu,
193 MenubarTrigger,
194 MenubarContent,
195 MenubarItem,
196 MenubarSeparator,
197 MenubarLabel,
198 MenubarCheckboxItem,
199 MenubarRadioGroup,
200 MenubarRadioItem,
201 MenubarPortal,
202 MenubarSubContent,
203 MenubarSubTrigger,
204 MenubarGroup,
205 MenubarSub,
206 MenubarShortcut,
207 };