161 lines
5.4 KiB
TypeScript
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>
|
|
);
|
|
}
|