2025-09-08 18:20:15 +02:00

160 lines
8.9 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import { MobileMenu } from './MobileMenu';
import banquiseServer from '/src/assets/banquise_server.svg'
import { URLS, SITE_CONFIG } from '../../config/constants';
import { commonStyles } from '../../styles/components';
import type { Translation } from '../../types/i18n';
interface NavigationProps {
translations: Translation['navigation'];
languageSwitcher: React.ReactElement;
}
export const Navigation: React.FC<NavigationProps> = ({ translations, languageSwitcher }) => {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const [scrolled, setScrolled] = useState(false);
useEffect(() => {
const handleScroll = () => {
const isScrolled = window.scrollY > 20;
setScrolled(isScrolled);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= 768) {
setMobileMenuOpen(false);
}
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<>
<nav className={`fixed top-0 left-0 right-0 z-50 transition-all duration-300 ${
scrolled
? 'bg-banquise-blue-dark/98 backdrop-blur-xl shadow-2xl border-b border-banquise-blue-lightest/30'
: 'bg-banquise-blue-dark/95 backdrop-blur-lg shadow-xl border-b border-banquise-blue-lightest/20'
}`}>
<div className={commonStyles.layout.container}>
<div className="flex justify-between items-center h-16 sm:h-18 lg:h-20 px-4 sm:px-6 lg:px-8">
{/* Logo section */}
<div className="flex items-center space-x-3 sm:space-x-4 group">
<div className="relative">
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-full blur-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
<img
src={banquiseServer}
alt="Logo La Banquise"
className="h-10 sm:h-12 lg:h-14 w-auto relative z-10 transition-transform duration-300 group-hover:scale-110"
style={{ filter: 'drop-shadow(0 0 12px rgba(168, 218, 255, 0.4))' }}
/>
</div>
<div className="hidden sm:block">
<h1 className={`text-xl sm:text-2xl lg:text-3xl font-bold text-white tracking-wide ${commonStyles.text.heading}`}>
{SITE_CONFIG.name}
</h1>
<p className="text-banquise-blue-lightest/80 text-xs lg:text-sm font-medium">
{SITE_CONFIG.tagline}
</p>
</div>
</div>
{/* Navigation links desktop */}
<div className="hidden md:flex items-center space-x-1 lg:space-x-2">
<a href="#home" className={commonStyles.nav.link}>
<span className="relative z-10">{translations.home}</span>
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
</a>
<a href="#services" className={commonStyles.nav.link}>
<span className="relative z-10">{translations.services}</span>
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
</a>
<a href="#about" className={commonStyles.nav.link}>
<span className="relative z-10">{translations.about}</span>
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
</a>
<a href="#contact" className={commonStyles.nav.link}>
<span className="relative z-10">{translations.contact}</span>
<div className="absolute inset-0 bg-gradient-to-r from-banquise-blue-light/20 to-banquise-blue/20 rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
</a>
</div>
{/* Action buttons desktop */}
<div className="hidden md:flex items-center space-x-3 lg:space-x-4">
{/* Language switcher */}
{languageSwitcher}
<a
href={URLS.social.discord}
target="_blank"
rel="noopener noreferrer"
className={`${commonStyles.buttons.discord} ${commonStyles.gradients.discord}`}
>
<div className={`absolute inset-0 ${commonStyles.gradients.discordHover} opacity-0 group-hover:opacity-100 transition-opacity duration-300`}></div>
<div className="relative z-10 flex items-center space-x-2">
<svg className="w-4 h-4 lg:w-5 lg:h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.211.375-.445.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/>
</svg>
<span>Discord</span>
</div>
</a>
<a
href={URLS.services.auth}
target="_blank"
rel="noopener noreferrer"
className={`${commonStyles.buttons.auth} ${
scrolled
? `${commonStyles.gradients.primary} border border-banquise-blue-lightest/30 hover:shadow-banquise-blue/25`
: 'bg-gradient-to-r from-banquise-blue-light to-banquise-blue border-2 border-white/20 hover:shadow-banquise-blue-light/25'
}`}
>
<div className={`absolute inset-0 transition-opacity duration-300 opacity-0 group-hover:opacity-100 ${
scrolled
? 'bg-gradient-to-r from-banquise-blue-light to-banquise-blue'
: 'bg-gradient-to-r from-white/10 to-banquise-blue-lightest/20'
}`}></div>
<div className="relative z-10 flex items-center space-x-2">
<svg className="w-4 h-4 lg:w-5 lg:h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
<span className="hidden lg:inline">Connexion</span>
</div>
</a>
</div>
{/* Mobile menu button */}
<button
className="md:hidden relative p-3 rounded-xl bg-white/10 hover:bg-white/20 transition-all duration-300 hover:scale-105 active:scale-95 group"
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
aria-label={mobileMenuOpen ? "Fermer le menu" : "Ouvrir le menu"}
aria-expanded={mobileMenuOpen}
>
<div className="w-6 h-6 relative">
<span className={`absolute block w-6 h-6 bg-white transition-all duration-300 ${mobileMenuOpen ? 'rotate-45 top-3' : 'top-1'}`}></span>
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 top-3 ${mobileMenuOpen ? 'opacity-0 scale-0' : 'opacity-100'}`}></span>
<span className={`absolute block w-6 h-0.5 bg-white transition-all duration-300 ${mobileMenuOpen ? '-rotate-45 top-3' : 'top-5'}`}></span>
</div>
</button>
</div>
</div>
{/* Glassmorphism effect bar */}
<div className="absolute bottom-0 left-0 right-0 h-px bg-gradient-to-r from-transparent via-banquise-blue-lightest/30 to-transparent"></div>
</nav>
{/* Spacer pour compenser la navbar fixed */}
<div className="h-16 sm:h-18 lg:h-20"></div>
{/* Menu mobile */}
<MobileMenu
isOpen={mobileMenuOpen}
onClose={() => setMobileMenuOpen(false)}
translations={translations}
/>
</>
);
};