diff --git a/src/components/AppNavbar.tsx b/src/components/AppNavbar.tsx index 24d38a914..68b5415b8 100644 --- a/src/components/AppNavbar.tsx +++ b/src/components/AppNavbar.tsx @@ -31,6 +31,8 @@ export default function AppNavbar() { const { data: session, status } = useSession(); const [mobileOpen, setMobileOpen] = useState(false); const [scrolled, setScrolled] = useState(false); + const [scrollProgress, setScrollProgress] = useState(0); + const [prefersReducedMotion, setPrefersReducedMotion] = useState(false); const handleAnchorClick = (e: React.MouseEvent, href: string) => { const hashIndex = href.indexOf("#"); @@ -46,7 +48,20 @@ export default function AppNavbar() { useEffect(() => { setMobileOpen(false); }, [pathname]); useEffect(() => { - const fn = () => setScrolled(window.scrollY > 20); + const mql = window.matchMedia("(prefers-reduced-motion: reduce)"); + setPrefersReducedMotion(mql.matches); + const handler = (e: MediaQueryListEvent) => setPrefersReducedMotion(e.matches); + mql.addEventListener("change", handler); + return () => mql.removeEventListener("change", handler); + }, []); + + useEffect(() => { + const fn = () => { + setScrolled(window.scrollY > 20); + const scrollTop = window.scrollY; + const docHeight = document.documentElement.scrollHeight - window.innerHeight; + setScrollProgress(docHeight > 0 ? Math.min(scrollTop / docHeight, 1) : 0); + }; fn(); window.addEventListener("scroll", fn, { passive: true }); return () => window.removeEventListener("scroll", fn); @@ -90,6 +105,22 @@ export default function AppNavbar() { return (
+ {/* Scroll-progress bar */} +