migrate to nextjs
This commit is contained in:
147
components/Layout.tsx
Normal file
147
components/Layout.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
'use client';
|
||||
|
||||
import { ArrowUp, Home, Info, Mail } from 'lucide-react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
const pathname = usePathname();
|
||||
const [showScrollTop, setShowScrollTop] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
setShowScrollTop(window.scrollY > 400);
|
||||
};
|
||||
|
||||
const throttledScroll = () => {
|
||||
window.requestAnimationFrame(handleScroll);
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', throttledScroll, { passive: true });
|
||||
return () => window.removeEventListener('scroll', throttledScroll);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
window.scrollTo(0, 0);
|
||||
}, [pathname]);
|
||||
|
||||
const scrollToTop = () => {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
const isActive = (path: string) => pathname === path;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<header className="sticky top-0 z-[100] bg-bg-color/95 backdrop-blur-xl border-b border-secondary-bg pt-[env(safe-area-top)]">
|
||||
<div className="container mx-auto px-4 h-20 flex justify-between items-center">
|
||||
<Link
|
||||
href="/"
|
||||
className="flex items-center"
|
||||
aria-label="MB Grid Solutions - Zur Startseite"
|
||||
>
|
||||
<img
|
||||
src="/assets/logo.png"
|
||||
alt="MB Grid Solutions"
|
||||
className="h-12 md:h-40 transition-all"
|
||||
loading="eager"
|
||||
/>
|
||||
</Link>
|
||||
<nav className="hidden md:flex gap-8" aria-label="Hauptnavigation">
|
||||
<Link href="/" className={`text-xs font-semibold uppercase tracking-widest transition-colors ${isActive('/') ? 'text-accent-green' : 'text-text-primary hover:text-accent-green'}`}>
|
||||
Startseite
|
||||
</Link>
|
||||
<Link href="/ueber-uns" className={`text-xs font-semibold uppercase tracking-widest transition-colors ${isActive('/ueber-uns') ? 'text-accent-green' : 'text-text-primary hover:text-accent-green'}`}>
|
||||
Über uns
|
||||
</Link>
|
||||
<Link href="/kontakt" className={`text-xs font-semibold uppercase tracking-widest transition-colors ${isActive('/kontakt') ? 'text-accent-green' : 'text-text-primary hover:text-accent-green'}`}>
|
||||
Kontakt
|
||||
</Link>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main className="flex-grow pb-[calc(72px+env(safe-area-bottom))] md:pb-0">
|
||||
{children}
|
||||
</main>
|
||||
|
||||
<button
|
||||
onClick={scrollToTop}
|
||||
className={`fixed bottom-24 md:bottom-8 right-5 md:right-8 w-12 md:w-14 h-12 md:h-14 bg-primary text-white rounded-full flex items-center justify-center cursor-pointer z-[900] shadow-lg transition-all duration-300 hover:-translate-y-1 hover:bg-accent-green ${showScrollTop ? 'opacity-100 visible translate-y-0' : 'opacity-0 invisible translate-y-2'}`}
|
||||
aria-label="Nach oben scrollen"
|
||||
aria-hidden={!showScrollTop}
|
||||
tabIndex={showScrollTop ? 0 : -1}
|
||||
>
|
||||
<ArrowUp size={24} strokeWidth={2.5} />
|
||||
</button>
|
||||
|
||||
<nav className="md:hidden fixed bottom-0 left-0 w-full h-[calc(72px+env(safe-area-bottom))] bg-white/95 backdrop-blur-2xl border-t border-black/10 flex justify-around items-start pt-2 z-[1000] px-2" aria-label="Mobile Navigation">
|
||||
<Link
|
||||
href="/"
|
||||
className={`flex flex-col items-center gap-1 text-[10px] font-semibold uppercase tracking-wider flex-1 py-2 transition-colors ${isActive('/') ? 'text-primary' : 'text-gray-400'}`}
|
||||
aria-label="Startseite"
|
||||
>
|
||||
<Home size={22} strokeWidth={2} className={isActive('/') ? 'text-accent-green scale-110' : ''} />
|
||||
<span>Start</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="/ueber-uns"
|
||||
className={`flex flex-col items-center gap-1 text-[10px] font-semibold uppercase tracking-wider flex-1 py-2 transition-colors ${isActive('/ueber-uns') ? 'text-primary' : 'text-gray-400'}`}
|
||||
aria-label="Über uns"
|
||||
>
|
||||
<Info size={22} strokeWidth={2} className={isActive('/ueber-uns') ? 'text-accent-green scale-110' : ''} />
|
||||
<span>Über uns</span>
|
||||
</Link>
|
||||
<Link
|
||||
href="/kontakt"
|
||||
className={`flex flex-col items-center gap-1 text-[10px] font-semibold uppercase tracking-wider flex-1 py-2 transition-colors ${isActive('/kontakt') ? 'text-primary' : 'text-gray-400'}`}
|
||||
aria-label="Kontakt"
|
||||
>
|
||||
<Mail size={22} strokeWidth={2} className={isActive('/kontakt') ? 'text-accent-green scale-110' : ''} />
|
||||
<span>Kontakt</span>
|
||||
</Link>
|
||||
</nav>
|
||||
|
||||
<footer className="bg-white border-t border-secondary-bg py-8 md:py-16 mt-8 md:mt-16">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 md:gap-12 mb-8 md:mb-12">
|
||||
<div className="flex flex-col items-center md:items-start text-center md:text-left">
|
||||
<img
|
||||
src="/assets/logo.png"
|
||||
alt="MB Grid Solutions"
|
||||
className="h-16 md:h-20 mb-6 grayscale"
|
||||
loading="lazy"
|
||||
/>
|
||||
<p className="text-text-secondary text-sm md:text-base leading-relaxed">
|
||||
Ihr Partner für Energiekabelprojekte bis 110 kV.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-center md:items-start text-center md:text-left">
|
||||
<h4 className="text-sm md:text-base font-semibold mb-4">Navigation</h4>
|
||||
<nav className="flex flex-col gap-3" aria-label="Footer Navigation">
|
||||
<Link href="/" className="text-sm md:text-[15px] hover:text-accent-green transition-colors">Startseite</Link>
|
||||
<Link href="/ueber-uns" className="text-sm md:text-[15px] hover:text-accent-green transition-colors">Über uns</Link>
|
||||
<Link href="/kontakt" className="text-sm md:text-[15px] hover:text-accent-green transition-colors">Kontakt</Link>
|
||||
</nav>
|
||||
</div>
|
||||
<div className="flex flex-col items-center md:items-start text-center md:text-left">
|
||||
<h4 className="text-sm md:text-base font-semibold mb-4">Rechtliches</h4>
|
||||
<nav className="flex flex-col gap-3" aria-label="Legal Navigation">
|
||||
<Link href="/impressum" className="text-sm md:text-[15px] hover:text-accent-green transition-colors">Impressum</Link>
|
||||
<Link href="/datenschutz" className="text-sm md:text-[15px] hover:text-accent-green transition-colors">Datenschutz</Link>
|
||||
<Link href="/agb" className="text-sm md:text-[15px] hover:text-accent-green transition-colors">AGB</Link>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-secondary-bg pt-8 flex flex-col md:flex-row justify-between items-center gap-4 text-text-secondary text-xs md:text-sm text-center">
|
||||
<div>© 2026 MB Grid Solutions GmbH. Alle Rechte vorbehalten.</div>
|
||||
<div>Made with precision.</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
Reference in New Issue
Block a user