Fix some card UX.

This commit is contained in:
Greyson Parrelli
2026-07-27 00:03:23 -04:00
parent 76e08ceb17
commit 1070999b95
4 changed files with 133 additions and 15 deletions
+48 -3
View File
@@ -1,10 +1,11 @@
import { useEffect, useMemo, useState } from 'react'
import { useEffect, useMemo, useRef, useState } from 'react'
import type { Dispatch, SetStateAction } from 'react'
import { createPortal } from 'react-dom'
import type { BattleEvent, Card, ClientMessage, GameView } from '../types'
import { CardView } from './CardView'
import { CardView, CardZoom } from './CardView'
import { DiceRoll, ROLL_MS } from './DiceRoll'
import { SPEED_OPTIONS, useBattleSpeed } from '../useBattleSpeed'
import { useMediaQuery } from '../useMediaQuery'
// How long a settled rock roll (and its damage) stays on screen before the
// battle advances to the next step.
@@ -313,6 +314,25 @@ export function BattlePhase({ view, send, step, setStep }: Props) {
// paused freezes auto-advance so the player can walk the log manually.
const [paused, setPaused] = useState(false)
// Phone tap-to-magnify: tapping a pet/food opens a big readable copy (phones
// can't hover to preview). Opening it pauses the replay; closing it resumes
// only if the replay was actually playing when we tapped, so a manual pause
// (or a finished battle) stays put.
const isPhone = useMediaQuery('(max-width: 600px)')
const [zoom, setZoom] = useState<{ card: Card; bonus: number; damage: number; dead: boolean } | null>(
null,
)
const resumeAfterZoom = useRef(false)
const openZoom = (z: { card: Card; bonus?: number; damage?: number; dead?: boolean }) => {
resumeAfterZoom.current = !paused && !done
setPaused(true)
setZoom({ card: z.card, bonus: z.bonus ?? 0, damage: z.damage ?? 0, dead: !!z.dead })
}
const closeZoom = () => {
setZoom(null)
if (resumeAfterZoom.current) setPaused(false)
}
// A rock event on screen scrambles its dice first; only once they settle do
// we apply the damage and reveal the result.
const showingRock = !done && lastEvent?.type === 'rock'
@@ -485,7 +505,11 @@ export function BattlePhase({ view, send, step, setStep }: Props) {
}`}
style={{ zIndex: i + 1 }}
>
<CardView card={f} size="sm" />
<CardView
card={f}
size="sm"
onClick={isPhone ? () => openZoom({ card: f }) : undefined}
/>
</div>
))}
</div>
@@ -512,6 +536,17 @@ export function BattlePhase({ view, send, step, setStep }: Props) {
bonus={s.unit.bonus}
damage={s.unit.damage}
dead={s.unit.dying}
onClick={
isPhone
? () =>
openZoom({
card: s.unit!.card,
bonus: s.unit!.bonus,
damage: s.unit!.damage,
dead: s.unit!.dying,
})
: undefined
}
/>
{(s.unit.spooked > 0 || s.unit.exposed > 0) && (
<div className="ailment-badges">
@@ -717,6 +752,16 @@ export function BattlePhase({ view, send, step, setStep }: Props) {
</div>,
document.body,
)}
{zoom && (
<CardZoom
card={zoom.card}
bonus={zoom.bonus}
damage={zoom.damage}
dead={zoom.dead}
onClose={closeZoom}
/>
)}
</div>
)
}