From 67980741f2654c4a7a3c954963b29e81ce1794ee Mon Sep 17 00:00:00 2001 From: Andy Aylward Date: Sun, 8 Mar 2026 17:21:40 -0400 Subject: [PATCH] fix(golf): keep drawn card in-place on source pile and fix double-click selection Bug 1: Drawn card now stays visually on its source pile (draw or discard) with a gold highlight, instead of appearing as a third pile. Track source via drawnFrom state, reset when drawnCard clears. Bug 2: Switch .card.selected from border to outline (no box model change avoids layout shift in the card grid). Drop CSS animation that could cause compositor layer promotion issues on first click. Co-Authored-By: Claude Opus 4.6 --- src/apps/golf/components/GolfGame.module.css | 41 ++++-------- src/apps/golf/components/GolfGame.tsx | 66 ++++++++++++-------- 2 files changed, 50 insertions(+), 57 deletions(-) diff --git a/src/apps/golf/components/GolfGame.module.css b/src/apps/golf/components/GolfGame.module.css index ff38050..b1bd073 100644 --- a/src/apps/golf/components/GolfGame.module.css +++ b/src/apps/golf/components/GolfGame.module.css @@ -254,15 +254,10 @@ } .card.selected { - border: 3px solid #ffd700; - transform: scale(1.08); - box-shadow: 0 0 16px rgba(255, 215, 0, 0.5); - animation: selectedPulse 1.2s ease-in-out infinite; -} - -@keyframes selectedPulse { - 0%, 100% { box-shadow: 0 0 12px rgba(255, 215, 0, 0.4); } - 50% { box-shadow: 0 0 24px rgba(255, 215, 0, 0.8); } + outline: 3px solid #ffd700; + outline-offset: -3px; + transform: scale(1.05); + box-shadow: 0 0 20px rgba(255, 215, 0, 0.6); } .card.clickable, @@ -354,15 +349,10 @@ color: rgba(255, 255, 255, 0.5); } -.emptyPileReserved { - width: 80px; - height: 120px; - visibility: hidden; -} - -.drawnCardWrapper .card { - border: 2px solid #ffd700; - box-shadow: 0 0 16px rgba(255, 215, 0, 0.4); +.drawnCardHighlight .card { + outline: 3px solid #ffd700; + outline-offset: -3px; + box-shadow: 0 0 20px rgba(255, 215, 0, 0.6); } .playerArea { @@ -650,8 +640,9 @@ } .card.selected { - border: 3px solid #ffd700; - transform: scale(1.1); + outline: 3px solid #ffd700; + outline-offset: -3px; + transform: scale(1.08); box-shadow: 0 0 24px rgba(255, 215, 0, 0.6); } @@ -682,11 +673,6 @@ height: 100px; } - .emptyPileReserved { - width: 70px; - height: 100px; - } - .playerArea { padding: 1rem; width: 100%; @@ -888,11 +874,6 @@ height: 80px; } - .emptyPileReserved { - width: 55px; - height: 80px; - } - .cardGrid { max-width: 130px; gap: 0.6rem; diff --git a/src/apps/golf/components/GolfGame.tsx b/src/apps/golf/components/GolfGame.tsx index 33327ac..a7a7dd3 100644 --- a/src/apps/golf/components/GolfGame.tsx +++ b/src/apps/golf/components/GolfGame.tsx @@ -69,6 +69,19 @@ const GolfGame = ({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConn joinNewGame } = useGolfGame({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConnectionChange, permalinkParams }) + const [drawnFromRaw, setDrawnFromRaw] = useState<'deck' | 'discard' | null>(null) + const drawnFrom = gameState?.drawnCard ? drawnFromRaw : null + + const handleDrawCard = () => { + setDrawnFromRaw('deck') + drawCard() + } + + const handleTakeFromDiscard = () => { + setDrawnFromRaw('discard') + takeFromDiscard() + } + const renderCard = (card: Card | null, index: number, isRevealed: boolean, isPlayer: boolean) => { const isSelected = selectedCardIndex === index const canInteract = isPlayer && (isMyTurn || (currentPlayer && !currentPlayer.hasPeeked && gameState?.gamePhase === 'playing')) @@ -520,28 +533,38 @@ const GolfGame = ({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConn

Draw Pile

-
isMyTurn && !gameState.drawnCard && drawCard()} - onTouchEnd={(e) => { - e.preventDefault() - if (isMyTurn && !gameState.drawnCard) drawCard() - }} - > - ? - {gameState.drawPile} -
+ {gameState.drawnCard && isMyTurn && drawnFrom === 'deck' ? ( +
+ {renderCard(gameState.drawnCard, -2, true, false)} +
+ ) : ( +
isMyTurn && !gameState.drawnCard && handleDrawCard()} + onTouchEnd={(e) => { + e.preventDefault() + if (isMyTurn && !gameState.drawnCard) handleDrawCard() + }} + > + ? + {gameState.drawPile} +
+ )}

Discard Pile

- {gameState.discardPile.length > 0 ? ( + {gameState.drawnCard && isMyTurn && drawnFrom === 'discard' ? ( +
+ {renderCard(gameState.drawnCard, -2, true, false)} +
+ ) : gameState.discardPile.length > 0 ? (
0 ? styles.clickable : ''}`} - onClick={() => isMyTurn && !gameState.drawnCard && gameState.discardPile.length > 0 && takeFromDiscard()} + onClick={() => isMyTurn && !gameState.drawnCard && gameState.discardPile.length > 0 && handleTakeFromDiscard()} onTouchEnd={(e) => { e.preventDefault() - if (isMyTurn && !gameState.drawnCard && gameState.discardPile.length > 0) takeFromDiscard() + if (isMyTurn && !gameState.drawnCard && gameState.discardPile.length > 0) handleTakeFromDiscard() }} > {renderCard(gameState.discardPile[gameState.discardPile.length - 1], -1, true, false)} @@ -550,17 +573,6 @@ const GolfGame = ({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConn
Empty
)}
- -
-

{gameState.drawnCard && isMyTurn ? 'Drawn Card' : '\u00A0'}

- {gameState.drawnCard && isMyTurn ? ( -
- {renderCard(gameState.drawnCard, -2, true, false)} -
- ) : ( -
- )} -
@@ -576,11 +588,11 @@ const GolfGame = ({ onGameIdChange, onPlayerIdChange, onPlayerNameChange, onConn
{!gameState.drawnCard ? ( <> - {gameState.discardPile.length > 0 && ( - )}