deploy-ease-platform/frontend/src/components/ui/sidebar-menu.tsx
2024-12-27 21:08:38 +08:00

81 lines
2.4 KiB
TypeScript

import * as React from "react";
import { ChevronDown } from "lucide-react";
import { cn } from "@/lib/utils";
export interface MenuItemProps extends React.HTMLAttributes<HTMLDivElement> {
icon?: React.ReactNode;
title: string;
active?: boolean;
expanded?: boolean;
disabled?: boolean;
children?: React.ReactNode;
onClick?: () => void;
}
const MenuItem = React.forwardRef<HTMLDivElement, MenuItemProps>(
({ className, icon, title, active, expanded, disabled, children, onClick, ...props }, ref) => {
return (
<div ref={ref} className={cn("relative", className)} {...props}>
<div
className={cn(
"group flex cursor-pointer items-center rounded-lg px-3 py-2 text-sm font-medium",
"transition-all duration-200 ease-in-out",
"hover:bg-accent/50 hover:text-accent-foreground",
"dark:hover:bg-slate-800 dark:hover:text-slate-100",
active && "bg-accent text-accent-foreground dark:bg-slate-800 dark:text-slate-100",
disabled && "pointer-events-none opacity-50",
className
)}
onClick={onClick}
>
{icon && (
<span className={cn(
"mr-2 transition-colors",
"text-muted-foreground group-hover:text-current",
active && "text-current"
)}>
{icon}
</span>
)}
<span className="flex-1">{title}</span>
{children && (
<ChevronDown
className={cn(
"ml-1 h-4 w-4 transition-transform duration-200",
"text-muted-foreground group-hover:text-current",
active && "text-current",
expanded && "rotate-180"
)}
/>
)}
</div>
{expanded && children && (
<div className={cn(
"mt-1 space-y-1 pl-4",
"animate-in slide-in-from-left-5 duration-200"
)}>
{children}
</div>
)}
</div>
);
}
);
MenuItem.displayName = "MenuItem";
const MenuGroup = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"space-y-1.5 px-3",
className
)}
{...props}
/>
));
MenuGroup.displayName = "MenuGroup";
export { MenuItem, MenuGroup };