'use client'; import Link from 'next/link'; import Image from 'next/image'; import { motion } from 'framer-motion'; import { useTranslations } from 'next-intl'; import { usePathname } from 'next/navigation'; import { Button } from './ui'; import { useEffect, useState, useRef } from 'react'; import { cn } from './ui'; import { useAnalytics } from './analytics/useAnalytics'; import { AnalyticsEvents } from './analytics/analytics-events'; export default function Header() { const t = useTranslations('Navigation'); const pathname = usePathname(); const { trackEvent } = useAnalytics(); const [isScrolled, setIsScrolled] = useState(false); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const mobileMenuRef = useRef(null); const closeButtonRef = useRef(null); // Extract locale from pathname const currentLocale = pathname.split('/')[1] || 'en'; // Check if homepage const isHomePage = pathname === `/${currentLocale}` || pathname === '/'; useEffect(() => { const handleScroll = () => { setIsScrolled(window.scrollY > 50); }; window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll); }, []); // Prevent scroll when mobile menu is open // Prevent scroll when mobile menu is open and handle focus trap useEffect(() => { if (isMobileMenuOpen) { document.body.style.overflow = 'hidden'; // Focus trap logic const focusableElements = mobileMenuRef.current?.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])', ); if (focusableElements && focusableElements.length > 0) { const firstElement = focusableElements[0] as HTMLElement; const lastElement = focusableElements[focusableElements.length - 1] as HTMLElement; const handleTabKey = (e: KeyboardEvent) => { if (e.key === 'Tab') { if (e.shiftKey) { if (document.activeElement === firstElement) { e.preventDefault(); lastElement.focus(); } } else { if (document.activeElement === lastElement) { e.preventDefault(); firstElement.focus(); } } } }; const handleEscapeKey = (e: KeyboardEvent) => { if (e.key === 'Escape') { setIsMobileMenuOpen(false); } }; document.addEventListener('keydown', handleTabKey); document.addEventListener('keydown', handleEscapeKey); // Focus the first element when menu opens setTimeout(() => firstElement.focus(), 100); return () => { document.removeEventListener('keydown', handleTabKey); document.removeEventListener('keydown', handleEscapeKey); }; } } else { document.body.style.overflow = 'unset'; } }, [isMobileMenuOpen]); // Function to get path for a different locale const getPathForLocale = (newLocale: string) => { const segments = pathname.split('/'); segments[1] = newLocale; return segments.join('/'); }; const menuItems = [ { label: t('home'), href: '/' }, { label: t('team'), href: '/team' }, { label: t('products'), href: currentLocale === 'de' ? '/produkte' : '/products' }, { label: t('blog'), href: '/blog' }, ]; const headerClass = cn( 'fixed top-0 left-0 right-0 z-50 transition-all duration-500 safe-area-p transform-gpu', { 'bg-transparent py-4 md:py-8': isHomePage && !isScrolled && !isMobileMenuOpen, 'bg-primary py-3 md:py-4 shadow-2xl': !isHomePage || isScrolled || isMobileMenuOpen, }, ); const textColorClass = 'text-white'; const logoSrc = '/logo-white.svg'; return ( <>
trackEvent(AnalyticsEvents.BUTTON_CLICK, { target: 'home_logo', location: 'header', }) } > {t('home')} {menuItems.map((item, _idx) => ( { setIsMobileMenuOpen(false); trackEvent(AnalyticsEvents.LINK_CLICK, { label: item.label, href: item.href, location: 'header_nav', }); }} className={cn( textColorClass, 'hover:text-accent font-bold transition-all duration-500 text-base md:text-lg tracking-tight relative group inline-block hover:-translate-y-0.5', )} > {item.label} ))} trackEvent(AnalyticsEvents.TOGGLE_SWITCH, { type: 'language', from: currentLocale, to: 'en', location: 'header', }) } className={`hover:text-accent transition-colors flex items-center gap-2 touch-target ${currentLocale === 'en' ? 'text-accent' : 'opacity-60'}`} > EN trackEvent(AnalyticsEvents.TOGGLE_SWITCH, { type: 'language', from: currentLocale, to: 'de', location: 'header', }) } className={`hover:text-accent transition-colors flex items-center gap-2 touch-target ${currentLocale === 'de' ? 'text-accent' : 'opacity-60'}`} > DE {/* Mobile Menu Button */} { const newState = !isMobileMenuOpen; setIsMobileMenuOpen(newState); trackEvent(AnalyticsEvents.BUTTON_CLICK, { type: 'mobile_menu', action: newState ? 'open' : 'close', }); }} > {isMobileMenuOpen ? ( ) : ( )}
{/* Mobile Menu Overlay */}
); } const navVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.06, delayChildren: 0.1, }, }, } as const; const navLinkVariants = { hidden: { opacity: 0, y: 20, scale: 0.9 }, visible: { opacity: 1, y: 0, scale: 1, transition: { duration: 0.5, ease: 'easeOut', }, }, } as const; const headerRightVariants = { hidden: { opacity: 0, x: 30 }, visible: { opacity: 1, x: 0, transition: { duration: 0.6, ease: 'easeOut' }, }, } as const;