@@ -12,7 +12,8 @@ type Props = { className?: string };
12
12
const Astronaut : React . FC < Props > = ( props ) => {
13
13
const { className } = props ;
14
14
const [ timing ] = useState ( 200 ) ;
15
- const [ isRaised , setIsRaised ] = React . useState ( false ) ;
15
+ const [ isRaised , setIsRaised ] = useState ( false ) ;
16
+ const [ isOnAstronaut , setIsOnAstronaut ] = useState ( false ) ;
16
17
const animated_Astronaut = useSpring ( {
17
18
transform : isRaised ? `translateY(-${ 30 } px)` : `translateY(0px)` ,
18
19
config : {
@@ -23,10 +24,20 @@ const Astronaut: React.FC<Props> = (props) => {
23
24
} ) ;
24
25
const dark = useAgile ( core . ui . ASTRONAUT_DARK ) ;
25
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.
26
35
useEffect ( ( ) => {
27
- if ( ! isRaised ) {
28
- return ;
29
- }
36
+ setMounted ( true ) ;
37
+ } , [ ] ) ;
38
+
39
+ useEffect ( ( ) => {
40
+ if ( ! isRaised ) return ;
30
41
31
42
const timeoutId = setTimeout ( ( ) => {
32
43
core . ui . toggleAstronautColor ( ! dark ) ;
@@ -36,19 +47,35 @@ const Astronaut: React.FC<Props> = (props) => {
36
47
return ( ) => clearTimeout ( timeoutId ) ;
37
48
} , [ isRaised , timing ] ) ;
38
49
39
- function trigger ( ) {
40
- setIsRaised ( true ) ;
41
- }
50
+ const onMouseEnter = ( ) => {
51
+ if ( ! isOnAstronaut ) {
52
+ setIsOnAstronaut ( true ) ;
53
+ setIsRaised ( true ) ;
54
+ }
55
+ } ;
56
+
57
+ const onMouseLeave = ( ) => {
58
+ // to prevent endless bouncer
59
+ setTimeout ( ( ) => {
60
+ setIsOnAstronaut ( false ) ;
61
+ } , 1100 ) ;
62
+ } ;
42
63
43
64
return (
44
- < div className = { clsx ( styles . Container , className ) } >
65
+ < div key = { String ( mounted ) } className = { clsx ( styles . Container , className ) } >
45
66
< animated . div
46
67
style = { animated_Astronaut }
47
68
className = { styles . ImageContainer } >
48
69
{ dark ? (
49
- < AstronautDark onMouseEnter = { trigger } />
70
+ < AstronautDark
71
+ onMouseEnter = { onMouseEnter }
72
+ onMouseLeave = { onMouseLeave }
73
+ />
50
74
) : (
51
- < AstronautLight onMouseEnter = { trigger } />
75
+ < AstronautLight
76
+ onMouseEnter = { onMouseEnter }
77
+ onMouseLeave = { onMouseLeave }
78
+ />
52
79
) }
53
80
</ animated . div >
54
81
< div className = { styles . Text } > Poke me 👆 to mutate my color State.</ div >
0 commit comments