'use client'; import { forwardRef, HTMLAttributes, useEffect, useState } from 'react'; export interface ScrollIndicatorProps extends HTMLAttributes { text?: string; showArrow?: boolean; showPercentage?: boolean; variant?: 'default' | 'blood' | 'minimal'; position?: 'right' | 'left'; trackHeight?: number; } const variantStyles: Record = { default: { track: 'bg-stone-700', thumb: 'bg-amber-500 shadow-[0_0_10px_rgba(201,162,39,0.3)]', text: 'text-stone-500', }, blood: { track: 'bg-red-500/20', thumb: 'bg-red-500 shadow-[0_0_10px_rgba(255,0,64,0.5)]', text: 'text-gray-500', }, minimal: { track: 'bg-stone-700', thumb: 'bg-amber-500', text: 'text-stone-500', }, }; export const ScrollIndicator = forwardRef( ({ text = 'SCROLL', showArrow = false, showPercentage = false, variant = 'default', position = 'right', trackHeight = 100, className, ...props }, ref) => { const [scrollProgress, setScrollProgress] = useState(0); 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))); }; window.addEventListener('scroll', handleScroll, { passive: true }); handleScroll(); return () => window.removeEventListener('scroll', handleScroll); }, []); const colors = variantStyles[variant]; const thumbTop = (scrollProgress / 100) * (trackHeight - 20); const isMinimal = variant === 'minimal'; return (
{showArrow && ( )}
{text && !isMinimal && ( {text} )} {showPercentage && ( {Math.round(scrollProgress)}% )}
); } ); ScrollIndicator.displayName = 'ScrollIndicator'; export default ScrollIndicator;