Change the nav sticky behavior
All checks were successful
continuous-integration/drone/tag Build is passing

This commit is contained in:
Arnie 2024-10-24 14:35:43 +02:00
parent ea5fed1bf9
commit 0d74fd01bc
2 changed files with 25 additions and 64 deletions

View File

@ -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",

View File

@ -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 (
<div ref={ref}>
<StickyWrapper ref={ref}>
<TopSpacer />
<ProfileImg src={profile} alt="profile picture" />
<NavigationHeadline>
@ -177,7 +138,7 @@ const MainNavigation: React.FC = () => {
id: "Navigation.experience",
})}
</NavigationHeadline>
</div>
</StickyWrapper>
);
};