feat(ui): redesign header to premium floating pill with framer-motion active indicators and dynamic CTA
Former-commit-id: 4586ca5af936d5f81485e92af70353ccfcfb767a
This commit is contained in:
@@ -69,50 +69,71 @@ export function Header({ navLinks }: HeaderProps) {
|
||||
return (
|
||||
<>
|
||||
<header
|
||||
className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ease-in-out ${
|
||||
isSolidMode
|
||||
? 'bg-neutral-light/90 backdrop-blur-md shadow-sm py-4'
|
||||
: 'bg-transparent py-6'
|
||||
className={`fixed top-0 left-0 right-0 z-50 flex justify-center transition-all duration-700 ease-[cubic-bezier(0.16,1,0.3,1)] ${
|
||||
isSolidMode ? 'pt-4 px-4' : 'pt-0 px-0'
|
||||
}`}
|
||||
>
|
||||
<div className="container flex items-center justify-between">
|
||||
<Link href={`/${currentLocale}`} className="relative flex items-center h-12 w-48 z-50">
|
||||
<div
|
||||
className={`w-full transition-all duration-700 ease-[cubic-bezier(0.16,1,0.3,1)] flex items-center justify-between ${
|
||||
isSolidMode
|
||||
? 'max-w-7xl rounded-full bg-white/85 backdrop-blur-2xl shadow-[0_8px_32px_rgba(0,0,0,0.08)] border border-white/60 py-2.5 px-6 md:px-8'
|
||||
: 'bg-transparent py-6 container'
|
||||
}`}
|
||||
>
|
||||
<Link href={`/${currentLocale}`} className={`relative flex items-center transition-all duration-500 ease-out z-50 group ${isSolidMode ? 'h-9 w-36' : 'h-12 w-48'}`}>
|
||||
<Image
|
||||
src={(isSolidMode || isMobileMenuOpen) ? "/assets/logo.png" : "/assets/logo-white.png"}
|
||||
alt="E-TIB Gruppe"
|
||||
fill
|
||||
className="object-contain object-left"
|
||||
className="object-contain object-left group-hover:scale-105 transition-transform duration-500 origin-left"
|
||||
priority
|
||||
sizes="192px"
|
||||
/>
|
||||
</Link>
|
||||
|
||||
<nav className="hidden md:flex items-center gap-10">
|
||||
<nav className="hidden md:flex items-center gap-8 lg:gap-10">
|
||||
{navLinks && navLinks.length > 0 && navLinks.map((link) => {
|
||||
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 (
|
||||
<Link
|
||||
key={link.url}
|
||||
href={mappedUrl}
|
||||
className={`font-semibold text-sm uppercase tracking-widest transition-all duration-300 ${
|
||||
className={`relative font-bold text-xs lg:text-sm uppercase tracking-widest transition-colors duration-300 group py-2 ${
|
||||
isSolidMode
|
||||
? 'text-text-primary hover:text-primary'
|
||||
: 'text-neutral-light hover:text-primary-light'
|
||||
? (isActive ? 'text-primary' : 'text-text-primary hover:text-primary')
|
||||
: (isActive ? 'text-white' : 'text-white/80 hover:text-white')
|
||||
}`}
|
||||
>
|
||||
{link.label}
|
||||
|
||||
{/* Framer Motion Active Indicator */}
|
||||
{isActive && (
|
||||
<motion.div
|
||||
layoutId="header-active-indicator"
|
||||
className={`absolute -bottom-1 left-0 right-0 h-0.5 rounded-full ${isSolidMode ? 'bg-primary' : 'bg-white'}`}
|
||||
transition={{ type: 'spring', stiffness: 400, damping: 30 }}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Subtle hover underline */}
|
||||
<span className={`absolute -bottom-1 left-1/2 w-0 h-0.5 -translate-x-1/2 rounded-full transition-all duration-300 ease-out group-hover:w-full ${isSolidMode ? 'bg-primary/30' : 'bg-white/30'} ${isActive ? 'opacity-0' : 'opacity-100'}`} />
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
<div className={`h-4 w-px mx-2 transition-colors duration-300 ${isSolidMode ? 'bg-neutral-300' : 'bg-white/20'}`} />
|
||||
|
||||
<div className={`h-5 w-px transition-colors duration-300 ${isSolidMode ? 'bg-neutral-200' : 'bg-white/20'}`} />
|
||||
|
||||
<LanguageSwitcher isSolidMode={isSolidMode} />
|
||||
|
||||
<Button
|
||||
href={`/${currentLocale}/${currentLocale === 'de' ? 'kontakt' : 'contact'}`}
|
||||
variant="primary"
|
||||
className="px-8"
|
||||
variant={isSolidMode ? "primary" : "outline"}
|
||||
className={`px-7 py-2.5 ml-2 transition-all duration-500 ${!isSolidMode ? 'border-white/30 hover:border-white text-white hover:bg-white hover:text-neutral-dark' : ''}`}
|
||||
>
|
||||
{currentLocale === 'de' ? 'Kontakt' : 'Contact'}
|
||||
</Button>
|
||||
@@ -120,21 +141,22 @@ export function Header({ navLinks }: HeaderProps) {
|
||||
|
||||
{/* Mobile Nav Button */}
|
||||
<button
|
||||
className="md:hidden z-50 text-primary p-2"
|
||||
className="md:hidden z-50 p-2 relative group"
|
||||
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={(isSolidMode || isMobileMenuOpen) ? "currentColor" : "white"} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
|
||||
<div className={`absolute inset-0 rounded-full transition-all duration-300 ${isSolidMode ? 'bg-neutral-100 group-hover:bg-neutral-200' : 'bg-white/10 group-hover:bg-white/20'}`} />
|
||||
<svg className="relative z-10 transition-transform duration-300 group-hover:scale-110" xmlns="http://www.w3.org/2000/svg" width="24" height="24" 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>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
<line x1="18" y1="6" x2="6" y2="18" className="origin-center animate-in fade-in zoom-in duration-300" />
|
||||
<line x1="6" y1="6" x2="18" y2="18" className="origin-center animate-in fade-in zoom-in duration-300" />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<line x1="3" x2="21" y1="6" y2="6"/>
|
||||
<line x1="3" x2="21" y1="12" y2="12"/>
|
||||
<line x1="3" x2="21" y1="18" y2="18"/>
|
||||
<line x1="3" x2="21" y1="6" y2="6" className="transition-all duration-300 group-hover:translate-x-1" />
|
||||
<line x1="3" x2="21" y1="12" y2="12" />
|
||||
<line x1="3" x2="21" y1="18" y2="18" className="transition-all duration-300 group-hover:-translate-x-1" />
|
||||
</>
|
||||
)}
|
||||
</svg>
|
||||
|
||||
Reference in New Issue
Block a user