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");
}, [open]);
const ref = useRef<HTMLDivElement>(null);
const isVisible = useOnScreen(ref);
return (
<div className={styles.wrapper}>
<div className={styles.wrapper} ref={ref}>
<Nav sections={sections} currentIndex={currentIndex} link={props.link} />
<div className={styles.content}>
{isReadAll ? (
@ -76,6 +79,7 @@ export function OrganizedContent(props: Props) {
currentIndex={currentIndex}
link={props.link}
pageTitle={props.pageTitle}
componentIsVisible={isVisible}
/>
</div>
);
@ -166,6 +170,7 @@ interface MobileProps {
currentIndex: number;
link: Link;
pageTitle: string;
componentIsVisible: boolean;
}
function MobileWrapper(mobileProps: MobileProps) {
@ -174,7 +179,7 @@ function MobileWrapper(mobileProps: MobileProps) {
return (
<div ref={wrapperRef}>
<Burger open={mobileProps.open} setOpen={mobileProps.setOpen} />
<Burger {...mobileProps} />
<Menu {...mobileProps} />
</div>
);
@ -183,23 +188,24 @@ function MobileWrapper(mobileProps: MobileProps) {
interface BurgerProps {
open: 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 [visible, setVisible] = useState(true);
const [burgerVisible, setBurgerVisible] = useState(true);
const debouncedPrevScrollPos = useDebounce<number>(prevScrollPos, 100);
useEffect(() => {
const handleScroll = () => {
// find current scroll position
const currentScrollPos = window.pageYOffset;
// set state based on location info (explained in more detail below)
setVisible(
(debouncedPrevScrollPos > currentScrollPos &&
debouncedPrevScrollPos - currentScrollPos > 70) ||
currentScrollPos < 10
setBurgerVisible(
componentIsVisible &&
((debouncedPrevScrollPos > currentScrollPos &&
debouncedPrevScrollPos - currentScrollPos > 70) ||
currentScrollPos < 10)
);
// set state to new scroll position
@ -208,11 +214,13 @@ const Burger = ({ open, setOpen }: BurgerProps) => {
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, [debouncedPrevScrollPos, visible]);
}, [componentIsVisible, debouncedPrevScrollPos, burgerVisible]);
return (
<div
className={styles.burger + " " + (visible ? "" : styles.hiddenBurger)}
className={
styles.burger + " " + (burgerVisible ? "" : styles.hiddenBurger)
}
onClick={() => setOpen(!open)}
>
<div>
@ -317,3 +325,23 @@ function Arrow({ direction }: { direction: "left" | "right" }) {
</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;
}