'use client'; import { motion, useReducedMotion, useMotionValue, useSpring } from 'framer-motion'; import { useEffect, useState } from 'react'; import { Box } from '@/ui/Box'; import { Text } from '@/ui/Text'; import { Stack } from '@/ui/Stack'; export function StandingsTableMockup() { const shouldReduceMotion = useReducedMotion(); const [hoveredRow, setHoveredRow] = useState(null); const [isMobile, setIsMobile] = useState(false); useEffect(() => { setIsMobile(window.innerWidth < 768); }, []); if (isMobile) { return ( # Driver Pts {[1, 2, 3, 4, 5].map((i) => ( {i} 🏎️ {300 - i * 20} ))} ); } const getRowAnimation = (i: number) => ({ hidden: { opacity: 0, y: shouldReduceMotion ? 0 : 10 }, visible: { opacity: 1, y: 0, transition: { delay: shouldReduceMotion ? 0 : i * 0.05, type: 'spring' as const, stiffness: 300, damping: 24 } } }); return ( Real-time standings updated after every race # Driver Wins Points {[1, 2, 3, 4, 5, 6, 7, 8].map((i) => ( !shouldReduceMotion && setHoveredRow(i)} onHoverEnd={() => setHoveredRow(null)} whileHover={shouldReduceMotion ? {} : { scale: 1.01, boxShadow: '0 0 20px rgba(25,140,255,0.3)', transition: { duration: 0.15 } }} > {i} 🏎️ ))} ); } function AnimatedPoints({ points, position, shouldReduceMotion }: { points: number; position: number; shouldReduceMotion: boolean; }) { const motionValue = useMotionValue(0); const spring = useSpring(motionValue, { stiffness: 50, damping: 20 }); useEffect(() => { if (shouldReduceMotion) { motionValue.set(points); } else { setTimeout(() => motionValue.set(points), 100 + position * 50); } }, [points, position, shouldReduceMotion, motionValue]); const percentage = (points / 300) * 100; return ( {shouldReduceMotion ? points : {spring}} ); }