feat: initialize reactjs project using vite
This commit is contained in:
90
src/components/layout/Navbar.tsx
Normal file
90
src/components/layout/Navbar.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { motion } from 'motion/react';
|
||||
import { useTranslation } from '../../i18n';
|
||||
import styles from './Navbar.module.css';
|
||||
|
||||
export function Navbar() {
|
||||
const { t, language, setLanguage } = useTranslation();
|
||||
const location = useLocation();
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
setIsScrolled(window.scrollY > 20);
|
||||
};
|
||||
window.addEventListener('scroll', handleScroll, { passive: true });
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setIsMobileMenuOpen(false);
|
||||
}, [location.pathname]);
|
||||
|
||||
const navLinks = [
|
||||
{ path: '/', label: t.nav.home },
|
||||
{ path: '/about', label: t.nav.about },
|
||||
{ path: '/contact', label: t.nav.contact },
|
||||
];
|
||||
|
||||
const toggleLanguage = () => {
|
||||
setLanguage(language === 'de' ? 'en' : 'de');
|
||||
};
|
||||
|
||||
return (
|
||||
<motion.header
|
||||
className={`${styles.header} ${isScrolled ? styles.scrolled : ''}`}
|
||||
initial={{ y: -100 }}
|
||||
animate={{ y: 0 }}
|
||||
transition={{ duration: 0.5, ease: 'easeOut' }}
|
||||
>
|
||||
<nav className={`${styles.nav} container`}>
|
||||
<Link to="/" className={styles.logo}>
|
||||
<span className={styles.logoText}>Ragusa</span>
|
||||
<span className={styles.logoAccent}>IT</span>
|
||||
</Link>
|
||||
|
||||
<div className={`${styles.navLinks} ${isMobileMenuOpen ? styles.open : ''}`}>
|
||||
{navLinks.map((link) => (
|
||||
<Link
|
||||
key={link.path}
|
||||
to={link.path}
|
||||
className={`${styles.navLink} ${location.pathname === link.path ? styles.active : ''}`}
|
||||
>
|
||||
{link.label}
|
||||
{location.pathname === link.path && (
|
||||
<motion.div
|
||||
className={styles.activeIndicator}
|
||||
layoutId="activeNav"
|
||||
transition={{ type: 'spring', stiffness: 380, damping: 30 }}
|
||||
/>
|
||||
)}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className={styles.actions}>
|
||||
<button
|
||||
onClick={toggleLanguage}
|
||||
className={styles.langToggle}
|
||||
aria-label={`Switch to ${language === 'de' ? 'English' : 'German'}`}
|
||||
>
|
||||
<span className={language === 'de' ? styles.activeLang : ''}>DE</span>
|
||||
<span className={styles.langDivider}>/</span>
|
||||
<span className={language === 'en' ? styles.activeLang : ''}>EN</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
className={styles.mobileMenuBtn}
|
||||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||||
aria-label="Toggle menu"
|
||||
aria-expanded={isMobileMenuOpen}
|
||||
>
|
||||
<span className={`${styles.hamburger} ${isMobileMenuOpen ? styles.open : ''}`} />
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
</motion.header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user