From e60a14e799d6cce7e4a630fb45cd255a0b641420 Mon Sep 17 00:00:00 2001 From: Liam Date: Thu, 12 Sep 2024 23:26:02 +0100 Subject: [PATCH] better score animations --- src/app/layout.tsx | 11 ++- .../leaderboard/leaderboard-scores.tsx | 2 +- src/components/player/player-scores.tsx | 80 ++++++++++++++----- 3 files changed, 68 insertions(+), 25 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 297f786..a6eb7f3 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,4 +1,5 @@ import { PreloadResources } from "@/components/preload-resources"; +import { AnimatePresence } from "framer-motion"; import type { Metadata } from "next"; import localFont from "next/font/local"; import BackgroundImage from "../components/background-image"; @@ -67,10 +68,12 @@ export default function RootLayout({ -
- - {children} -
+ +
+ + {children} +
+
diff --git a/src/components/leaderboard/leaderboard-scores.tsx b/src/components/leaderboard/leaderboard-scores.tsx index 780cfb3..306bc56 100644 --- a/src/components/leaderboard/leaderboard-scores.tsx +++ b/src/components/leaderboard/leaderboard-scores.tsx @@ -47,7 +47,7 @@ export default function LeaderboardScores({ leaderboard }: Props) { } return ( - +
{isError &&

Oopsies! Something went wrong.

} diff --git a/src/components/player/player-scores.tsx b/src/components/player/player-scores.tsx index 5b33aa1..a5a0851 100644 --- a/src/components/player/player-scores.tsx +++ b/src/components/player/player-scores.tsx @@ -8,7 +8,7 @@ import { capitalizeFirstLetter } from "@/common/string-utils"; import useWindowDimensions from "@/hooks/use-window-dimensions"; import { ClockIcon, TrophyIcon } from "@heroicons/react/24/solid"; import { useQuery } from "@tanstack/react-query"; -import { motion, useAnimation } from "framer-motion"; +import { motion, useAnimation, Variants } from "framer-motion"; import { useCallback, useEffect, useState } from "react"; import Card from "../card"; import Pagination from "../input/pagination"; @@ -35,11 +35,48 @@ type Props = { page: number; }; +const containerVariants: Variants = { + hiddenRight: { + opacity: 0, + x: 50, + }, + hiddenLeft: { + opacity: 0, + x: -50, + }, + visible: { + opacity: 1, + x: 0, + transition: { + staggerChildren: 0.05, + }, + }, +}; + +const childVariants: Variants = { + hiddenRight: { + opacity: 0, + x: 50, + }, + hiddenLeft: { + opacity: 0, + x: -50, + }, + visible: { + opacity: 1, + x: 0, + transition: { + ease: "anticipate", + }, + }, +}; + export default function PlayerScores({ initialScoreData, player, sort, page }: Props) { const { width } = useWindowDimensions(); const controls = useAnimation(); const [currentSort, setCurrentSort] = useState(sort); + const [previousPage, setPreviousPage] = useState(page); const [currentPage, setCurrentPage] = useState(page); const [currentScores, setCurrentScores] = useState(initialScoreData); @@ -54,23 +91,18 @@ export default function PlayerScores({ initialScoreData, player, sort, page }: P staleTime: 30 * 1000, // Cache data for 30 seconds }); - const handleAnimation = useCallback(() => { - controls.set({ x: -50, opacity: 0 }); - controls.start({ x: 0, opacity: 1, transition: { duration: 0.25 } }); - }, [controls]); + const handleScoreLoad = useCallback(async () => { + await controls.start(previousPage >= currentPage ? "hiddenRight" : "hiddenLeft"); + setCurrentScores(scores); + await controls.start("visible"); + }, [scores, controls]); useEffect(() => { if (scores) { - setCurrentScores(scores); + handleScoreLoad(); } }, [scores]); - useEffect(() => { - if (scores) { - handleAnimation(); - } - }, [scores, handleAnimation]); - useEffect(() => { const newUrl = `/player/${player.id}/${currentSort}/${currentPage}`; window.history.replaceState({ ...window.history.state, as: newUrl, url: newUrl }, "", newUrl); @@ -89,7 +121,7 @@ export default function PlayerScores({ initialScoreData, player, sort, page }: P } return ( - +
{Object.values(scoreSort).map((sortOption, index) => (
- -
- {currentScores.playerScores.map((playerScore, index) => ( - - ))} -
+ + {currentScores.playerScores.map((playerScore, index) => ( + + + + ))} { + setPreviousPage(currentPage); + setCurrentPage(page); + }} />
);