fix: activeIndicator placement and animation

This commit is contained in:
Melvin Ragusa
2026-01-21 23:33:43 +01:00
parent 1b91cf53db
commit f2250ab65e
2 changed files with 49 additions and 17 deletions

View File

@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react';
import { useState, useEffect, useRef } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { motion } from 'motion/react';
import { useTranslation } from '../../i18n';
@@ -9,6 +9,18 @@ export function Navbar() {
const location = useLocation();
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [indicatorX, setIndicatorX] = useState(0);
const navLinksRef = useRef<HTMLDivElement>(null);
const linkRefs = useRef<(HTMLAnchorElement | null)[]>([]);
const navLinks = [
{ path: '/', label: t.nav.home },
{ path: '/about', label: t.nav.about },
{ path: '/contact', label: t.nav.contact },
];
// Find active index
const activeIndex = navLinks.findIndex((link) => link.path === location.pathname);
useEffect(() => {
const handleScroll = () => {
@@ -22,11 +34,25 @@ export function Navbar() {
setIsMobileMenuOpen(false);
}, [location.pathname]);
const navLinks = [
{ path: '/', label: t.nav.home },
{ path: '/about', label: t.nav.about },
{ path: '/contact', label: t.nav.contact },
];
// Calculate indicator position
useEffect(() => {
const updateIndicatorPosition = () => {
const activeLink = linkRefs.current[activeIndex];
const container = navLinksRef.current;
if (activeLink && container) {
const containerRect = container.getBoundingClientRect();
const linkRect = activeLink.getBoundingClientRect();
// Calculate center of the link relative to the container
const centerX = linkRect.left - containerRect.left + linkRect.width / 2;
setIndicatorX(centerX);
}
};
updateIndicatorPosition();
window.addEventListener('resize', updateIndicatorPosition);
return () => window.removeEventListener('resize', updateIndicatorPosition);
}, [activeIndex, language]); // Recalculate when active link or language changes
const toggleLanguage = () => {
setLanguage(language === 'de' ? 'en' : 'de');
@@ -45,23 +71,27 @@ export function Navbar() {
<span className={styles.logoAccent}>IT</span>
</Link>
<div className={`${styles.navLinks} ${isMobileMenuOpen ? styles.open : ''}`}>
{navLinks.map((link) => (
<div
ref={navLinksRef}
className={`${styles.navLinks} ${isMobileMenuOpen ? styles.open : ''}`}
>
{navLinks.map((link, index) => (
<Link
key={link.path}
ref={(el) => { linkRefs.current[index] = el; }}
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>
))}
{activeIndex !== -1 && (
<motion.div
className={styles.activeIndicator}
animate={{ x: indicatorX }}
transition={{ type: 'spring', stiffness: 380, damping: 30 }}
/>
)}
</div>
<div className={styles.actions}>