From f551ff9f59d2227a3e89dfe303280425b1ecea98 Mon Sep 17 00:00:00 2001 From: Matheo Guilbert Date: Fri, 17 Apr 2026 09:00:20 +0200 Subject: [PATCH] fixing headers anchor links --- components/layout/Header.tsx | 249 +++++++++++++++++++---------------- 1 file changed, 134 insertions(+), 115 deletions(-) diff --git a/components/layout/Header.tsx b/components/layout/Header.tsx index ecc7671..1087043 100644 --- a/components/layout/Header.tsx +++ b/components/layout/Header.tsx @@ -1,133 +1,152 @@ -'use client'; +"use client"; -import Link from 'next/link'; -import React, { useState, useEffect, MouseEvent } from 'react'; +import Link from "next/link"; +import React, { useState, useEffect, MouseEvent } from "react"; +import { useParams, usePathname } from "next/navigation"; import { CiMenuFries } from "react-icons/ci"; import { IoCloseOutline } from "react-icons/io5"; export default function Header() { + const params = useParams<{ locale?: string }>(); + const pathname = usePathname(); + const locale = params?.locale ?? "fr"; + const homePath = `/${locale}`; - const links = [ - { "text": "Accueil", "target": "/" }, - { "text": "Travaux", "target": "/#works" }, - { "text": "À propos", "target": "/#about" }, - { "text": "Blog", "target": "/blog" }, - ]; + const links = [ + { text: "Accueil", target: homePath }, + { text: "Travaux", target: `${homePath}#works` }, + { text: "A propos", target: `${homePath}#about` }, + { text: "Blog", target: `${homePath}/blog` }, + ]; - const [isOpen, setIsOpen] = useState(false); - const [showText, setShowText] = useState(false); + const [isOpen, setIsOpen] = useState(false); + const [showText, setShowText] = useState(false); - const handleAnchorClick = (e: MouseEvent, target: string) => { - if (target.startsWith("/#")) { // only anchor links - e.preventDefault(); - const id = target.slice(2); - const element = document.getElementById(id); - if (element) { - element.scrollIntoView({ behavior: "smooth" }); - } - } - setIsOpen(false); - }; + const scrollToSection = (id: string) => { + const element = document.getElementById(id); + if (!element) return false; - useEffect(() => { - if (isOpen) { - const timer = setTimeout(() => setShowText(true), 450); - return () => clearTimeout(timer); - } else { - setShowText(false); - } - }, [isOpen]); + element.scrollIntoView({ behavior: "smooth" }); + return true; + }; - return ( -
-
- -
M. Guilbert
- logo mg dev - + const handleAnchorClick = (e: MouseEvent, target: string) => { + const isAnchor = target.includes("#"); + const isOnHome = pathname === homePath || pathname === `${homePath}/`; - {/* Desktop */} - -
France
+ if (isAnchor && isOnHome) { + e.preventDefault(); + const sectionId = target.split("#")[1]; + scrollToSection(sectionId); + } - {/* Mobile */} - -
+ setIsOpen(false); + }; - {/* Overlay mobile menu */} -
- {/* wave / circle that fills the screen */} -
+ useEffect(() => { + const hash = window.location.hash.replace("#", ""); + if (!hash) return; - {/* content */} -
- - {/* top bar */} -
-
- M. Guilbert -
+ if (scrollToSection(hash)) return; - -
+ const timer = window.setTimeout(() => { + scrollToSection(hash); + }, 120); - {/* liens */} - + return () => window.clearTimeout(timer); + }, [pathname]); - {/* footer */} -
- France -
-
-
-
+ useEffect(() => { + if (isOpen) { + const timer = setTimeout(() => setShowText(true), 450); + return () => clearTimeout(timer); + } - ); -} \ No newline at end of file + setShowText(false); + }, [isOpen]); + + return ( +
+
+ +
M. Guilbert
+ logo mg dev + + + +
France
+ + +
+ +
+
+ +
+
+
+ M. Guilbert +
+ + +
+ + + +
+ France +
+
+
+
+ ); +}