feat: dynamic menu item support

main
Mahmudul Hasan 2024-07-15 16:28:12 +06:00
parent 5a5e3c00f3
commit a425c78bdf
4 changed files with 45 additions and 20 deletions

View File

@ -1,9 +1,10 @@
import { Sheet, SheetContent, SheetTrigger } from "@/Components/ui/sheet";
import { Button } from "@/Components/ui/button";
import { Home, Menu } from "lucide-react";
import { AlignJustifyIcon, Menu } from "lucide-react";
import { Link } from "@inertiajs/react";
import { MenuItemProp } from "@/types";
import ApplicationLogo from "@/Components/ApplicationLogo";
import { DropdownMenuSeparator } from "./ui/dropdown-menu";
const MobileMenu = ({ links }: { links: MenuItemProp[] }) => {
return (
@ -19,31 +20,41 @@ const MobileMenu = ({ links }: { links: MenuItemProp[] }) => {
</Button>
</SheetTrigger>
<SheetContent side="left" className="flex flex-col">
<nav className="grid gap-2 text-lg font-medium">
<nav className="text-lg font-medium">
<Link
href="#"
className="flex items-center gap-2 text-lg font-semibold"
className="flex items-center gap-2 text-lg font-semibold mb-4"
>
<ApplicationLogo className="h-8 w-8 fill-current text-gray-500" />
<span>Acme Inc</span>
</Link>
{links.map((link, index) => {
return (
<Link
key={index}
href={link.href}
className="mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2 text-muted-foreground hover:text-foreground"
>
<Home className="h-5 w-5" />
{link.title}
</Link>
);
})}
<DropdownMenuSeparator />
<div className="space-y-2">
{links.map((link, index) => (
<MobileMenuItem key={index} link={link} />
))}
</div>
</nav>
</SheetContent>
</Sheet>
);
};
const MobileMenuItem = ({ link }: { link: MenuItemProp }) => {
const Icon = (link.icon ?? AlignJustifyIcon) as React.ElementType;
return (
<Link
href={link.href}
className="mx-[-0.65rem] flex items-center gap-4 rounded-xl px-3 py-2 text-muted-foreground hover:text-foreground"
>
<Icon className="h-5 w-5" />
{link.title}
</Link>
);
};
export default MobileMenu;

View File

@ -1,5 +1,5 @@
import { Link, usePage } from "@inertiajs/react";
import { Home } from "lucide-react";
import { AlignJustifyIcon, Home, Icon } from "lucide-react";
import { cn } from "@/lib/utils";
import { buttonVariants } from "@/Components/ui/button";
import {
@ -10,6 +10,7 @@ import {
} from "@/Components/ui/tooltip";
import { MenuItemProp } from "@/types";
import ApplicationLogo from "@/Components/ApplicationLogo";
import { ReactNode } from "react";
type Props = {
links: MenuItemProp[];
@ -22,6 +23,8 @@ type MenuItemProps = {
};
const CollapsedMenuItem = ({ link, isActive }: MenuItemProps) => {
const Icon = (link.icon ?? AlignJustifyIcon) as React.ElementType;
return (
<Tooltip delayDuration={0}>
<TooltipTrigger asChild>
@ -37,7 +40,7 @@ const CollapsedMenuItem = ({ link, isActive }: MenuItemProps) => {
"dark:bg-muted dark:text-muted-foreground dark:hover:bg-muted dark:hover:text-white"
)}
>
<Home className="h-4 w-4" />
{<Icon className="h-4 w-4" />}
<span className="sr-only">{link.title}</span>
</Link>
</TooltipTrigger>
@ -49,6 +52,8 @@ const CollapsedMenuItem = ({ link, isActive }: MenuItemProps) => {
};
const ExpandedMenuItem = ({ link, isActive }: MenuItemProps) => {
const Icon = (link.icon ?? AlignJustifyIcon) as React.ElementType;
return (
<Link
href={link.href}
@ -57,14 +62,14 @@ const ExpandedMenuItem = ({ link, isActive }: MenuItemProps) => {
"justify-start"
)}
>
<Home className="mr-2 h-4 w-4" />
{<Icon className="mr-2 h-4 w-4" />}
{link.title}
</Link>
);
};
const Sidebar = ({ links, isCollapsed }: Props) => {
const { url, component } = usePage();
const { url } = usePage();
return (
<TooltipProvider>

View File

@ -1,7 +1,7 @@
import { PropsWithChildren, ReactNode, useState } from "react";
import { Link } from "@inertiajs/react";
import { MenuItemProp, User } from "@/types";
import { CircleUser, Search } from "lucide-react";
import { CircleUser, Search, UserIcon } from "lucide-react";
import { Button } from "@/Components/ui/button";
import {
DropdownMenu,
@ -33,6 +33,7 @@ const links: MenuItemProp[] = [
title: "Profile",
href: route("profile.edit"),
variant: "ghost",
icon: UserIcon,
},
];

View File

@ -1,3 +1,6 @@
import { LucideProps } from "lucide-react";
import { ForwardRefExoticComponent, ReactNode, RefAttributes } from "react";
export interface User {
id: number;
name: string;
@ -16,6 +19,11 @@ export type PageProps<
export type MenuItemProp = {
title: string;
href: string;
icon?:
| ForwardRefExoticComponent<
Omit<LucideProps, "ref"> & RefAttributes<SVGSVGElement>
>
| ReactNode;
variant:
| "link"
| "default"