Animated scroll progress for your web pages.
1'use client';
2
3import { motion, SpringOptions, useScroll, useSpring } from 'motion/react';
4import { cn } from '@/lib/utils';
5import { RefObject } from 'react';
6
7export type ScrollProgressProps = {
8 className?: string;
9 springOptions?: SpringOptions;
10 containerRef?: RefObject<HTMLDivElement>;
11};
12
13const DEFAULT_SPRING_OPTIONS: SpringOptions = {
14 stiffness: 200,
15 damping: 50,
16 restDelta: 0.001,
17};
18
19export function ScrollProgress({
20 className,
21 springOptions,
22 containerRef,
23}: ScrollProgressProps) {
24 const { scrollYProgress } = useScroll({
25 container: containerRef,
26 layoutEffect: Boolean(containerRef?.current),
27 });
28
29 const scaleX = useSpring(scrollYProgress, {
30 ...DEFAULT_SPRING_OPTIONS,
31 ...(springOptions ?? {}),
32 });
33
34 return (
35 <motion.div
36 className={cn('inset-x-0 top-0 h-1 origin-left', className)}
37 style={{
38 scaleX,
39 }}
40 />
41 );
42}
43