Refactor sticky nav hook/components
This commit is contained in:
parent
c959e88ebb
commit
ffde3cedaf
@ -36,9 +36,8 @@ export default function Nav({
|
||||
const showNav = !isPathSignIn(pathname);
|
||||
|
||||
const {
|
||||
isNavSticky,
|
||||
shouldHideStickyNav,
|
||||
shouldAnimateStickyNav,
|
||||
classNameStickyContainer,
|
||||
classNameStickyNav,
|
||||
} = useStickyNav(ref);
|
||||
|
||||
const renderLink = (
|
||||
@ -63,9 +62,7 @@ export default function Nav({
|
||||
|
||||
return (
|
||||
<AppGrid
|
||||
className={clsx(
|
||||
isNavSticky && 'sticky top-0 z-10 pointer-events-none',
|
||||
)}
|
||||
className={classNameStickyContainer}
|
||||
classNameMain='pointer-events-auto'
|
||||
contentMain={
|
||||
<AnimateItems
|
||||
@ -77,15 +74,11 @@ export default function Nav({
|
||||
key="nav"
|
||||
ref={ref}
|
||||
className={clsx(
|
||||
'w-full',
|
||||
'w-full flex items-center bg-main',
|
||||
NAV_HEIGHT_CLASS,
|
||||
// Enlarge nav to ensure it fully masks underlying content
|
||||
'md:w-[calc(100%+8px)] md:translate-x-[-4px] md:px-[4px]',
|
||||
'flex items-center bg-main',
|
||||
shouldAnimateStickyNav && 'transition-transform duration-200',
|
||||
shouldHideStickyNav
|
||||
? 'translate-y-[-100%]'
|
||||
: 'translate-y-0',
|
||||
NAV_HEIGHT_CLASS,
|
||||
classNameStickyNav,
|
||||
)}>
|
||||
<ViewSwitcher
|
||||
currentSelection={switcherSelectionForPath()}
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
import useScrollDirection from '@/utility/useScrollDirection';
|
||||
import { RefObject } from 'react';
|
||||
import clsx from 'clsx/lite';
|
||||
import { RefObject, useMemo } from 'react';
|
||||
|
||||
export default function useStickyNav(
|
||||
ref: RefObject<HTMLElement | null>,
|
||||
isEnabled = true,
|
||||
) {
|
||||
const { scrollDirection, lastScrollY } = useScrollDirection();
|
||||
const { scrollDirection, scrollY } = useScrollDirection();
|
||||
|
||||
const navHeight = ref.current?.clientHeight ?? 0;
|
||||
|
||||
const hasScrolledPastNav = lastScrollY > navHeight;
|
||||
const hasScrolledPastNav = scrollY > navHeight;
|
||||
|
||||
const isNavSticky = isEnabled && (
|
||||
hasScrolledPastNav ||
|
||||
@ -21,13 +22,20 @@ export default function useStickyNav(
|
||||
scrollDirection === 'down';
|
||||
|
||||
const shouldAnimateStickyNav =
|
||||
isNavSticky &&
|
||||
lastScrollY > navHeight * 2 ||
|
||||
scrollDirection === 'up';
|
||||
isNavSticky && (
|
||||
scrollY > navHeight * 2 ||
|
||||
scrollDirection === 'up'
|
||||
);
|
||||
|
||||
return {
|
||||
isNavSticky,
|
||||
shouldHideStickyNav,
|
||||
shouldAnimateStickyNav,
|
||||
};
|
||||
const classNames = useMemo(() => ({
|
||||
classNameStickyContainer: clsx(
|
||||
isNavSticky && 'sticky top-0 z-10 pointer-events-none',
|
||||
),
|
||||
classNameStickyNav: clsx(
|
||||
shouldHideStickyNav ? 'translate-y-[-100%]' : 'translate-y-0',
|
||||
shouldAnimateStickyNav && 'transition-transform duration-200',
|
||||
),
|
||||
}), [isNavSticky, shouldAnimateStickyNav, shouldHideStickyNav]);
|
||||
|
||||
return classNames;
|
||||
};
|
||||
|
||||
@ -1,26 +1,28 @@
|
||||
import { useEffect, useState, useRef } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function useScrollDirection() {
|
||||
const [scrollDirection, setScrollDirection] = useState<'up' | 'down'>('down');
|
||||
|
||||
const lastScrollY = useRef(0);
|
||||
const [scrollInfo, setScrollInfo] = useState({
|
||||
scrollDirection: 'down' as 'up' | 'down',
|
||||
scrollY: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = () => {
|
||||
const pageHeight =
|
||||
document.documentElement.scrollHeight - window.innerHeight;
|
||||
setScrollDirection((
|
||||
window.scrollY >= lastScrollY.current ||
|
||||
lastScrollY.current > pageHeight
|
||||
) ? 'down' : 'up');
|
||||
lastScrollY.current = window.scrollY;
|
||||
const pageHeight = (
|
||||
document.documentElement.scrollHeight -
|
||||
window.innerHeight
|
||||
);
|
||||
setScrollInfo(prev => ({
|
||||
scrollDirection: (
|
||||
window.scrollY >= prev.scrollY ||
|
||||
prev.scrollY > pageHeight
|
||||
) ? 'down' : 'up',
|
||||
scrollY: window.scrollY,
|
||||
}));
|
||||
};
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
return () => window.removeEventListener('scroll', handleScroll);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
scrollDirection,
|
||||
lastScrollY: lastScrollY.current,
|
||||
};
|
||||
return scrollInfo;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user