Files
triqura-ecd/app/(marketing)/components/minimal-nav.tsx
colinislit f68fc088f7 logo
2025-12-03 15:04:46 +01:00

155 lines
5.0 KiB
TypeScript

'use client'
/**
* Minimal Navigation Component
*
* Fixed top navigation with logo and links.
* Mobile-friendly with hamburger menu.
* Adaptive styling based on scroll position (hero vs content).
*/
import { useState, useEffect } from 'react'
import Link from 'next/link'
import Image from 'next/image'
import { Menu, X } from 'lucide-react'
import type { NavigationContent } from '@/content/schemas/manifesto'
interface MinimalNavProps {
content: NavigationContent
}
export function MinimalNav({ content }: MinimalNavProps) {
const [isMenuOpen, setIsMenuOpen] = useState(false)
const [isScrolled, setIsScrolled] = useState(false)
useEffect(() => {
const handleScroll = () => {
// Check if scrolled past hero section (approximately 100vh)
setIsScrolled(window.scrollY > window.innerHeight * 0.8)
}
window.addEventListener('scroll', handleScroll, { passive: true })
handleScroll() // Initial check
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
// Close menu when clicking outside or on link
useEffect(() => {
if (isMenuOpen) {
const handleClickOutside = () => setIsMenuOpen(false)
document.addEventListener('click', handleClickOutside)
return () => document.removeEventListener('click', handleClickOutside)
}
}, [isMenuOpen])
// Determine nav styling based on scroll position
// On hero: dark nav with light text, on content: light nav with dark text
const navClasses = isScrolled
? 'bg-white/95 backdrop-blur-sm shadow-sm'
: 'bg-slate-900/80 backdrop-blur-sm md:bg-white/80 md:backdrop-blur-sm'
const logoClasses = isScrolled
? 'text-teal-600'
: 'text-white md:text-teal-600'
const linkClasses = isScrolled
? 'text-slate-900 hover:text-slate-700'
: 'text-white hover:text-slate-200 md:mix-blend-difference md:text-white md:hover:opacity-80'
const menuButtonClasses = isScrolled
? 'text-slate-900 focus-visible:outline-slate-900'
: 'text-white focus-visible:outline-white'
return (
<nav
className={`fixed top-0 left-0 right-0 z-[60] transition-colors duration-200 ${navClasses}`}
role="navigation"
aria-label="Hoofdnavigatie"
>
<div className="max-w-7xl mx-auto px-4 md:px-8 py-4 flex justify-between items-center h-16">
{/* Logo */}
<Link
href="/"
className={`flex items-center gap-2 font-black text-xl uppercase font-sans tracking-tight leading-none transition-colors hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:rounded ${logoClasses}`}
aria-label="AI Speedrun Home"
onClick={() => setIsMenuOpen(false)}
>
{content.logo}
<Image
src="/images/aispeedrun-logo.webp"
alt=""
width={40}
height={40}
className="rounded-md"
/>
</Link>
{/* Desktop Navigation Links */}
<div className="hidden md:flex gap-6 items-center" role="list">
{content.links.map((link) => (
<Link
key={link.href}
href={link.href}
className={`font-semibold text-base font-sans transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:rounded ${linkClasses}`}
role="listitem"
>
{link.label}
</Link>
))}
</div>
{/* Mobile Menu Button */}
<button
className={`md:hidden p-2 -mr-2 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:rounded ${menuButtonClasses}`}
onClick={(e) => {
e.stopPropagation()
setIsMenuOpen(!isMenuOpen)
}}
aria-label="Menu"
aria-expanded={isMenuOpen}
aria-controls="mobile-menu"
>
{isMenuOpen ? (
<X className="w-6 h-6" />
) : (
<Menu className="w-6 h-6" />
)}
</button>
</div>
{/* Mobile Menu */}
{isMenuOpen && (
<div
id="mobile-menu"
className={`md:hidden border-t ${
isScrolled
? 'bg-white border-slate-200'
: 'bg-slate-900 border-slate-800'
}`}
onClick={(e) => e.stopPropagation()}
>
<div className="px-4 py-4 space-y-3">
{content.links.map((link) => (
<Link
key={link.href}
href={link.href}
className={`block font-semibold text-base py-2 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:rounded ${
isScrolled
? 'text-slate-900 hover:text-slate-700 focus-visible:outline-slate-900'
: 'text-white hover:text-slate-200 focus-visible:outline-white'
}`}
onClick={() => setIsMenuOpen(false)}
>
{link.label}
</Link>
))}
</div>
</div>
)}
</nav>
)
}