@@ -11,71 +11,57 @@ type Props = { className?: string };
11
11
12
12
const Astronaut : React . FC < Props > = ( props ) => {
13
13
const { className } = props ;
14
- const [ timing ] = useState ( 200 ) ;
15
14
const [ isRaised , setIsRaised ] = useState ( false ) ;
16
- const [ isOnAstronaut , setIsOnAstronaut ] = useState ( false ) ;
17
- const animated_Astronaut = useSpring ( {
18
- transform : isRaised ? `translateY(-${ 30 } px)` : `translateY(0px)` ,
15
+ const [ inAnimation , setInAnimation ] = useState ( false ) ;
16
+ const [ triggeredAnimationColor , setTriggeredAnimationColor ] = useState ( false ) ;
17
+ const dark = useAgile ( core . ui . ASTRONAUT_DARK ) ;
18
+ const animatedAstronautProps = useSpring ( {
19
+ to : { x : isRaised ? 0 : 1 } ,
19
20
config : {
20
21
mass : 1 ,
21
22
tension : 400 ,
22
23
friction : 15 ,
24
+ duration : 500 ,
25
+ } ,
26
+ onRest : ( ) => {
27
+ if ( inAnimation ) {
28
+ setInAnimation ( false ) ;
29
+ setTriggeredAnimationColor ( false ) ;
30
+ }
31
+ } ,
32
+ onFrame : ( frame ) => {
33
+ if ( frame . x >= 0.45 && frame . x <= 0.5 && ! triggeredAnimationColor ) {
34
+ core . ui . toggleAstronautColor ( ! dark ) ;
35
+ setTriggeredAnimationColor ( true ) ;
36
+ }
23
37
} ,
24
38
} ) ;
25
- const dark = useAgile ( core . ui . ASTRONAUT_DARK ) ;
26
-
27
- const [ mounted , setMounted ] = useState ( false ) ;
28
- // The astronaut theme on SSR is always the default theme but the site theme
29
- // can be in a different mode. React hydration doesn't update DOM styles
30
- // that come from SSR. Hence force a re-render after mounting to apply the
31
- // current relevant styles. There will be a flash seen of the original
32
- // styles seen using this current approach but that's probably ok. Fixing
33
- // the flash will require changing the theming approach and is not worth it
34
- // at this point.
35
- useEffect ( ( ) => {
36
- setMounted ( true ) ;
37
- } , [ ] ) ;
38
-
39
- useEffect ( ( ) => {
40
- if ( ! isRaised ) return ;
41
-
42
- const timeoutId = setTimeout ( ( ) => {
43
- core . ui . toggleAstronautColor ( ! dark ) ;
44
- setIsRaised ( false ) ;
45
- } , timing ) ;
46
-
47
- return ( ) => clearTimeout ( timeoutId ) ;
48
- } , [ isRaised , timing ] ) ;
49
39
50
40
const onMouseEnter = ( ) => {
51
- if ( ! isOnAstronaut ) {
52
- setIsOnAstronaut ( true ) ;
53
- setIsRaised ( true ) ;
41
+ if ( ! inAnimation ) {
42
+ setInAnimation ( true ) ;
43
+ setIsRaised ( ! isRaised ) ;
54
44
}
55
45
} ;
56
46
57
- const onMouseLeave = ( ) => {
58
- // to prevent endless bouncer
59
- setTimeout ( ( ) => {
60
- setIsOnAstronaut ( false ) ;
61
- } , 1100 ) ;
62
- } ;
63
-
64
47
return (
65
- < div key = { String ( mounted ) } className = { clsx ( styles . Container , className ) } >
48
+ < div className = { clsx ( styles . Container , className ) } >
66
49
< animated . div
67
- style = { animated_Astronaut }
50
+ style = { {
51
+ transform : animatedAstronautProps . x . interpolate ( {
52
+ range : [ 0 , 0.5 , 1 ] ,
53
+ output : [
54
+ `translateY(${ 0 } px)` ,
55
+ `translateY(-${ 30 } px)` ,
56
+ `translateY(${ 0 } px)` ,
57
+ ] ,
58
+ } ) ,
59
+ } }
68
60
className = { styles . ImageContainer } >
69
61
{ dark ? (
70
- < AstronautDark
71
- onMouseEnter = { onMouseEnter }
72
- onMouseLeave = { onMouseLeave }
73
- />
62
+ < AstronautDark onMouseEnter = { onMouseEnter } />
74
63
) : (
75
- < AstronautLight
76
- onMouseEnter = { onMouseEnter }
77
- onMouseLeave = { onMouseLeave }
78
- />
64
+ < AstronautLight onMouseEnter = { onMouseEnter } />
79
65
) }
80
66
</ animated . div >
81
67
< div className = { styles . Text } > Poke me 👆 to mutate my color State.</ div >
0 commit comments