ldc-ovoteam/resources/ts/front/Components/Theme/Header/MobileNav.tsx

161 lines
5.4 KiB
TypeScript

//* PACKAGES
import { Button } from "@/components/ui/button";
import { Link } from "@inertiajs/react";
import * as SheetPrimitive from "@radix-ui/react-dialog";
import { ChevronLeft, ChevronRight, Menu, X } from "lucide-react";
import { useState } from "react";
//* THEME
import GoToSearchPage from "$/uwil/Header/GoToSearchPage";
import Logo from "$/uwil/Logo";
import {
Sheet,
SheetContent,
SheetFooter,
SheetHeader,
SheetTrigger,
} from "$/uwil/Sheet";
import SocialNetworks from "$/uwil/SocialNetworks";
import { cn } from "@/lib/utils";
import { FrontNavLinkProps } from "@/types/front";
function ConditionalLink({
title,
external,
href,
className,
}: FrontNavLinkProps & { className?: string }) {
return external ? (
<a
href={href ?? "#"}
target="_blank"
className={cn("text-xl font-bold", className)}
rel="noopener noreferrer"
>
{title}
</a>
) : (
<Link href={href ?? "#"} className={cn("text-xl font-bold", className)}>
{title}
</Link>
);
}
export default function MobileNav({
navLinks,
}: {
navLinks: FrontNavLinkProps[];
}) {
const [activeMenu, setActiveMenu] = useState<FrontNavLinkProps | null>(null);
const goBack = () => setActiveMenu(null);
const headerClasses =
"h-[140px] flex flex-row items-start justify-between relative pt-2";
return (
<div className={cn("lg:hidden", headerClasses)}>
<GoToSearchPage />
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" className="cursor-pointer [&_svg]:size-7">
<Menu />
</Button>
</SheetTrigger>
<SheetContent
showCloseButton={false}
side="right"
className="!fixed !inset-0 !w-screen !h-screen !max-w-none relative pt-0"
>
<SheetHeader className={cn(headerClasses, "space-y-0 relative")}>
<Logo className="block w-[38px] h-auto" />
<div className="flex items-center gap-1">
<GoToSearchPage />
<Button
variant="ghost"
className="cursor-pointor [&_svg]:size-7"
asChild
>
<SheetPrimitive.Close className="ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
<X />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</Button>
</div>
</SheetHeader>
{/* Contenu menu */}
<div className="flex flex-col gap-6 relative overflow-hidden mt-10 h-full">
<div
className={cn(
"absolute inset-0 flex flex-col gap-6 transition-transform duration-300",
activeMenu ? "-translate-x-full" : "translate-x-0",
)}
>
{!activeMenu &&
navLinks.map((link) => (
<div key={link.title}>
{link.children ? (
<div className="flex items-center justify-between">
<Link
href={link.href ?? "#"}
className="text-xl font-bold"
>
{link.title}
</Link>
<Button
size="icon"
variant="outline"
onClick={() => setActiveMenu(link)}
>
<ChevronRight />
</Button>
</div>
) : (
// eslint-disable-next-line react/jsx-props-no-spreading
<ConditionalLink {...link} />
)}
</div>
))}
<SocialNetworks />
</div>
<div
className={cn(
"absolute inset-0 transition-transform duration-300",
activeMenu ? "translate-x-0" : "translate-x-full",
)}
>
{activeMenu && (
<div className="flex flex-col items-start justify-start gap-8">
<div className="flex items-center gap-3">
<Button onClick={goBack} size="icon" variant="outline">
<ChevronLeft />
</Button>
<Link
href={activeMenu.href}
className="font-semibold text-xl"
>
{activeMenu.title}
</Link>
</div>
<ul className="list-disc pl-5 space-y-4">
{activeMenu.children?.map((child) => (
<li key={child.title}>
<ConditionalLink
// eslint-disable-next-line react/jsx-props-no-spreading
{...child}
className="font-semibold text-md"
/>
</li>
))}
</ul>
</div>
)}
</div>
</div>
<SheetFooter className="absolute bottom-0 left-0 right-0 h-16 bg-primary" />
</SheetContent>
</Sheet>
<Logo className="-translate-y-1/2 absolute top-1/2 left-1/2 -translate-x-1/2 w-[79px] h-auto z-10" />
</div>
);
}