Add working mobile hamburger menu
This commit is contained in:
@@ -1,3 +1,6 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { Menu, X } from 'lucide-react'
|
||||||
|
|
||||||
type NavItem = { href: string; label: string }
|
type NavItem = { href: string; label: string }
|
||||||
|
|
||||||
const navItems: NavItem[] = [
|
const navItems: NavItem[] = [
|
||||||
@@ -9,12 +12,25 @@ const navItems: NavItem[] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export default function NavBar() {
|
export default function NavBar() {
|
||||||
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
|
|
||||||
|
const handleClick = (href: string) => {
|
||||||
|
setIsOpen(false)
|
||||||
|
// Smooth scroll to section
|
||||||
|
const element = document.querySelector(href)
|
||||||
|
if (element) {
|
||||||
|
element.scrollIntoView({ behavior: 'smooth' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="fixed inset-x-0 top-0 z-50 border-b border-slate-200/70 bg-white/80 backdrop-blur">
|
<header className="fixed inset-x-0 top-0 z-50 border-b border-slate-200/70 bg-white/80 backdrop-blur">
|
||||||
<nav className="mx-auto flex max-w-6xl items-center justify-between px-4 py-3" aria-label="Primary">
|
<nav className="mx-auto flex max-w-6xl items-center justify-between px-4 py-3" aria-label="Primary">
|
||||||
<a href="#introduction" className="font-semibold tracking-wide text-slate-800">
|
<a href="#introduction" className="font-semibold tracking-wide text-slate-800">
|
||||||
Peter Myers
|
Peter Myers
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
{/* Desktop menu */}
|
||||||
<ul className="hidden items-center gap-6 md:flex">
|
<ul className="hidden items-center gap-6 md:flex">
|
||||||
{navItems.map((item) => (
|
{navItems.map((item) => (
|
||||||
<li key={item.href}>
|
<li key={item.href}>
|
||||||
@@ -27,14 +43,39 @@ export default function NavBar() {
|
|||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
<a
|
|
||||||
href="#introduction"
|
{/* Mobile menu button */}
|
||||||
className="md:hidden text-sm font-medium text-slate-700 hover:text-slate-900"
|
<button
|
||||||
aria-label="Jump to introduction"
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
|
className="md:hidden p-2 text-slate-700 hover:text-slate-900 focus:outline-none focus:ring-2 focus:ring-emerald-500/60 rounded"
|
||||||
|
aria-label={isOpen ? 'Close menu' : 'Open menu'}
|
||||||
|
aria-expanded={isOpen}
|
||||||
>
|
>
|
||||||
Menu
|
{isOpen ? <X className="h-6 w-6" /> : <Menu className="h-6 w-6" />}
|
||||||
</a>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
{/* Mobile menu overlay */}
|
||||||
|
{isOpen && (
|
||||||
|
<div className="md:hidden border-t border-slate-200/70 bg-white/95 backdrop-blur">
|
||||||
|
<ul className="px-4 py-3 space-y-2">
|
||||||
|
{navItems.map((item) => (
|
||||||
|
<li key={item.href}>
|
||||||
|
<a
|
||||||
|
href={item.href}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
handleClick(item.href)
|
||||||
|
}}
|
||||||
|
className="block py-2 text-base font-medium text-slate-700 hover:text-slate-900 hover:bg-emerald-50/50 rounded px-2"
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user