Make burger disappear when off screen

This commit is contained in:
William Tran 2021-07-05 13:02:04 -04:00
parent 5a3fdb9005
commit db88a7699c
1 changed files with 39 additions and 11 deletions

View File

@ -49,8 +49,11 @@ export function OrganizedContent(props: Props) {
: (document.body.style.overflow = "visible"); : (document.body.style.overflow = "visible");
}, [open]); }, [open]);
const ref = useRef<HTMLDivElement>(null);
const isVisible = useOnScreen(ref);
return ( return (
<div className={styles.wrapper}> <div className={styles.wrapper} ref={ref}>
<Nav sections={sections} currentIndex={currentIndex} link={props.link} /> <Nav sections={sections} currentIndex={currentIndex} link={props.link} />
<div className={styles.content}> <div className={styles.content}>
{isReadAll ? ( {isReadAll ? (
@ -76,6 +79,7 @@ export function OrganizedContent(props: Props) {
currentIndex={currentIndex} currentIndex={currentIndex}
link={props.link} link={props.link}
pageTitle={props.pageTitle} pageTitle={props.pageTitle}
componentIsVisible={isVisible}
/> />
</div> </div>
); );
@ -166,6 +170,7 @@ interface MobileProps {
currentIndex: number; currentIndex: number;
link: Link; link: Link;
pageTitle: string; pageTitle: string;
componentIsVisible: boolean;
} }
function MobileWrapper(mobileProps: MobileProps) { function MobileWrapper(mobileProps: MobileProps) {
@ -174,7 +179,7 @@ function MobileWrapper(mobileProps: MobileProps) {
return ( return (
<div ref={wrapperRef}> <div ref={wrapperRef}>
<Burger open={mobileProps.open} setOpen={mobileProps.setOpen} /> <Burger {...mobileProps} />
<Menu {...mobileProps} /> <Menu {...mobileProps} />
</div> </div>
); );
@ -183,23 +188,24 @@ function MobileWrapper(mobileProps: MobileProps) {
interface BurgerProps { interface BurgerProps {
open: boolean; open: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>; setOpen: React.Dispatch<React.SetStateAction<boolean>>;
componentIsVisible: boolean;
} }
const Burger = ({ open, setOpen }: BurgerProps) => { const Burger = ({ open, setOpen, componentIsVisible }: BurgerProps) => {
const [prevScrollPos, setPrevScrollPos] = useState(0); const [prevScrollPos, setPrevScrollPos] = useState(0);
const [visible, setVisible] = useState(true); const [burgerVisible, setBurgerVisible] = useState(true);
const debouncedPrevScrollPos = useDebounce<number>(prevScrollPos, 100); const debouncedPrevScrollPos = useDebounce<number>(prevScrollPos, 100);
useEffect(() => { useEffect(() => {
const handleScroll = () => { const handleScroll = () => {
// find current scroll position // find current scroll position
const currentScrollPos = window.pageYOffset; const currentScrollPos = window.pageYOffset;
// set state based on location info (explained in more detail below) // set state based on location info (explained in more detail below)
setVisible( setBurgerVisible(
(debouncedPrevScrollPos > currentScrollPos && componentIsVisible &&
debouncedPrevScrollPos - currentScrollPos > 70) || ((debouncedPrevScrollPos > currentScrollPos &&
currentScrollPos < 10 debouncedPrevScrollPos - currentScrollPos > 70) ||
currentScrollPos < 10)
); );
// set state to new scroll position // set state to new scroll position
@ -208,11 +214,13 @@ const Burger = ({ open, setOpen }: BurgerProps) => {
window.addEventListener("scroll", handleScroll); window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll); return () => window.removeEventListener("scroll", handleScroll);
}, [debouncedPrevScrollPos, visible]); }, [componentIsVisible, debouncedPrevScrollPos, burgerVisible]);
return ( return (
<div <div
className={styles.burger + " " + (visible ? "" : styles.hiddenBurger)} className={
styles.burger + " " + (burgerVisible ? "" : styles.hiddenBurger)
}
onClick={() => setOpen(!open)} onClick={() => setOpen(!open)}
> >
<div> <div>
@ -317,3 +325,23 @@ function Arrow({ direction }: { direction: "left" | "right" }) {
</svg> </svg>
); );
} }
function useOnScreen(ref: React.RefObject<HTMLDivElement>) {
const [isIntersecting, setIntersecting] = useState(false);
useEffect(() => {
const observer = new IntersectionObserver(([entry]) =>
setIntersecting(entry.isIntersecting)
);
if (ref.current) {
observer.observe(ref.current);
}
// Remove the observer as soon as the component is unmounted
return () => {
observer.disconnect();
};
}, [ref]);
return isIntersecting;
}