import { type CSSProperties } from "react"; import { useScrollEdges } from "./useScrollEdges"; // Vertical scroll-affordance for a scroll container (typically one whose native scrollbar is hidden // with `.no-scrollbar`, but the page scroller keeps its bar and takes the fade anyway): fades the // top/bottom edge of the content to hint there's more to scroll, but only on the edge that's actually // clipped (no fade at a boundary, none when it all fits). Returns a callback ref to attach to the // scroller and the mask `style` to spread onto it. The scroller-and-children watching machinery lives // in the shared `useScrollEdges` (the horizontal twin, Carousel's `useHScroll`, uses the same core). // `fadeTop` gates the top edge only. Pass false when the scroller's top is a sticky element (a table's // sticky header): fading there would eat into the header instead of hinting at content, and the header // would visibly change as the fade turns on with the first scroll. export function useScrollFade( fadePx = 20, fadeTop = true, ): { ref: (node: HTMLElement | null) => void; style: CSSProperties; } { const { ref, start, end } = useScrollEdges("y"); const mask = `linear-gradient(to bottom, transparent, #000 ${start && fadeTop ? fadePx : 0}px, #000 calc(100% - ${ end ? fadePx : 0 }px), transparent)`; return { ref, style: { maskImage: mask, WebkitMaskImage: mask } }; }