useScrollProgress
ericts-ui/use-scroll-progressFreeHook
A render-free vertical scroll progress hook for window or element scrollers with optional time-based smoothing.
Install it
npx shadcn@latest add https://ui.ericts.com/r/use-scroll-progress.jsonSource
1"use client";23import { useCallback, useEffect, useLayoutEffect, useRef } from "react";4import type { RefObject } from "react";56const DEFAULT_DISTANCE = 1;7const DEFAULT_SMOOTHING = 0.1;8const SETTLE_THRESHOLD = 0.0004;910const useIsomorphicLayoutEffect =11 typeof window === "undefined" ? useEffect : useLayoutEffect;1213export type ScrollProgressSource = "container" | "window";1415export type UseScrollProgressOptions<16 TContainer extends HTMLElement,17 TTrack extends HTMLElement,18> = {19 /** Scrollable element. Also used as the measured viewport in container mode. */20 containerRef: RefObject<TContainer | null>;21 /** Element whose top edge marks progress zero in window mode. */22 trackRef?: RefObject<TTrack | null>;23 /** Read from the element or the page. Defaults to `container`. */24 source?: ScrollProgressSource;25 /** Length of the 0–1 range, in measured viewport heights. */26 distance?: number;27 /** Exponential follow time in seconds. Set to `0` for direct scrubbing. */28 smoothing?: number;29 /** Gate scroll tracking without unmounting the consumer. */30 enabled?: boolean;31 /** Value emitted while disabled. Defaults to `1`. */32 disabledProgress?: number;33 /** Called outside React's render cycle whenever progress changes. */34 onProgress: (progress: number) => void;35 /** Called after the scroll viewport is measured. */36 onMeasure?: (viewportHeight: number) => void;37};3839export type UseScrollProgressResult = {40 /** Re-read viewport size and progress after imperative layout changes. */41 measure: () => void;42};4344/**45 * Tracks vertical scroll as a clamped 0–1 value without rendering on every46 * frame. It supports a nested scroll container or the page, optional47 * exponential smoothing, resize measurement, and an imperative refresh.48 */49export function useScrollProgress<50 TContainer extends HTMLElement = HTMLElement,51 TTrack extends HTMLElement = HTMLElement,52>({53 containerRef,54 trackRef,55 source = "container",56 distance = DEFAULT_DISTANCE,57 smoothing = DEFAULT_SMOOTHING,58 enabled = true,59 disabledProgress = 1,60 onProgress,61 onMeasure,62}: UseScrollProgressOptions<63 TContainer,64 TTrack65>): UseScrollProgressResult {66 const onProgressRef = useRef(onProgress);67 const onMeasureRef = useRef(onMeasure);68 const viewportHeightRef = useRef(1);69 const viewportWidthRef = useRef<number | null>(null);70 const initialProgress = clamp(disabledProgress, 0, 1);71 const currentRef = useRef(initialProgress);72// … truncated
Files it writes
More from ericts-ui
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| useElementHeightuse-element-height | ericts-ui | Hooks | Free | no deps | |
| useElementSizeMapuse-element-size-map | ericts-ui | Hooks | Free | no deps | |
| useReducedMotionuse-reduced-motion | ericts-ui | Hooks | Free | no deps | |
| useScrollAnchoruse-scroll-anchor | ericts-ui | Hooks | Free | no deps |
