238 lines
9.2 KiB
TypeScript
238 lines
9.2 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import Link from 'next/link';
|
|
import Image from 'next/image';
|
|
import { usePathname } from 'next/navigation';
|
|
import { Button } from '@/components/ui/Button';
|
|
import { LocaleSwitcher } from '@/components/LocaleSwitcher';
|
|
|
|
interface MobileMenuProps {
|
|
locale: string;
|
|
siteName: string;
|
|
logo?: string;
|
|
onClose?: () => void;
|
|
}
|
|
|
|
export function MobileMenu({ locale, siteName, logo, onClose }: MobileMenuProps) {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const pathname = usePathname();
|
|
|
|
// Main navigation menu
|
|
const mainMenu = [
|
|
{ title: 'Home', path: `/${locale}` },
|
|
{ title: 'Blog', path: `/${locale}/blog` },
|
|
{ title: 'Products', path: `/${locale}/products` },
|
|
{ title: 'Contact', path: `/${locale}/contact` }
|
|
];
|
|
|
|
// Product categories (could be dynamic from data)
|
|
const productCategories = [
|
|
{ title: 'Medium Voltage', path: `/${locale}/product-category/medium-voltage` },
|
|
{ title: 'Low Voltage', path: `/${locale}/product-category/low-voltage` },
|
|
{ title: 'Accessories', path: `/${locale}/product-category/accessories` }
|
|
];
|
|
|
|
// Close on route change
|
|
useEffect(() => {
|
|
setIsOpen(false);
|
|
if (onClose) onClose();
|
|
}, [pathname, onClose]);
|
|
|
|
const toggleMenu = () => {
|
|
setIsOpen(!isOpen);
|
|
if (!isOpen && onClose) onClose();
|
|
};
|
|
|
|
const closeMenu = () => {
|
|
setIsOpen(false);
|
|
if (onClose) onClose();
|
|
};
|
|
|
|
const isSvgLogo = logo?.endsWith('.svg');
|
|
|
|
return (
|
|
<>
|
|
{/* Mobile Toggle Button */}
|
|
<button
|
|
onClick={toggleMenu}
|
|
className="md:hidden p-3 rounded-lg hover:bg-gray-100 active:bg-gray-200 transition-colors touch-target-sm"
|
|
aria-label="Toggle mobile menu"
|
|
aria-expanded={isOpen}
|
|
>
|
|
<svg
|
|
className="w-6 h-6 text-gray-700"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
{isOpen ? (
|
|
<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>
|
|
|
|
{/* Mobile Menu Overlay */}
|
|
{isOpen && (
|
|
<div
|
|
className="fixed inset-0 bg-black bg-opacity-50 z-50 md:hidden"
|
|
onClick={closeMenu}
|
|
aria-hidden="true"
|
|
/>
|
|
)}
|
|
|
|
{/* Mobile Menu Drawer */}
|
|
<div
|
|
className={`fixed top-0 right-0 h-full w-full max-w-md bg-white shadow-2xl z-50 transform transition-transform duration-300 ease-in-out md:hidden safe-area-p ${
|
|
isOpen ? 'translate-x-0' : 'translate-x-full'
|
|
}`}
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-label="Mobile navigation menu"
|
|
>
|
|
<div className="flex flex-col h-full">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between p-4 border-b border-gray-200 safe-area-p">
|
|
<div className="flex items-center gap-3">
|
|
{logo ? (
|
|
<div className="w-10 h-10 flex items-center justify-center">
|
|
{isSvgLogo ? (
|
|
<img
|
|
src={logo}
|
|
alt={siteName}
|
|
className="w-full h-full object-contain"
|
|
/>
|
|
) : (
|
|
<div className="relative w-10 h-10">
|
|
<Image
|
|
src={logo}
|
|
alt={siteName}
|
|
fill
|
|
className="object-contain"
|
|
sizes="40px"
|
|
priority={false}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : (
|
|
<div className="w-10 h-10 bg-primary rounded-lg flex items-center justify-center shadow-sm">
|
|
<span className="text-white font-bold text-sm">KLZ</span>
|
|
</div>
|
|
)}
|
|
<span className="font-semibold text-gray-900 text-lg">{siteName}</span>
|
|
</div>
|
|
<button
|
|
onClick={closeMenu}
|
|
className="p-3 rounded-lg hover:bg-gray-100 active:bg-gray-200 transition-colors touch-target-sm"
|
|
aria-label="Close menu"
|
|
>
|
|
<svg className="w-6 h-6 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
{/* Navigation */}
|
|
<div className="flex-1 overflow-y-auto p-4">
|
|
{/* Main Navigation */}
|
|
<div className="mb-6">
|
|
<h3 className="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-3">
|
|
Navigation
|
|
</h3>
|
|
<nav className="space-y-1">
|
|
{mainMenu.map((item) => (
|
|
<Link
|
|
key={item.path}
|
|
href={item.path}
|
|
className="flex items-center justify-between px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-100 hover:text-primary active:bg-gray-200 transition-colors touch-target-md"
|
|
onClick={closeMenu}
|
|
>
|
|
<span className="font-medium text-base">{item.title}</span>
|
|
<svg className="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
</svg>
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
</div>
|
|
|
|
{/* Product Categories */}
|
|
<div className="mb-6">
|
|
<h3 className="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-3">
|
|
Product Categories
|
|
</h3>
|
|
<nav className="space-y-1">
|
|
{productCategories.map((item) => (
|
|
<Link
|
|
key={item.path}
|
|
href={item.path}
|
|
className="flex items-center justify-between px-4 py-3 rounded-lg text-gray-700 hover:bg-gray-100 hover:text-primary active:bg-gray-200 transition-colors touch-target-md"
|
|
onClick={closeMenu}
|
|
>
|
|
<span className="font-medium text-base">{item.title}</span>
|
|
<svg className="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
</svg>
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
</div>
|
|
|
|
{/* Language Switcher */}
|
|
<div className="mb-6">
|
|
<h3 className="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-3">
|
|
Language
|
|
</h3>
|
|
<div className="px-3">
|
|
<LocaleSwitcher />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Contact Information */}
|
|
<div className="mb-6">
|
|
<h3 className="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-3">
|
|
Contact
|
|
</h3>
|
|
<div className="space-y-2 px-4 text-sm text-gray-600">
|
|
<a
|
|
href="mailto:info@klz-cables.com"
|
|
className="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-gray-100 transition-colors touch-target-sm"
|
|
>
|
|
<svg className="w-5 h-5 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
|
</svg>
|
|
<span className="font-medium">info@klz-cables.com</span>
|
|
</a>
|
|
<a
|
|
href="tel:+490123456789"
|
|
className="flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-gray-100 transition-colors touch-target-sm"
|
|
>
|
|
<svg className="w-5 h-5 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
|
</svg>
|
|
<span className="font-medium">+49 (0) 123 456 789</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Footer CTA */}
|
|
<div className="p-4 border-t border-gray-200 bg-gray-50">
|
|
<Link href={`/${locale}/contact`} onClick={closeMenu} className="block w-full">
|
|
<Button
|
|
variant="primary"
|
|
size="md"
|
|
fullWidth
|
|
>
|
|
Get in Touch
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
} |