11"use client" ;
22
33import { motion } from "motion/react" ;
4+ import { useState , useEffect } from "react" ;
45import { cn } from "@/lib/utils" ;
56
67export const Spinner = ( { className } : { className ?: string } ) => {
8+ const [ rotation , setRotation ] = useState ( 0 ) ;
9+
10+ // Start the animation loop
11+ useEffect ( ( ) => {
12+ const timer = setTimeout ( ( ) => {
13+ setRotation ( 240 ) ; // Start by rotating right with overshoot
14+ } , 20 ) ;
15+ return ( ) => clearTimeout ( timer ) ;
16+ } , [ ] ) ;
17+
718 // Create 7 circles positioned in a circle
819 const circles = Array . from ( { length : 7 } , ( _ , i ) => {
920 const angle = ( i * 360 ) / 7 ; // Distribute circles evenly
1021 const radius = 7 ; // Distance from center
1122 const x = Math . cos ( ( angle * Math . PI ) / 180 ) * radius ;
1223 const y = Math . sin ( ( angle * Math . PI ) / 180 ) * radius ;
1324
14- return { x, y, delay : i * 0.1 } ;
25+ return { x, y } ;
1526 } ) ;
1627
1728 return (
@@ -23,32 +34,29 @@ export const Spinner = ({ className }: { className?: string }) => {
2334 < motion . div
2435 className = "absolute inset-0 flex items-center justify-center"
2536 animate = { {
26- rotate : [ 0 , 360 , 360 , 0 , 0 ] , // Right, pause, left, pause
37+ rotate : rotation ,
2738 } }
2839 transition = { {
40+ type : "spring" ,
41+ stiffness : 120 ,
42+ damping : 15 ,
2943 duration : 3 ,
30- repeat : Infinity ,
31- ease : "circInOut" ,
32- times : [ 0 , 0.4 , 0.5 , 0.9 , 1 ] , // Timing for each keyframe
44+ } }
45+ onAnimationComplete = { ( ) => {
46+ // After animation completes, switch to the opposite rotation with 60° overshoot
47+ setTimeout ( ( ) => {
48+ setRotation ( ( prev ) => ( prev === 0 || prev === 240 ? - 60 : 240 ) ) ;
49+ } , 20 ) ;
3350 } }
3451 >
3552 { circles . map ( ( circle , index ) => (
36- < motion . div
53+ < div
3754 key = { index }
3855 className = "absolute size-1 bg-current rounded-full"
3956 style = { {
4057 left : 12 + circle . x - 2 , // Center (12) + offset - half circle size (2)
4158 top : 12 + circle . y - 2 ,
4259 } }
43- animate = { {
44- scale : [ 1 , 1 , 1 ] ,
45- } }
46- transition = { {
47- duration : 4 ,
48- repeat : Infinity ,
49- delay : circle . delay ,
50- ease : "easeInOut" ,
51- } }
5260 />
5361 ) ) }
5462 </ motion . div >
0 commit comments