From 0d74fd01bc4c7852a800b4723387676aed3c640c Mon Sep 17 00:00:00 2001 From: Arnie Date: Thu, 24 Oct 2024 14:35:43 +0200 Subject: [PATCH] Change the nav sticky behavior --- .../src/components/Layout/MainLayout.tsx | 2 +- .../components/Navigation/MainNavigation.tsx | 87 +++++-------------- 2 files changed, 25 insertions(+), 64 deletions(-) diff --git a/app/frontend/src/components/Layout/MainLayout.tsx b/app/frontend/src/components/Layout/MainLayout.tsx index 2985184..73df744 100644 --- a/app/frontend/src/components/Layout/MainLayout.tsx +++ b/app/frontend/src/components/Layout/MainLayout.tsx @@ -23,7 +23,7 @@ const Nav = styled("nav")({ flex: "0 0 280px", width: 280, minHeight: "100%", - padding: "2rem 2rem 2rem", + padding: "0 2rem 2rem", [hideNavigationMQ]: { display: "none", diff --git a/app/frontend/src/components/Navigation/MainNavigation.tsx b/app/frontend/src/components/Navigation/MainNavigation.tsx index 2af78de..044d8e0 100644 --- a/app/frontend/src/components/Navigation/MainNavigation.tsx +++ b/app/frontend/src/components/Navigation/MainNavigation.tsx @@ -18,21 +18,15 @@ const ProfileImg = styled("img")({ width: 150, }); -const getTopOffset = (input: HTMLElement) => { - let el: HTMLElement | Element | null = input; - let o = 0; - do { - if (!(el instanceof HTMLElement)) { - break; - } +const navBottomPadding = 50; - if (!isNaN(el.offsetTop)) { - o += el.offsetTop; - } - } while ((el = el.offsetParent)); +const TopSpacer = styled("div")({ + height: 40, +}); - return o; -}; +const StickyWrapper = styled("div")({ + position: "sticky", +}); const MainNavigation: React.FC = () => { const intl = useIntl(); @@ -45,64 +39,30 @@ const MainNavigation: React.FC = () => { return; } + d.style.top = "0px"; + let { height } = d.getBoundingClientRect(); + const listener = () => { + const visibleArea = navBottomPadding + height; + if (window.innerHeight > visibleArea) { + d.style.top = "0px"; + } else { + d.style.top = `${window.innerHeight - visibleArea}px`; + } + }; + const ro = new ResizeObserver((entries) => { if (entries[0]) { height = entries[0].contentRect.height; + listener(); } }); ro.observe(d); - let scrollPrev = window.scrollY; - - const listener = () => { - const down = scrollPrev < window.scrollY; - scrollPrev = window.scrollY; - const top = getTopOffset(d); - - console.log({ - "window.innerHeight": window.innerHeight, - height, - top, - down, - }); - - if (window.innerHeight > height) { - d.style.marginTop = `${Math.max(window.scrollY, 0)}px`; - return; - } - - if (down) { - const delta = top + height; - const wDelta = window.scrollY + window.innerHeight; - - const diff = wDelta - delta; - console.log({ delta, wDelta, "window.scrollY": window.scrollY, diff }); - - if (diff > 0) { - const sizeDelta = Math.min(window.innerHeight - height, 0); - d.style.marginTop = `${Math.max(top + diff + sizeDelta, 0)}px`; - console.log({ - sizeDelta, - marginTop: Math.max(top + diff + sizeDelta, 0), - }); - } - } else { - const delta = top; - const wDelta = window.scrollY; - - const diff = wDelta - delta; - console.log({ delta, wDelta, "window.scrollY": window.scrollY, diff }); - if (diff < 0) { - console.log({ marginTop: Math.max(top + diff, 0) }); - d.style.marginTop = `${Math.max(top + diff, 0)}px`; - } - } - }; - - window.addEventListener("scroll", listener); + window.addEventListener("scroll", listener, { passive: true }); + window.addEventListener("resize", listener, { passive: true }); return () => { window.removeEventListener("scroll", listener); @@ -111,7 +71,8 @@ const MainNavigation: React.FC = () => { }, []); return ( -
+ + @@ -177,7 +138,7 @@ const MainNavigation: React.FC = () => { id: "Navigation.experience", })} -
+ ); };