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 - + {isMobileMenuOpen ? ( + + ) : ( + + )} + +
+ + {/* Mobile menu panel (animated) */} + + + {/* Scrim overlay */} +
); }