|
|
|
@ -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; |
|
|
|
|
} |
|
|
|
|