Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 65x 65x 65x 65x 25x 25x 25x 5x 5x 5x 4x 5x 5x 4x 25x 25x 25x 25x 65x | import { useEffect, useRef, useState } from "react";
type ScrollDirection = "up" | "down" | null;
export function useScrollDirection(
targetRef: React.RefObject<HTMLElement | null>,
threshold = 10,
): ScrollDirection {
const [direction, setDirection] = useState<ScrollDirection>(null);
const lastScrollY = useRef(0);
const idleTimer = useRef<ReturnType<typeof setTimeout> | undefined>(
undefined,
);
useEffect(() => {
const el = targetRef.current;
Iif (!el) return;
const onScroll = () => {
const currentY = el.scrollTop;
const diff = currentY - lastScrollY.current;
if (Math.abs(diff) < threshold) return;
setDirection(diff > 0 ? "down" : "up");
lastScrollY.current = currentY;
// Show bars again after scrolling stops
if (idleTimer.current) clearTimeout(idleTimer.current);
idleTimer.current = setTimeout(() => setDirection(null), 800);
};
el.addEventListener("scroll", onScroll, { passive: true });
return () => {
el.removeEventListener("scroll", onScroll);
if (idleTimer.current) clearTimeout(idleTimer.current);
};
}, [targetRef, threshold]);
return direction;
}
|