wip
This commit is contained in:
@@ -12,6 +12,7 @@ export default function Header() {
|
||||
const t = useTranslations('Navigation');
|
||||
const pathname = usePathname();
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||
|
||||
// Extract locale from pathname
|
||||
const currentLocale = pathname.split('/')[1] || 'en';
|
||||
@@ -27,6 +28,20 @@ export default function Header() {
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, []);
|
||||
|
||||
// Close mobile menu on route change
|
||||
useEffect(() => {
|
||||
setIsMobileMenuOpen(false);
|
||||
}, [pathname]);
|
||||
|
||||
// Prevent scroll when mobile menu is open
|
||||
useEffect(() => {
|
||||
if (isMobileMenuOpen) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
} else {
|
||||
document.body.style.overflow = 'unset';
|
||||
}
|
||||
}, [isMobileMenuOpen]);
|
||||
|
||||
// Function to get path for a different locale
|
||||
const getPathForLocale = (newLocale: string) => {
|
||||
@@ -45,8 +60,8 @@ export default function Header() {
|
||||
const headerClass = cn(
|
||||
"fixed top-0 left-0 right-0 z-50 transition-all duration-500 safe-area-p",
|
||||
{
|
||||
"bg-transparent py-4 md:py-8": isHomePage && !isScrolled,
|
||||
"bg-primary py-3 md:py-4 shadow-2xl": !isHomePage || isScrolled,
|
||||
"bg-transparent py-4 md:py-8": isHomePage && !isScrolled && !isMobileMenuOpen,
|
||||
"bg-primary py-3 md:py-4 shadow-2xl": !isHomePage || isScrolled || isMobileMenuOpen,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -114,15 +129,79 @@ export default function Header() {
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
<button className={cn("lg:hidden touch-target p-2 rounded-xl bg-white/10 backdrop-blur-md border border-white/20", textColorClass)}>
|
||||
<button
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
className={cn("lg:hidden touch-target p-2 rounded-xl bg-white/10 backdrop-blur-md border border-white/20 z-50", textColorClass)}
|
||||
aria-label="Toggle Menu"
|
||||
>
|
||||
<svg className="w-7 h-7" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||
{isMobileMenuOpen ? (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
) : (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||
)}
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu Overlay */}
|
||||
<div className={cn(
|
||||
"fixed inset-0 bg-primary-dark z-40 lg:hidden transition-all duration-500 ease-in-out flex flex-col",
|
||||
isMobileMenuOpen ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-full pointer-events-none"
|
||||
)}>
|
||||
<div className="flex-grow flex flex-col justify-center items-center p-8 space-y-8">
|
||||
{menuItems.map((item, idx) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={`/${currentLocale}${item.href === '/' ? '' : item.href}`}
|
||||
className={cn(
|
||||
"text-3xl font-extrabold text-white hover:text-accent transition-all transform",
|
||||
isMobileMenuOpen ? "translate-y-0 opacity-100" : "translate-y-10 opacity-0"
|
||||
)}
|
||||
style={{ transitionDelay: `${idx * 100}ms` }}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
))}
|
||||
|
||||
<div className={cn(
|
||||
"pt-8 border-t border-white/10 w-full flex flex-col items-center space-y-8 transition-all duration-500 delay-500",
|
||||
isMobileMenuOpen ? "translate-y-0 opacity-100" : "translate-y-10 opacity-0"
|
||||
)}>
|
||||
<div className="flex items-center space-x-8 text-xl font-extrabold tracking-widest uppercase text-white">
|
||||
<Link
|
||||
href={getPathForLocale('en')}
|
||||
className={`hover:text-accent transition-colors ${currentLocale === 'en' ? 'text-accent' : 'opacity-60'}`}
|
||||
>
|
||||
EN
|
||||
</Link>
|
||||
<div className="w-px h-6 bg-white/20" />
|
||||
<Link
|
||||
href={getPathForLocale('de')}
|
||||
className={`hover:text-accent transition-colors ${currentLocale === 'de' ? 'text-accent' : 'opacity-60'}`}
|
||||
>
|
||||
DE
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
href={`/${currentLocale}/contact`}
|
||||
variant="accent"
|
||||
size="lg"
|
||||
className="w-full max-w-xs py-6 text-xl shadow-2xl"
|
||||
>
|
||||
{t('contact')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bottom Branding */}
|
||||
<div className="p-12 flex justify-center opacity-20">
|
||||
<Image src="/logo-white.svg" alt="KLZ" width={80} height={80} unoptimized />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
{/* Removed spacer div that caused white gap */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
49
components/blog/ShareButton.tsx
Normal file
49
components/blog/ShareButton.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Button } from '@/components/ui';
|
||||
|
||||
interface ShareButtonProps {
|
||||
title: string;
|
||||
text: string;
|
||||
url: string;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
export default function ShareButton({ title, text, url, locale }: ShareButtonProps) {
|
||||
const handleShare = async () => {
|
||||
if (navigator.share) {
|
||||
try {
|
||||
await navigator.share({
|
||||
title,
|
||||
text,
|
||||
url,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error sharing:', error);
|
||||
}
|
||||
} else {
|
||||
// Fallback to copy link
|
||||
try {
|
||||
await navigator.clipboard.writeText(url);
|
||||
alert(locale === 'de' ? 'Link kopiert!' : 'Link copied!');
|
||||
} catch (error) {
|
||||
console.error('Error copying link:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Button
|
||||
onClick={handleShare}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="flex items-center gap-2 rounded-full px-6"
|
||||
>
|
||||
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 100 5.368 3 3 0 000-5.368z" />
|
||||
</svg>
|
||||
{locale === 'de' ? 'Teilen' : 'Share'}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import React from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Scribble from '@/components/Scribble';
|
||||
import { Section } from '../../components/ui';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
export default function VideoSection() {
|
||||
const t = useTranslations('Home.video');
|
||||
@@ -29,11 +27,6 @@ export default function VideoSection() {
|
||||
)
|
||||
})}
|
||||
</h2>
|
||||
<div className="mt-12 flex justify-center">
|
||||
<div className="w-24 h-24 rounded-full border-2 border-white/30 flex items-center justify-center group cursor-pointer hover:bg-white transition-all duration-500">
|
||||
<div className="w-0 h-0 border-t-[12px] border-t-transparent border-l-[20px] border-l-white border-b-[12px] border-b-transparent ml-2 group-hover:border-l-primary-dark transition-colors" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export default function ProductsIllustration() {
|
||||
return (
|
||||
<div className="absolute inset-0 z-0 overflow-hidden pointer-events-none bg-primary">
|
||||
<svg
|
||||
viewBox="0 0 1000 500"
|
||||
className="w-full h-full"
|
||||
preserveAspectRatio="xMidYMid slice"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id="scan-beam" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" stopColor="#82ed20" stopOpacity="0" />
|
||||
<stop offset="50%" stopColor="#82ed20" stopOpacity="0.5" />
|
||||
<stop offset="100%" stopColor="#82ed20" stopOpacity="0" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
{/* 3D Cable Wireframe Construction */}
|
||||
<g transform="translate(100, 250) rotate(-10)">
|
||||
|
||||
{/* Inner Core Strands (Twisted) */}
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<path
|
||||
key={`strand-${i}`}
|
||||
d={`M 0 ${i*10 - 20} Q 400 ${i*10 - 60} 800 ${i*10 - 20}`}
|
||||
stroke="white"
|
||||
strokeWidth="2"
|
||||
strokeOpacity="0.8"
|
||||
fill="none"
|
||||
>
|
||||
<animate attributeName="d"
|
||||
values={`M 0 ${i*10 - 20} Q 400 ${i*10 - 60} 800 ${i*10 - 20};
|
||||
M 0 ${i*10 - 20} Q 400 ${i*10 + 20} 800 ${i*10 - 20};
|
||||
M 0 ${i*10 - 20} Q 400 ${i*10 - 60} 800 ${i*10 - 20}`}
|
||||
dur="4s"
|
||||
repeatCount="indefinite"
|
||||
/>
|
||||
</path>
|
||||
))}
|
||||
|
||||
{/* Insulation Layers (Ellipses along the path) */}
|
||||
{[...Array(8)].map((_, i) => (
|
||||
<ellipse
|
||||
key={`ring-${i}`}
|
||||
cx={100 + i * 100}
|
||||
cy="0"
|
||||
rx="40"
|
||||
ry="80"
|
||||
stroke="white"
|
||||
strokeWidth="1"
|
||||
strokeOpacity="0.2"
|
||||
fill="none"
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Outer Sheath (Top and Bottom Lines) */}
|
||||
<path d="M 0 -80 L 800 -80" stroke="white" strokeWidth="1" strokeOpacity="0.3" strokeDasharray="10 5" />
|
||||
<path d="M 0 80 L 800 80" stroke="white" strokeWidth="1" strokeOpacity="0.3" strokeDasharray="10 5" />
|
||||
|
||||
{/* Scanning Ring (Animated) */}
|
||||
<g>
|
||||
<ellipse cx="0" cy="0" rx="50" ry="90" stroke="#82ed20" strokeWidth="2" strokeOpacity="0.8" fill="none">
|
||||
<animate attributeName="cx" from="0" to="800" dur="3s" repeatCount="indefinite" />
|
||||
<animate attributeName="rx" values="50;45;50" dur="0.5s" repeatCount="indefinite" />
|
||||
</ellipse>
|
||||
{/* Scan Beam */}
|
||||
<rect x="-50" y="-100" width="100" height="200" fill="url(#scan-beam)" opacity="0.3">
|
||||
<animate attributeName="x" from="-50" to="750" dur="3s" repeatCount="indefinite" />
|
||||
</rect>
|
||||
</g>
|
||||
</g>
|
||||
|
||||
{/* Floating Data/Tech Elements */}
|
||||
<g transform="translate(0, 0)">
|
||||
{[...Array(20)].map((_, i) => (
|
||||
<rect
|
||||
key={`bit-${i}`}
|
||||
x={Math.random() * 1000}
|
||||
y={Math.random() * 500}
|
||||
width={Math.random() * 20 + 5}
|
||||
height="2"
|
||||
fill="white"
|
||||
fillOpacity="0.3"
|
||||
>
|
||||
<animate attributeName="opacity" values="0;0.5;0" dur={`${Math.random() * 2 + 1}s`} repeatCount="indefinite" />
|
||||
<animate attributeName="width" values="5;30;5" dur={`${Math.random() * 2 + 1}s`} repeatCount="indefinite" />
|
||||
</rect>
|
||||
))}
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-primary/80 via-transparent to-primary/80" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user