"use client"; import { useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { formatCompact } from "@/lib/format"; import styles from "./MobileNavToggle.module.css"; interface Section { href: string; label: string; } export function MobileNavToggle({ sections, stars, }: { sections: Section[]; stars: number; }) { const [open, setOpen] = useState(false); const [mounted, setMounted] = useState(false); const toggleRef = useRef(null); useEffect(() => { setMounted(true); }, []); useEffect(() => { if (!open) return; const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") setOpen(false); }; document.addEventListener("keydown", onKey); document.body.style.overflow = "hidden"; return () => { document.removeEventListener("keydown", onKey); document.body.style.overflow = ""; toggleRef.current?.focus(); }; }, [open]); // The parent
uses `backdrop-filter`, which establishes a containing // block for fixed descendants — that would clip the sheet to the header // strip. Portal it to so `position: fixed; inset: 0` covers the // viewport instead. const sheet = (
{ if (e.target === e.currentTarget) setOpen(false); }} >
); return ( <> {mounted ? createPortal(sheet, document.body) : null} ); }