From c4b44e872a3b8ead29aa337fab1bfd8fb9a29923 Mon Sep 17 00:00:00 2001 From: Vishesh 'ironeagle' Bangotra Date: Sat, 29 Nov 2025 03:42:33 +0530 Subject: [PATCH] feat(ui): implement timed haiku rotation with staggered line reveal and group fade-out - Added haiku display block under board with Framer Motion animations - Implement sequential line-by-line fade-in (staggered 2.4s per line) - Implement full-haiku fade-out using AnimatePresence keyed by haikuIndex - Added timed rotation logic using total animation duration (~14.4s) - Integrated getHaiku() random selector for new haiku each cycle - Ensured smooth transitions by updating haikuIndex on cycle end - Added no-winner condition wrapper to show haikus during gameplay --- src/tictactoe/Board.tsx | 70 ++++++++++++++++++++++++++- src/tictactoe/utils/haikus.ts | 91 +++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 src/tictactoe/utils/haikus.ts diff --git a/src/tictactoe/Board.tsx b/src/tictactoe/Board.tsx index 246d0af..6f26b4e 100644 --- a/src/tictactoe/Board.tsx +++ b/src/tictactoe/Board.tsx @@ -1,6 +1,7 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { useNakama } from "./providers/NakamaProvider"; +import getHaiku from "./utils/haikus"; interface BoardProps { board: string[][]; @@ -47,6 +48,21 @@ export default function Board({ status = isMyTurn ? "Your turn" : "Opponent's turn"; } + const [haiku, setHaiku] = useState(getHaiku()); + const [haikuIndex, setHaikuIndex] = useState(0); + + useEffect(() => { + const totalTime = 3 * 2400 + 6000 + 2400; + + const timer = setTimeout(() => { + const next = getHaiku(); + setHaiku(next); + setHaikuIndex((i) => i + 1); + }, totalTime); + + return () => clearTimeout(timer); + }, [haikuIndex]); + return ( <> {matchId && ( @@ -154,6 +170,58 @@ export default function Board({ )} + {!winner && ( +
+ + + {haiku.map((line, i) => ( + + {line} + + ))} + + +
+ )} + {/* Winner pulse animation */} {winner && (