feat(ui): finalize E-TIB modernization with footer redesign, video optimization, and TS fixes

Former-commit-id: 67ac02c8404cc66893fdf97308574701cca6000c
This commit is contained in:
2026-05-07 10:43:20 +02:00
parent f2fdea96ec
commit 5439df72ea
3712 changed files with 932332 additions and 1867 deletions

View File

@@ -5,6 +5,7 @@ import Link from 'next/link';
import Image from 'next/image';
import { usePathname } from 'next/navigation';
import { motion, AnimatePresence } from 'framer-motion';
import { LanguageSwitcher } from './LanguageSwitcher';
export interface NavLink {
label: string;
@@ -18,6 +19,7 @@ interface HeaderProps {
export function Header({ navLinks }: HeaderProps) {
const [isScrolled, setIsScrolled] = React.useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);
const [forceSolid, setForceSolid] = React.useState(false);
const pathname = usePathname() || '/';
// Determine current locale from pathname
@@ -35,27 +37,39 @@ export function Header({ navLinks }: HeaderProps) {
setIsScrolled(window.scrollY > 20);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// Check for forced solid header (used by error pages, legal pages without hero, etc.)
const checkSolid = () => {
setForceSolid(document.body.getAttribute('data-force-solid-header') === 'true');
};
checkSolid();
// Set up observer for client-side navigation changes
const observer = new MutationObserver(checkSolid);
observer.observe(document.body, { attributes: true, attributeFilter: ['data-force-solid-header'] });
// Re-check when pathname changes
checkSolid();
return () => {
window.removeEventListener('scroll', handleScroll);
observer.disconnect();
};
}, [pathname]);
// Close mobile menu on route change
React.useEffect(() => {
setIsMobileMenuOpen(false);
}, [pathname]);
const LanguageSwitcher = ({ mobile = false }) => (
<div className={`flex items-center gap-2 ${mobile ? 'text-xl' : 'text-sm font-bold'} ${mobile ? 'text-neutral-dark' : isScrolled ? 'text-text-primary' : 'text-neutral-light'}`}>
<Link href={getSwitchedUrl('de')} className={`transition-colors hover:text-primary ${currentLocale === 'de' ? 'text-primary' : ''}`}>DE</Link>
<span className="opacity-50">|</span>
<Link href={getSwitchedUrl('en')} className={`transition-colors hover:text-primary ${currentLocale === 'en' ? 'text-primary' : ''}`}>EN</Link>
</div>
);
const isSolidMode = isScrolled || forceSolid;
return (
<>
<header
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ease-in-out ${
isScrolled
isSolidMode
? 'bg-neutral-light/90 backdrop-blur-md shadow-sm py-4'
: 'bg-transparent py-6'
}`}
@@ -63,7 +77,7 @@ export function Header({ navLinks }: HeaderProps) {
<div className="container flex items-center justify-between">
<Link href={`/${currentLocale}`} className="relative flex items-center h-12 w-48 z-50">
<Image
src={(isScrolled || isMobileMenuOpen) ? "/assets/logo.png" : "/assets/logo-white.png"}
src={(isSolidMode || isMobileMenuOpen) ? "/assets/logo.png" : "/assets/logo-white.png"}
alt="E-TIB Gruppe"
fill
className="object-contain object-left"
@@ -83,7 +97,7 @@ export function Header({ navLinks }: HeaderProps) {
key={link.url}
href={mappedUrl}
className={`font-semibold text-sm uppercase tracking-widest transition-all duration-300 ${
isScrolled
isSolidMode
? 'text-text-primary hover:text-primary'
: 'text-neutral-light hover:text-primary-light'
}`}
@@ -92,8 +106,8 @@ export function Header({ navLinks }: HeaderProps) {
</Link>
);
})}
<div className="h-4 w-px bg-white/20 mx-2" />
<LanguageSwitcher />
<div className={`h-4 w-px mx-2 transition-colors duration-300 ${isSolidMode ? 'bg-neutral-300' : 'bg-white/20'}`} />
<LanguageSwitcher isSolidMode={isSolidMode} />
<Link
href={`/${currentLocale}/${currentLocale === 'de' ? 'kontakt' : 'contact'}`}
className="rounded-xl bg-primary hover:bg-primary-dark text-neutral-light px-8 py-3 font-bold text-sm uppercase tracking-wider transition-all shadow-xl hover:shadow-primary/20 hover:-translate-y-0.5 active:translate-y-0"
@@ -108,7 +122,7 @@ export function Header({ navLinks }: HeaderProps) {
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
aria-label="Toggle menu"
>
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={(isScrolled || isMobileMenuOpen) ? "currentColor" : "white"} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke={(isSolidMode || isMobileMenuOpen) ? "currentColor" : "white"} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
{isMobileMenuOpen ? (
<>
<line x1="18" y1="6" x2="6" y2="18"></line>