scroll-progress.tsx
1 'use client'; 2 3 import { motion, type SpringOptions, useScroll, useSpring } from 'motion/react'; 4 import { RefObject } from 'react'; 5 import { cn } from '@/lib/utils'; 6 7 export type ScrollProgressProps = { 8 className?: string; 9 springOptions?: SpringOptions; 10 containerRef?: RefObject<HTMLDivElement>; 11 }; 12 13 const DEFAULT_SPRING_OPTIONS: SpringOptions = { 14 damping: 50, 15 restDelta: 0.001, 16 stiffness: 200, 17 }; 18 19 export 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 }