diff --git a/src/components/Header.tsx b/src/components/Header.tsx index e562cde..cbf5ec1 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -8,13 +8,14 @@ import { useAuthContext } from "@/contexts/AuthContext"; import { createClient } from "@/utils/supabase/client"; import Avatar from "@/components/Account/Avatar"; -function NavLink({ href, label, className = "" }: { href: string; label: React.ReactNode; className?: string }) { +function NavLink({ href, label, className = "", onClick }: { href: string; label: React.ReactNode; className?: string; onClick?: () => void }) { const pathname = usePathname(); const isActive = pathname === href; return ( (false); const [userId, setUserId] = React.useState(null); const [avatarUrl, setAvatarUrl] = React.useState(null); + const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false); React.useEffect(() => { let isMounted = true; @@ -58,6 +60,32 @@ export default function Header() { }; }, [supabase, user]); + // Close mobile menu on route change for better UX + React.useEffect(() => { + setIsMobileMenuOpen(false); + }, [pathname]); + + // Lock background scroll when mobile menu is open + React.useEffect(() => { + if (isMobileMenuOpen) { + const original = document.body.style.overflow; + document.body.style.overflow = "hidden"; + return () => { + document.body.style.overflow = original; + }; + } + }, [isMobileMenuOpen]); + + // Close on Escape key + React.useEffect(() => { + if (!isMobileMenuOpen) return; + const onKeyDown = (e: KeyboardEvent) => { + if (e.key === "Escape") setIsMobileMenuOpen(false); + }; + window.addEventListener("keydown", onKeyDown); + return () => window.removeEventListener("keydown", onKeyDown); + }, [isMobileMenuOpen]); + return ( @@ -65,41 +93,118 @@ export default function Header() { Hackdex - - - - My Base ROMs - - {countReady} + + + + + + My Base ROMs + + {countReady} + - - } - /> - + + {isAuthenticated && ( + + + + + )} + + + setIsMobileMenuOpen((v) => !v)} > - Submit - - {isAuthenticated && ( - - - - - )} - + {isMobileMenuOpen ? ( + + ) : ( + + )} + + + + {/* Mobile menu panel (animated) */} + + + + setIsMobileMenuOpen(false)} /> + setIsMobileMenuOpen(false)} + label={ + + My Base ROMs + + {countReady} + + + } + /> + setIsMobileMenuOpen(false)} + /> + {isAuthenticated && ( + setIsMobileMenuOpen(false)} + data-active={pathname === "/account" || undefined} + className="mt-1 inline-flex items-center gap-3 rounded-md px-3 py-3 ring-1 ring-[var(--border)]" + aria-label="Open account" + title="Account" + > + + Account + + )} + + + + + {/* Scrim overlay */} + setIsMobileMenuOpen(false)} + /> ); }