103 lines
3.3 KiB
TypeScript
103 lines
3.3 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* MobileNavToggle — hamburger button that opens the global section drawer
|
|
* below the md breakpoint.
|
|
*
|
|
* Built on the project's wrapped shadcn Drawer (which composes vaul). The
|
|
* raw `vaul` primitive + `asChild` pattern was unreliable here — the
|
|
* wrapped components handle ref forwarding and portal mounting correctly
|
|
* out of the box, and they already encode the project's z-index convention.
|
|
*
|
|
* Kept separate from the per-page MobileNav (which renders a book's
|
|
* sidebar) so reading pages keep their existing drawer untouched.
|
|
*/
|
|
|
|
import { useState } from "react";
|
|
import Link from "next/link";
|
|
import { Menu } from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
import { useHidesAppChrome } from "@/lib/use-chrome-visibility";
|
|
import {
|
|
Drawer,
|
|
DrawerContent,
|
|
DrawerDescription,
|
|
DrawerHeader,
|
|
DrawerTitle,
|
|
DrawerTrigger,
|
|
} from "@/components/ui/drawer";
|
|
|
|
type NavItem = { href: string; label: string };
|
|
|
|
const SECONDARY: NavItem[] = [
|
|
{ href: "/disciples", label: "Disciples" },
|
|
{ href: "/journals", label: "Journals" },
|
|
{ href: "/magazines", label: "Magazines" },
|
|
{ href: "/other-documents", label: "Other Documents" },
|
|
{ href: "/downloads", label: "Downloads" },
|
|
{ href: "/about", label: "About" },
|
|
];
|
|
|
|
export function MobileNavToggle({
|
|
items,
|
|
}: {
|
|
items: ReadonlyArray<NavItem>;
|
|
}) {
|
|
const [open, setOpen] = useState(false);
|
|
// A thread already has a back button in its own header; a hamburger beside
|
|
// it offers a second, conflicting way out.
|
|
const hidden = useHidesAppChrome();
|
|
if (hidden) return null;
|
|
|
|
return (
|
|
<Drawer open={open} onOpenChange={setOpen} direction="left">
|
|
<DrawerTrigger
|
|
aria-label="Open menu"
|
|
className={cn(
|
|
"size-9 inline-flex items-center justify-center rounded-lg",
|
|
"text-foreground/80 hover:text-foreground hover:bg-foreground/5 transition-colors",
|
|
)}
|
|
>
|
|
<Menu className="size-5" />
|
|
</DrawerTrigger>
|
|
<DrawerContent
|
|
direction="left"
|
|
className="h-full w-72 max-w-[80%]"
|
|
>
|
|
<DrawerHeader className="text-left border-b border-border pb-4">
|
|
<DrawerTitle className="font-[family-name:var(--font-title)] font-semibold uppercase tracking-[0.14em] text-sm">
|
|
Prabhupāda Says
|
|
</DrawerTitle>
|
|
<DrawerDescription className="sr-only">
|
|
Quickly jump between sections of Prabhupāda Says.
|
|
</DrawerDescription>
|
|
</DrawerHeader>
|
|
|
|
<nav className="flex-1 overflow-y-auto px-3 py-2">
|
|
{items.map((item) => (
|
|
<Link
|
|
key={item.href}
|
|
href={item.href}
|
|
onClick={() => setOpen(false)}
|
|
className="block rounded-lg px-3 py-2.5 text-base text-foreground hover:bg-muted transition-colors"
|
|
>
|
|
{item.label}
|
|
</Link>
|
|
))}
|
|
<div className="my-3 border-t border-border" />
|
|
{SECONDARY.map((item) => (
|
|
<Link
|
|
key={item.href}
|
|
href={item.href}
|
|
onClick={() => setOpen(false)}
|
|
className="block rounded-lg px-3 py-2.5 text-sm text-muted-foreground hover:bg-muted hover:text-foreground transition-colors"
|
|
>
|
|
{item.label}
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
</DrawerContent>
|
|
</Drawer>
|
|
);
|
|
}
|