Every token on the board can be read as its card

"What does a rosebush do again?" now has an in-game answer: press and
hold any square (450ms) to open the card behind whatever occupies it —
creature, terrain, dropped object, warp token, or boobytrap marker —
in the view-only inspector corner. A plain click that claims no game
action peeks too: out of turn, every tap reads; on your turn, taps
beyond your reach read instead of doing nothing, and clicking an
opponent's creature with nothing selected reads its card. Priority
when a square holds several stories: creature, then terrain, then the
topmost dropped object.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-16 10:39:56 -04:00
co-authored by Claude Fable 5
parent a9d40d73ac
commit 97a3305d07
2 changed files with 59 additions and 3 deletions
+24 -1
View File
@@ -14,6 +14,7 @@
onPlayerClick,
onCreatureClick,
onWarpClick,
onCellPeek,
markedCell = null,
litCells = null,
}: {
@@ -25,6 +26,8 @@
onPlayerClick?: (playerId: string) => void;
onCreatureClick?: (creatureId: string) => void;
onWarpClick?: (cell: { x: number; y: number }, side: Side) => void;
/** Long-press on a square: read the card behind whatever occupies it. */
onCellPeek?: (cell: { x: number; y: number }) => void;
/** First square of a two-square spell: marked so the click reads as taken. */
markedCell?: { x: number; y: number } | null;
/** When set, squares NOT in this set dim — the targeting aid. */
@@ -33,6 +36,23 @@
const PLAYER_COLORS = ["#1a9c46", "#d3352b", "#c9308f", "#3a3ac0", "#2ab0c9", "#c9a72a"];
// Press-and-hold peeks the square's card; a fired hold swallows the click.
let peekTimer: ReturnType<typeof setTimeout> | null = null;
let peekFired = false;
function pressCell(c: { x: number; y: number }) {
peekFired = false;
if (!onCellPeek) return;
peekTimer = setTimeout(() => { peekFired = true; onCellPeek(c); }, 450);
}
function releasePress() {
if (peekTimer) clearTimeout(peekTimer);
peekTimer = null;
}
function tapCell(c: { x: number; y: number }) {
if (peekFired) { peekFired = false; return; }
onCellClick?.(c);
}
// Real token art, cropped from the owner's physical set (public/tokens/).
// Anything without an entry falls back to the vector rendering below.
const USE_TOKEN_ART = true;
@@ -137,7 +157,10 @@
x={c.x * CELL} y={c.y * CELL} width={CELL} height={CELL}
class="floor"
role="button" tabindex="-1"
onclick={() => onCellClick?.(c)}
onclick={() => tapCell(c)}
onpointerdown={() => pressCell(c)}
onpointerup={releasePress}
onpointerleave={releasePress}
onkeydown={() => {}}
/>
{/each}