feat: Add mobile hamburger menu and Videos link to Browse dropdown
Some checks are pending
Deploy Elmeg / deploy (push) Waiting to run

This commit is contained in:
fullsizemalt 2025-12-23 00:58:21 -08:00
parent 735fd1a6ea
commit 1b11ad8b52

View file

@ -1,6 +1,7 @@
"use client" "use client"
import { useState } from "react"
import Link from "next/link" import Link from "next/link"
import { Music, User, ChevronDown } from "lucide-react" import { Music, User, ChevronDown, Menu, X } from "lucide-react"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { SearchDialog } from "@/components/ui/search-dialog" import { SearchDialog } from "@/components/ui/search-dialog"
import { NotificationBell } from "@/components/notifications/notification-bell" import { NotificationBell } from "@/components/notifications/notification-bell"
@ -14,66 +15,67 @@ import {
} from "@/components/ui/dropdown-menu" } from "@/components/ui/dropdown-menu"
import { useAuth } from "@/contexts/auth-context" import { useAuth } from "@/contexts/auth-context"
const browseLinks = [
{ href: "/shows", label: "Shows" },
{ href: "/venues", label: "Venues" },
{ href: "/songs", label: "Songs" },
{ href: "/performances", label: "Top Performances" },
{ href: "/tours", label: "Tours" },
{ href: "/videos", label: "Videos" },
]
export function Navbar() { export function Navbar() {
const { user, logout } = useAuth() const { user, logout } = useAuth()
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
return ( return (
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60"> <header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 flex h-14 items-center"> <div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 flex h-14 items-center justify-between">
<div className="mr-4 hidden md:flex"> {/* Logo - always visible */}
<Link href="/" className="mr-6 flex items-center space-x-2"> <Link href="/" className="flex items-center space-x-2">
<Music className="h-6 w-6" /> <Music className="h-6 w-6" />
<span className="hidden font-bold sm:inline-block"> <span className="font-bold">Elmeg</span>
Elmeg </Link>
</span>
{/* Desktop Navigation */}
<nav className="hidden md:flex items-center space-x-6 text-sm font-medium">
<Link href="/archive" className="transition-colors hover:text-foreground/80 text-foreground/60">
Archive
</Link> </Link>
<nav className="flex items-center space-x-6 text-sm font-medium">
<Link href="/archive" className="transition-colors hover:text-foreground/80 text-foreground/60">
Archive
</Link>
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger className="flex items-center space-x-1 transition-colors hover:text-foreground/80 text-foreground/60 outline-none"> <DropdownMenuTrigger className="flex items-center space-x-1 transition-colors hover:text-foreground/80 text-foreground/60 outline-none">
<span>Browse</span> <span>Browse</span>
<ChevronDown className="h-4 w-4" /> <ChevronDown className="h-4 w-4" />
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="start"> <DropdownMenuContent align="start">
<Link href="/shows"> {browseLinks.map((link) => (
<DropdownMenuItem>Shows</DropdownMenuItem> <Link key={link.href} href={link.href}>
<DropdownMenuItem>{link.label}</DropdownMenuItem>
</Link> </Link>
<Link href="/venues"> ))}
<DropdownMenuItem>Venues</DropdownMenuItem> </DropdownMenuContent>
</Link> </DropdownMenu>
<Link href="/songs">
<DropdownMenuItem>Songs</DropdownMenuItem>
</Link>
<Link href="/performances">
<DropdownMenuItem>Top Performances</DropdownMenuItem>
</Link>
<Link href="/tours">
<DropdownMenuItem>Tours</DropdownMenuItem>
</Link>
{/* Leaderboards hidden until community activity grows */}
</DropdownMenuContent>
</DropdownMenu>
<Link href="/about" className="transition-colors hover:text-foreground/80 text-foreground/60"> <Link href="/about" className="transition-colors hover:text-foreground/80 text-foreground/60">
About About
</Link> </Link>
</nav> </nav>
</div>
<div className="flex flex-1 items-center justify-between space-x-2 md:justify-end"> {/* Right side - search, theme, auth */}
<div className="w-full flex-1 md:w-auto md:flex-none"> <div className="flex items-center gap-2">
<div className="hidden sm:block">
<SearchDialog /> <SearchDialog />
</div> </div>
<ThemeToggle /> <ThemeToggle />
<nav className="flex items-center gap-2">
{/* Desktop auth */}
<div className="hidden md:flex items-center gap-2">
{user ? ( {user ? (
<> <>
{(user.role === 'admin' || user.role === 'moderator') && ( {(user.role === 'admin' || user.role === 'moderator') && (
<Link href="/mod"> <Link href="/mod">
<Button variant="ghost" size="sm"> <Button variant="ghost" size="sm">Mod</Button>
Mod
</Button>
</Link> </Link>
)} )}
<NotificationBell /> <NotificationBell />
@ -103,22 +105,119 @@ export function Navbar() {
</DropdownMenu> </DropdownMenu>
</> </>
) : ( ) : (
<div className="flex items-center gap-2"> <>
<Link href="/login"> <Link href="/login">
<Button variant="ghost" size="sm"> <Button variant="ghost" size="sm">Sign In</Button>
Sign In
</Button>
</Link> </Link>
<Link href="/register"> <Link href="/register">
<Button size="sm"> <Button size="sm">Sign Up</Button>
Sign Up
</Button>
</Link> </Link>
</div> </>
)} )}
</nav> </div>
{/* Mobile menu button */}
<Button
variant="ghost"
size="icon"
className="md:hidden"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
>
{mobileMenuOpen ? <X className="h-5 w-5" /> : <Menu className="h-5 w-5" />}
<span className="sr-only">Toggle menu</span>
</Button>
</div> </div>
</div> </div>
{/* Mobile Menu */}
{mobileMenuOpen && (
<div className="md:hidden border-t bg-background">
<div className="container mx-auto max-w-7xl px-4 py-4 space-y-4">
{/* Mobile search */}
<div className="sm:hidden">
<SearchDialog />
</div>
{/* Mobile nav links */}
<nav className="flex flex-col space-y-2">
<Link
href="/archive"
className="px-3 py-2 rounded-md hover:bg-muted transition-colors"
onClick={() => setMobileMenuOpen(false)}
>
Archive
</Link>
<div className="px-3 py-2 text-sm font-medium text-muted-foreground">Browse</div>
{browseLinks.map((link) => (
<Link
key={link.href}
href={link.href}
className="px-6 py-2 rounded-md hover:bg-muted transition-colors"
onClick={() => setMobileMenuOpen(false)}
>
{link.label}
</Link>
))}
<Link
href="/about"
className="px-3 py-2 rounded-md hover:bg-muted transition-colors"
onClick={() => setMobileMenuOpen(false)}
>
About
</Link>
</nav>
{/* Mobile auth */}
<div className="border-t pt-4">
{user ? (
<div className="flex flex-col space-y-2">
<div className="px-3 py-2 text-sm text-muted-foreground">{user.email}</div>
{(user.role === 'admin' || user.role === 'moderator') && (
<Link
href="/mod"
className="px-3 py-2 rounded-md hover:bg-muted transition-colors"
onClick={() => setMobileMenuOpen(false)}
>
Moderation
</Link>
)}
<Link
href="/profile"
className="px-3 py-2 rounded-md hover:bg-muted transition-colors"
onClick={() => setMobileMenuOpen(false)}
>
Profile
</Link>
<Link
href="/settings"
className="px-3 py-2 rounded-md hover:bg-muted transition-colors"
onClick={() => setMobileMenuOpen(false)}
>
Settings
</Link>
<button
onClick={() => { logout(); setMobileMenuOpen(false); }}
className="px-3 py-2 text-left rounded-md text-red-500 hover:bg-muted transition-colors"
>
Sign Out
</button>
</div>
) : (
<div className="flex gap-2">
<Link href="/login" className="flex-1" onClick={() => setMobileMenuOpen(false)}>
<Button variant="outline" className="w-full">Sign In</Button>
</Link>
<Link href="/register" className="flex-1" onClick={() => setMobileMenuOpen(false)}>
<Button className="w-full">Sign Up</Button>
</Link>
</div>
)}
</div>
</div>
</div>
)}
</header> </header>
) )
} }