From 1843519bd2219675d6b2450bdea037e83d22ba31 Mon Sep 17 00:00:00 2001 From: Shan Usmani Date: Sat, 25 Jul 2026 12:19:13 +0530 Subject: [PATCH 1/2] feat(ui): add scroll-progress bar and normalize header typography - Add scroll-progress bar at header bottom edge (accent color + glow) - Track scroll position via CSS scaleX for GPU-friendly animation - Normalize letter-spacing to 0.08em across nav links, badge, and stat labels - Optical alignment of triangle logo mark with DEVTRACK wordmark - Respects prefers-reduced-motion via existing CSS media query Closes #3222 --- src/components/AppNavbar.tsx | 37 +++++++++++++++++++++++--- src/components/landing/LandingPage.tsx | 6 ++--- 2 files changed, 37 insertions(+), 6 deletions(-) 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 */} +