Files
nextjs-saas/components/site/mobile-navigation.tsx
T
2026-09-17 23:08:26 -04:00

136 lines
5.4 KiB
TypeScript

'use client';
import { useEffect, useRef, useState } from 'react';
import { RiCloseLine, RiMenuLine } from '@remixicon/react';
import { Logo } from '@/components/site/logo';
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetTitle,
SheetTrigger,
} from '@/components/ui/sheet';
export type NavigationItem = {
label: string;
href: string;
description: string;
};
export function MobileNavigation({ items }: { items: NavigationItem[] }) {
const [open, setOpen] = useState(false);
const navigating = useRef(false);
useEffect(() => {
const desktop = window.matchMedia('(min-width: 768px)');
const closeOnDesktop = () => {
if (desktop.matches) setOpen(false);
};
desktop.addEventListener('change', closeOnDesktop);
return () => desktop.removeEventListener('change', closeOnDesktop);
}, []);
return (
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild>
<button
type="button"
aria-label="Open navigation menu"
className="inline-flex size-10 items-center justify-center rounded-md text-white/70 transition-colors hover:bg-white/5 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30 md:hidden"
>
<RiMenuLine className="size-5" aria-hidden="true" />
</button>
</SheetTrigger>
<SheetContent
side="top"
showCloseButton={false}
overlayClassName="z-[60] bg-black/60 duration-300 supports-backdrop-filter:backdrop-blur-md md:hidden"
className="z-[61] max-h-dvh w-full gap-0 overflow-hidden rounded-none border-white/10 bg-black text-white outline-none duration-300 data-[side=top]:data-open:slide-in-from-top data-[side=top]:data-closed:slide-out-to-top md:hidden"
onCloseAutoFocus={(event) => {
// Let the anchor move focus to its section without the trigger
// interrupting the page's smooth scroll when the sheet closes.
if (navigating.current) event.preventDefault();
navigating.current = false;
}}
>
<div className="flex h-16 shrink-0 items-center justify-between border-b border-white/10 px-6">
<Logo />
<SheetClose asChild>
<button
type="button"
aria-label="Close navigation menu"
className="inline-flex size-10 items-center justify-center rounded-md text-white/60 transition-colors hover:bg-white/5 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30"
>
<RiCloseLine className="size-5" aria-hidden="true" />
</button>
</SheetClose>
</div>
<div className="min-h-0 overflow-y-auto overscroll-contain p-3">
<SheetTitle className="px-3 pb-2 pt-3 text-[10px] font-medium uppercase tracking-[0.2em] text-white/40">
Explore Vertex
</SheetTitle>
<SheetDescription className="sr-only">
Explore our products, solutions, resources, documentation, and pricing.
</SheetDescription>
<nav aria-label="Mobile navigation">
<ul className="space-y-1">
{items.map(({ label, href, description }) => (
<li key={label}>
<SheetClose asChild>
<a
href={href}
onClick={() => {
navigating.current = true;
}}
className="flex items-center rounded-xl px-3 py-3 transition-colors hover:bg-white/5 focus-visible:bg-white/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-white/30"
>
<span className="min-w-0">
<span className="block text-xl font-medium tracking-tight">
{label}
</span>
<span className="mt-0.5 block text-xs leading-5 text-white/45">
{description}
</span>
</span>
</a>
</SheetClose>
</li>
))}
</ul>
</nav>
</div>
<div className="shrink-0 space-y-2 border-t border-white/10 bg-white/[0.02] p-5">
<SheetClose asChild>
<a
href="#"
onClick={() => {
navigating.current = true;
}}
className="flex h-12 items-center justify-center rounded-full bg-white px-4 text-sm font-medium text-black transition-colors hover:bg-white/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30 focus-visible:ring-offset-2 focus-visible:ring-offset-black"
>
Sign Up
</a>
</SheetClose>
<SheetClose asChild>
<a
href="#"
onClick={() => {
navigating.current = true;
}}
className="flex h-12 items-center justify-center rounded-full border border-white/10 px-4 text-sm font-medium text-white/70 transition-colors hover:bg-white/5 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30"
>
Log In
</a>
</SheetClose>
</div>
</SheetContent>
</Sheet>
);
}