Seed: project-management template (23 files)
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const MenuContext = React.createContext<{ open: boolean; setOpen: (o: boolean) => void }>({ open: false, setOpen: () => {} });
|
||||||
|
|
||||||
|
export function DropdownMenu({ children }: { children?: React.ReactNode }) {
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
return (
|
||||||
|
<MenuContext.Provider value={{ open, setOpen }}>
|
||||||
|
<div className="relative inline-block">{children}</div>
|
||||||
|
</MenuContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DropdownMenuTrigger({ asChild, children, ...props }: React.ButtonHTMLAttributes<HTMLButtonElement> & { asChild?: boolean }) {
|
||||||
|
const ctx = React.useContext(MenuContext);
|
||||||
|
if (asChild && React.isValidElement(children)) {
|
||||||
|
return React.cloneElement(children as React.ReactElement, { onClick: () => ctx.setOpen(!ctx.open) });
|
||||||
|
}
|
||||||
|
return <button type="button" onClick={() => ctx.setOpen(!ctx.open)} {...props}>{children}</button>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DropdownMenuContent({ align = "end", className, children, ...props }: React.HTMLAttributes<HTMLDivElement> & { align?: "start" | "end" | "center" }) {
|
||||||
|
const ctx = React.useContext(MenuContext);
|
||||||
|
if (!ctx.open) return null;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"absolute z-50 mt-1 min-w-[10rem] rounded-md border border-slate-200 bg-white py-1 shadow-lg",
|
||||||
|
align === "end" ? "right-0" : "left-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DropdownMenuItem({ className, onClick, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
||||||
|
const ctx = React.useContext(MenuContext);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={(e) => { onClick?.(e); ctx.setOpen(false); }}
|
||||||
|
className={cn("cursor-pointer px-3 py-2 text-sm hover:bg-slate-100", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DropdownMenuLabel({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
||||||
|
return <div className={cn("px-3 py-1.5 text-xs font-semibold text-slate-500", className)} {...props} />;
|
||||||
|
}
|
||||||
|
export function DropdownMenuSeparator({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
||||||
|
return <div className={cn("my-1 h-px bg-slate-200", className)} {...props} />;
|
||||||
|
}
|
||||||
|
export function DropdownMenuGroup({ children }: { children?: React.ReactNode }) { return <div>{children}</div>; }
|
||||||
|
|
||||||
|
export default DropdownMenu;
|
||||||
Reference in New Issue
Block a user