Skip to content

Commit 70dd683

Browse files
committed
project: implement animation for the app
1 parent 0137f15 commit 70dd683

File tree

7 files changed

+108
-25
lines changed

7 files changed

+108
-25
lines changed

packages/frontendmentor/fem-rock-paper-scissors-game/src/Theme.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,8 @@ export default {
3333
darkText: 'hsl(229, 25%, 31%)',
3434
scoreText: 'hsl(229, 64%, 46%)',
3535
headerOutline: 'hsl(217, 16%, 45%)',
36-
white: "#ffffff"
36+
white: "#ffffff",
37+
38+
shadowInner: "#2b3956",
39+
shadowOuter: "#273655"
3740
}

packages/frontendmentor/fem-rock-paper-scissors-game/src/components/Game.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const GameContainer = styled.div`
1212
place-items: center;
1313
gap: 4.25rem;
1414
15+
margin-top: 2rem;
16+
1517
background-image: url(${GameBackground});
1618
background-position: center;
1719
background-repeat: no-repeat;

packages/frontendmentor/fem-rock-paper-scissors-game/src/components/Gesture.tsx

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,65 @@
1-
import styled from "styled-components";
1+
import styled, { keyframes } from "styled-components";
22
import { GestureProps, Gestures } from "../types";
33

44
import RockIcon from "../assets/icon-rock.svg";
55
import PaperIcon from "../assets/icon-paper.svg";
66
import ScissorsIcon from "../assets/icon-scissors.svg";
77

8-
98
const GestureBase = styled.div`
109
width: 120px;
1110
height: 120px;
1211
1312
border-radius: 999px;
1413
14+
z-index: ${props => props.isWinner ? `-1` : ""};
15+
16+
box-shadow: ${props => props.isWinner ? `
17+
0 0 0 40px hsl(214, 47%, 23%),
18+
0 0 0 80px hsl(214, 47%, 21%)` : "none"};
19+
1520
display: flex;
1621
align-items: center;
1722
justify-content: center;
1823
1924
cursor: pointer;
20-
transition: box-shadow 250ms ease, transform 500ms ease;
25+
transition: box-shadow 250ms ease, opacity 500ms ease-out;
2126
2227
&:active {
23-
transform: scale(.7);
28+
opacity: .75;
29+
}
30+
31+
@media screen and (min-width: 650px) {
32+
width: 150px;
33+
height: 150px;
2434
}
2535
2636
@media screen and (max-width: 320px) {
2737
width: 100px;
2838
height: 100px;
2939
}
30-
31-
3240
`
3341

3442
const GestureInnerBase = styled.div`
3543
width: 75%;
3644
height: 75%;
45+
3746
3847
3948
background-repeat: no-repeat;
4049
background-position: center;
4150
background-size: 55%;
4251
border-radius: 100px;
52+
4353
background-color: ${props => props.theme.white};
4454
`
4555

4656
const GestureRock = styled(GestureBase)`
4757
background-image: linear-gradient(180deg, ${props => props.theme.rockGradient.from}, ${props => props.theme.rockGradient.to});
4858
4959
50-
@media (hover: hover) {
60+
@media (hover: hover) {
5161
&:hover {
52-
box-shadow: ${props => props.theme.rockGradient.from} 0px 5px 15px 0px;
62+
box-shadow: ${props => props.theme.rockGradient.from} 0px 5px 15px 0px;
5363
}
5464
}
5565
@@ -97,19 +107,19 @@ function getGestureComponentFromType(props: GestureProps) {
97107
switch (props.type) {
98108
case Gestures.rock:
99109
return (
100-
<GestureRock onClick={props.onClick}>
110+
<GestureRock onClick={props.onClick} isWinner={props.isWinner}>
101111
<GestureInnerRock />
102112
</GestureRock>
103113
)
104114
case Gestures.paper:
105115
return (
106-
<GesturePaper onClick={props.onClick}>
116+
<GesturePaper onClick={props.onClick} isWinner={props.isWinner}>
107117
<GestureInnerPaper />
108118
</GesturePaper>
109119
)
110120
case Gestures.scissors:
111121
return (
112-
<GestureScissors onClick={props.onClick}>
122+
<GestureScissors onClick={props.onClick} isWinner={props.isWinner}>
113123
<GestureInnerScissors />
114124
</GestureScissors>
115125
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import styled from "styled-components";
2+
3+
export default function {
4+
5+
}

packages/frontendmentor/fem-rock-paper-scissors-game/src/components/MoveState.tsx

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import styled from "styled-components";
1+
import styled, { keyframes } from "styled-components";
22
import Gesture from "./Gesture";
33

44
import { useState, useEffect } from "react";
@@ -7,11 +7,14 @@ import { MoveStateProps, GameOutcome, Gestures } from "../types";
77

88
import { PrimaryButton } from "./Button";
99

10+
11+
const ANIMATION_DURATION_IN_MS = 1000;
12+
1013
const MoveContainer = styled.div`
1114
display: flex;
1215
flex-direction: column;
1316
gap: 2rem;
14-
margin-top: 1.5rem;
17+
margin-top: 2rem;
1518
1619
@media screen and (min-width: 650px) {
1720
width: 60%;
@@ -21,6 +24,17 @@ const MoveContainer = styled.div`
2124
2225
`
2326

27+
const statusFadeOut = keyframes`
28+
from {
29+
opacity: 0;
30+
31+
}
32+
33+
to: {
34+
opacity: 1;
35+
}
36+
`
37+
2438
const StatusContainer = styled.div`
2539
display: flex;
2640
flex-direction: column;
@@ -35,19 +49,46 @@ const StatusContainer = styled.div`
3549
3650
@media screen and (min-width: 650px) {
3751
position: absolute;
38-
39-
left: 50%;
4052
top: 50%;
41-
53+
left: 50%;
4254
transform: translate(-50%, -50%);
55+
animation: ${statusFadeOut} ${ANIMATION_DURATION_IN_MS + 1000}ms forwards;
56+
animation-timing-function: ease-in-out;
4357
}
4458
`
4559

60+
const gestureGoRight = keyframes`
61+
from {
62+
left: 50%;
63+
transform: translateX(-50%);
64+
}
65+
66+
to {
67+
left: 100%;
68+
transform: translateX(-50%);
69+
70+
}
71+
`
72+
73+
const gestureGoLeft = keyframes`
74+
from {
75+
left: 50%;
76+
transform: translateX(-50%);
77+
}
78+
79+
80+
to {
81+
left: 0;
82+
transform: translateX(-50%);
83+
}
84+
`
85+
86+
87+
4688
const GestureContainer = styled.div`
4789
display: flex;
4890
gap: 1.75rem;
4991
justify-content: center;
50-
5192
> div {
5293
display: flex;
5394
flex-direction: column;
@@ -63,8 +104,25 @@ const GestureContainer = styled.div`
63104
}
64105
65106
@media screen and (min-width: 650px) {
66-
width: 100%;
67-
justify-content: space-between;
107+
display: block;
108+
position: relative;
109+
width: 80%;
110+
margin-inline: auto;
111+
height: 200px;
112+
113+
> div {
114+
animation-timing-function: ease-in;
115+
}
116+
117+
> div:nth-child(2) {
118+
position: absolute;
119+
animation: ${gestureGoRight} ${ANIMATION_DURATION_IN_MS}ms forwards;
120+
}
121+
122+
> div:nth-child(1) {
123+
position: absolute;
124+
animation: ${gestureGoLeft} ${ANIMATION_DURATION_IN_MS}ms forwards;
125+
}
68126
}
69127
`;
70128

@@ -97,27 +155,29 @@ function getOutcomeMessage(outcome: GameOutcome): string {
97155

98156
export default function (props: MoveStateProps) {
99157
const [message, setMessage] = useState<string>("");
158+
const [gameOutcome, setGameOutcome] = useState<GameOutcome>("");
100159

101160
useEffect(() => {
102-
const gameOutcome = getGameOutcome(props.player, props.house);
161+
setGameOutcome(getGameOutcome(props.player, props.house));
162+
103163
const message = getOutcomeMessage(gameOutcome);
104164
setMessage(message);
105165

106166
if (gameOutcome === GameOutcome.PlayerWins) props.setScore(props.score + 3);
107167
if (gameOutcome === GameOutcome.HouseWins) props.setScore(props.score - 2);
108168
if (gameOutcome === GameOutcome.Tie) props.setScore(props.score + 1);
109-
}, [])
169+
}, [gameOutcome])
110170

111171
return (
112172
<MoveContainer>
113173
<GestureContainer>
114174
<div>
115-
<Gesture type={props.player} />
175+
<Gesture type={props.player} isWinner={gameOutcome === GameOutcome.PlayerWins} />
116176
<p>you picked</p>
117177
</div>
118178

119179
<div>
120-
<Gesture type={props.house} />
180+
<Gesture type={props.house} isWinner={gameOutcome === GameOutcome.HouseWins}/>
121181
<p>house picked</p>
122182
</div>
123183
</GestureContainer>

packages/frontendmentor/fem-rock-paper-scissors-game/src/components/ScoreBoard.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const ScoreContainer = styled.div`
1212
display: flex;
1313
border-radius: .5rem;
1414
15+
z-index: 12;
16+
1517
padding: .75rem;
1618
1719
width: 90%;

packages/frontendmentor/fem-rock-paper-scissors-game/src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ export interface MoveStateProps {
3434
house: Gesture,
3535
onClick?: (e: any) => void;
3636
setScore: (e: number) => void;
37-
score: number
37+
score: number;
38+
isWinner?: boolean
3839
}

0 commit comments

Comments
 (0)