161 lines
4.6 KiB
TypeScript
161 lines
4.6 KiB
TypeScript
import React, { useEffect } from 'react';
|
|
import { Logo } from './navbar/Logo';
|
|
import { useTranslation } from '@/lib/hooks/useTranslation';
|
|
import { URLS } from '@/lib/config/constants';
|
|
import { cn, createNavClickHandler } from '@/lib/utils';
|
|
import { DiscordLogo } from '@/components/ui/DiscordLogo';
|
|
import type { Translation } from '@/types/i18n';
|
|
|
|
interface MobileMenuProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
translations: Translation['navigation'];
|
|
}
|
|
|
|
interface MobileNavItemProps {
|
|
title: string;
|
|
href: string;
|
|
isExternal?: boolean;
|
|
onClick?: () => void;
|
|
isDiscord?: boolean;
|
|
}
|
|
|
|
const MobileNavItem: React.FC<MobileNavItemProps> = ({
|
|
title,
|
|
href,
|
|
isExternal = false,
|
|
onClick,
|
|
isDiscord = false
|
|
}) => {
|
|
const handleClick = (e: React.MouseEvent) => {
|
|
if (onClick) {
|
|
e.preventDefault();
|
|
onClick();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<a
|
|
href={href}
|
|
onClick={handleClick}
|
|
className={cn(
|
|
'flex items-center justify-between px-4 py-3 rounded-lg',
|
|
'text-white hover:bg-white/10 transition-colors duration-200',
|
|
'border-b border-white/10 last:border-b-0'
|
|
)}
|
|
target={isExternal ? '_blank' : undefined}
|
|
rel={isExternal ? 'noopener noreferrer' : undefined}
|
|
>
|
|
<div className="flex items-center space-x-3">
|
|
{isDiscord && <DiscordLogo size="sm" className="text-[#5865F2]" />}
|
|
<span className="font-medium">{title}</span>
|
|
</div>
|
|
{isExternal && (
|
|
<svg className="w-4 h-4 text-white/60" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
|
</svg>
|
|
)}
|
|
</a>
|
|
);
|
|
};
|
|
|
|
export const MobileMenu: React.FC<MobileMenuProps> = ({ isOpen, onClose, translations }) => {
|
|
const { t } = useTranslation();
|
|
|
|
// Gérer le scroll du body
|
|
useEffect(() => {
|
|
if (isOpen) {
|
|
document.body.style.overflow = 'hidden';
|
|
} else {
|
|
document.body.style.overflow = 'unset';
|
|
}
|
|
|
|
return () => {
|
|
document.body.style.overflow = 'unset';
|
|
};
|
|
}, [isOpen]);
|
|
|
|
// Gestionnaire de navigation
|
|
const handleNavClick = createNavClickHandler(onClose);
|
|
|
|
return (
|
|
<div className={cn(
|
|
'md:hidden fixed inset-0 z-[100] transition-opacity duration-300',
|
|
isOpen ? 'visible opacity-100' : 'invisible opacity-0'
|
|
)}>
|
|
{/* Overlay simple */}
|
|
<div
|
|
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
|
|
onClick={onClose}
|
|
/>
|
|
|
|
{/* Menu Panel épuré */}
|
|
<div className={cn(
|
|
'absolute top-0 right-0 h-full w-72 max-w-[85vw]',
|
|
'bg-blue-900/95 backdrop-blur-lg shadow-xl',
|
|
'border-l border-white/10',
|
|
'transition-transform duration-300 ease-out',
|
|
isOpen ? 'translate-x-0' : 'translate-x-full'
|
|
)}>
|
|
|
|
{/* Header simple */}
|
|
<div className="flex items-center justify-between p-4 border-b border-white/10">
|
|
<Logo scrolled={false} />
|
|
<button
|
|
className="p-2 rounded-lg hover:bg-white/10 transition-colors"
|
|
onClick={onClose}
|
|
aria-label="Fermer le menu"
|
|
>
|
|
<svg className="w-5 h-5 text-white" 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 simple */}
|
|
<div className="p-4 space-y-2">
|
|
<MobileNavItem
|
|
title={translations.home}
|
|
href="#home"
|
|
onClick={() => handleNavClick('home')}
|
|
/>
|
|
|
|
<MobileNavItem
|
|
title={translations.services}
|
|
href="#services"
|
|
onClick={() => handleNavClick('services')}
|
|
/>
|
|
|
|
<MobileNavItem
|
|
title={translations.about}
|
|
href="#about"
|
|
onClick={() => handleNavClick('about')}
|
|
/>
|
|
|
|
<MobileNavItem
|
|
title={translations.contact}
|
|
href="mailto:contact@la-banquise.fr"
|
|
onClick={() => handleNavClick('contact')}
|
|
/>
|
|
|
|
{/* Séparateur simple */}
|
|
<div className="border-t border-white/10 my-4" />
|
|
|
|
<MobileNavItem
|
|
title="Discord"
|
|
href={URLS.social.discord}
|
|
isExternal={true}
|
|
isDiscord={true}
|
|
/>
|
|
|
|
<MobileNavItem
|
|
title="Se connecter"
|
|
href={URLS.services.auth}
|
|
isExternal={true}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|