JavaScript 56.7%
TypeScript 42.6%
1"use client";23import { useEffect, useState, useRef } from "react";4import { usePathname } from "next/navigation";56/** Barre de progression de navigation (2 px, dégradé d'accent + lueur). */7export default function TopLoader() {8 const pathname = usePathname();9 const [loading, setLoading] = useState(false);10 const [progress, setProgress] = useState(0);11 const [visible, setVisible] = useState(false);12 const prevPathname = useRef(pathname);13 const timers = useRef<ReturnType<typeof setTimeout>[]>([]);1415 useEffect(() => {16 if (pathname === prevPathname.current) return;17 prevPathname.current = pathname;1819 timers.current.forEach(clearTimeout);20 timers.current = [];21 const t = (fn: () => void, ms: number) => timers.current.push(setTimeout(fn, ms));2223 setLoading(true);24 setVisible(true);25 setProgress(0);26 t(() => setProgress(30), 40);27 t(() => setProgress(62), 180);28 t(() => setProgress(82), 380);29 t(() => {30 setProgress(100);31 t(() => {32 setLoading(false);33 t(() => { setVisible(false); setProgress(0); }, 220);34 }, 140);35 }, 520);3637 return () => { timers.current.forEach(clearTimeout); };38 }, [pathname]);3940 if (!visible) return null;4142 return (43 <div className="fixed top-0 left-0 right-0 z-[90] h-[2px] pointer-events-none" aria-hidden>44 <div45 className="h-full bg-accent-gradient transition-all ease-out shadow-[0_0_10px_rgb(var(--accent-500)/0.7),0_0_2px_rgb(var(--accent-400)/0.9)]"46 style={{47 width: `${progress}%`,48 transitionDuration: progress === 100 ? "140ms" : "480ms",49 opacity: loading ? 1 : 0,50 }}51 />52 </div>53 );54}55