'use client'; import * as React from 'react'; import { TransitionLink } from '@/components/ui/TransitionLink'; import Image from 'next/image'; import { usePathname } from 'next/navigation'; import { LanguageSwitcher } from './LanguageSwitcher'; export interface NavLink { label: string; url: string; children?: NavLink[]; isGroupLabel?: boolean; } interface HeaderProps { navLinks: NavLink[]; } export function Header({ navLinks }: HeaderProps) { const [isScrolled, setIsScrolled] = React.useState(false); const [forceSolid, setForceSolid] = React.useState(false); const [headerVariant, setHeaderVariant] = React.useState<'capsule' | 'standard'>('capsule'); const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false); const pathname = usePathname() || '/'; const shineRef = React.useRef(null); // Determine current locale from pathname const currentLocale = pathname.startsWith('/en') ? 'en' : 'de'; React.useEffect(() => { let animationFrameId: number; const handleScroll = () => { setIsScrolled(window.scrollY > 20); if (shineRef.current) { const y = window.scrollY; const adjustedY = Math.max(0, y - 20); const range = 800; const progress = (adjustedY % range) / range; const x = -150 + progress * 300; cancelAnimationFrame(animationFrameId); animationFrameId = requestAnimationFrame(() => { if (shineRef.current) { shineRef.current.style.transform = `translateX(${x}%)`; } }); } }; window.addEventListener('scroll', handleScroll); // Check for forced solid header (used by error pages, legal pages without hero, etc.) const checkHeaderState = () => { setForceSolid(document.body.getAttribute('data-force-solid-header') === 'true'); setHeaderVariant((document.body.getAttribute('data-header-variant') as 'capsule' | 'standard') || 'capsule'); }; checkHeaderState(); // Set up observer for client-side navigation changes const observer = new MutationObserver(checkHeaderState); observer.observe(document.body, { attributes: true, attributeFilter: ['data-force-solid-header', 'data-header-variant'] }); // Re-check when pathname changes checkHeaderState(); setIsMobileMenuOpen(false); return () => { window.removeEventListener('scroll', handleScroll); observer.disconnect(); }; }, [pathname]); const isSolidMode = isScrolled || forceSolid || headerVariant === 'standard'; const isStandard = headerVariant === 'standard'; return ( <>
{/* Scroll bound shine effect */}
E-TIB Gruppe {/* Masked sweep overlay on hover */}
{/* Right side elements (Language Switcher always visible, Contact button desktop only) */}
{/* Quick Actions (Mobile Only) */} {/* Language Switcher visible on desktop only */}
{/* Contact Button Desktop Only */}
); } function NavItem({ link, currentLocale, pathname, isSolidMode }: { link: NavLink, currentLocale: string, pathname: string, isSolidMode: boolean }) { const [isHovered, setIsHovered] = React.useState(false); // Close dropdown on navigation React.useEffect(() => { setIsHovered(false); }, [pathname]); // Close dropdown on scroll React.useEffect(() => { const handleScroll = () => { if (isHovered) setIsHovered(false); }; window.addEventListener('scroll', handleScroll, { passive: true }); return () => window.removeEventListener('scroll', handleScroll); }, [isHovered]); const mappedUrl = link.url.startsWith('/') && !link.url.match(/^\/(en|de)/) ? `/${currentLocale}${link.url}` : link.url; const isActive = pathname === mappedUrl || (mappedUrl !== `/${currentLocale}` && pathname?.startsWith(`${mappedUrl}/`)); return (
setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > {link.label} {link.children && ( )} {/* Active Indicator */} {isActive && !link.children && (
)} {/* Subtle hover underline */} <> {link.children && (
{/* Top glowing accent line */}
{link.children.map((child, idx) => { const childUrl = child.url.startsWith('/') && !child.url.match(/^\/(en|de)/) ? `/${currentLocale}${child.url}` : child.url; const isChildActive = pathname === childUrl; if (child.isGroupLabel) { return (
{child.label}
); } return ( setIsHovered(false)} className={`group/dropitem relative block px-4 py-3.5 rounded-2xl text-sm font-medium transition-all duration-300 overflow-hidden ${ isSolidMode ? isChildActive ? 'bg-primary/10 text-primary' : 'text-neutral-600 hover:text-primary hover:bg-neutral-50/80' : isChildActive ? 'bg-white/10 text-white' : 'text-neutral-300 hover:text-white hover:bg-white/[0.06]' }`} >
{child.label}
); })}
)}
); }