'use client'; import { forwardRef, HTMLAttributes, useEffect, useState } from 'react'; import styles from './scroll-indicator.module.css'; export interface ScrollIndicatorProps extends HTMLAttributes { text?: string; showArrow?: boolean; showPercentage?: boolean; variant?: 'default' | 'blood' | 'minimal'; position?: 'right' | 'left'; trackHeight?: number; } export const ScrollIndicator = forwardRef( ({ text = 'SCROLL', showArrow = false, showPercentage = false, variant = 'default', position = 'right', trackHeight = 100, className, ...props }, ref) => { const [scrollProgress, setScrollProgress] = useState(0); const [isPulsing, setIsPulsing] = useState(false); useEffect(() => { const handleScroll = () => { const scrollTop = window.scrollY; const docHeight = document.documentElement.scrollHeight - window.innerHeight; const progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0; setScrollProgress(Math.min(100, Math.max(0, progress))); // Trigger pulse effect setIsPulsing(true); setTimeout(() => setIsPulsing(false), 500); }; window.addEventListener('scroll', handleScroll, { passive: true }); handleScroll(); // Initial call return () => window.removeEventListener('scroll', handleScroll); }, []); const thumbTop = (scrollProgress / 100) * (trackHeight - 20); // 20 = thumb height const containerClasses = [ styles.container, variant === 'blood' && styles.variantBlood, variant === 'minimal' && styles.variantMinimal, position === 'left' && styles.positionLeft, className, ].filter(Boolean).join(' '); return (
{showArrow && }
{text && {text}} {showPercentage && ( {Math.round(scrollProgress)}% )}
); } ); ScrollIndicator.displayName = 'ScrollIndicator'; export default ScrollIndicator;