From effe17c7290f8e8cb3e5bd99e1f344cbb2d6b757 Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Wed, 23 Sep 2026 11:41:28 -0400 Subject: [PATCH] Phone fixes at a crowded table: focus scroll in viewport coordinates, a wrapping masthead, a slimmer bar Turning the ledger toward a wizard summed a sticky cell's offset, which moves with the scroll; it now uses viewport rectangles and the width the pinned columns cover, so repeated and switched taps land the same. The masthead's actions wrap instead of running off a phone. The phone bar names you, the wizard in focus and the count, with the roster a tap away. The hands row's first cell is pinned with the rest of the turn column. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up --- src/lib/components/Ledger.svelte | 15 ++++++++++----- src/lib/components/MobileBar.svelte | 23 ++++++++++++++++++++++- src/lib/components/Roster.svelte | 3 ++- src/routes/join/[code]/+page.svelte | 3 +++ src/routes/play/+page.svelte | 11 +++++++---- 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/lib/components/Ledger.svelte b/src/lib/components/Ledger.svelte index 26c155c..ba7ce51 100644 --- a/src/lib/components/Ledger.svelte +++ b/src/lib/components/Ledger.svelte @@ -75,17 +75,22 @@ const crowded = $derived(duel.others.length >= 3); - // The focused wizard's columns slide in just past the pinned ones. + // The focused wizard's columns slide in just past the pinned ones. Sticky cells + // report where they are stuck, not where they lie, so the sums are done in + // viewport coordinates: the header's distance from the scroller's edge plus + // the current scroll, less the width the pinned columns always cover. $effect(() => { const who = duel.focus; void duel.focusTick; if (!who || !scroller) return; const th = scroller.querySelector(`th[data-who="${who}"]`); - const pinned = scroller.querySelector('thead th.pin-right'); if (!th) return; - const left = pinned ? pinned.offsetLeft + pinned.offsetWidth : 0; + const pinnedWidth = ['th.turn', 'thead tr.hands th.pin-left', 'thead tr.hands th.pin-right'] + .map((sel) => scroller!.querySelector(sel)?.getBoundingClientRect().width ?? 0) + .reduce((a, b) => a + b, 0); + const left = th.getBoundingClientRect().left - scroller.getBoundingClientRect().left + scroller.scrollLeft - pinnedWidth; const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; - scroller.scrollTo({ left: th.offsetLeft - left, behavior: reduce ? 'auto' : 'smooth' }); + scroller.scrollTo({ left: Math.max(0, left), behavior: reduce ? 'auto' : 'smooth' }); }); @@ -110,7 +115,7 @@ {/each} - + {#each columns as who (who)} left right diff --git a/src/lib/components/MobileBar.svelte b/src/lib/components/MobileBar.svelte index 66bfb00..19d20ff 100644 --- a/src/lib/components/MobileBar.svelte +++ b/src/lib/components/MobileBar.svelte @@ -4,16 +4,28 @@ import { MAX_HP } from '$lib/game/state'; let { duel }: { duel: Duel } = $props(); + + /** Past three wizards the bar names you, the wizard in focus, and the count; the roster is a tap away. */ + const crowded = $derived(duel.others.length >= 3); + const shown = $derived(crowded ? [duel.focus ?? duel.foeId].filter((id) => id !== duel.me) : duel.others); + + function toRoster() { + const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; + document.getElementById('roster')?.scrollIntoView({ behavior: reduce ? 'auto' : 'smooth', block: 'start' }); + } {#if !duel.state.over}
1}> {#if !duel.spectating}{duel.you.name} {duel.you.hp}/{MAX_HP}{/if} - {#each duel.others as id (id)} + {#each shown as id (id)} {@const w = duel.state.wizards[id]} {w.name} {w.hp}/{MAX_HP} {/each} + {#if crowded} + + {/if}
{#if duel.spectating} the gallery @@ -88,6 +100,15 @@ opacity: 0.6; } + .count { + background: none; + border: 0; + padding: 0; + font: inherit; + color: var(--frost); + text-decoration: underline dotted; + } + .gestures { display: flex; gap: 0.5rem; diff --git a/src/lib/components/Roster.svelte b/src/lib/components/Roster.svelte index 3c2b25d..9e77fee 100644 --- a/src/lib/components/Roster.svelte +++ b/src/lib/components/Roster.svelte @@ -26,7 +26,7 @@ } -
+

At the table

    {#each duel.others as id (id)} @@ -53,6 +53,7 @@