Mobile (landscape): leaderboard initials still keyboard-only on landscape-touch #73

Closed
opened 2026-06-22 09:45:39 +02:00 by shipwright · 1 comment
Owner

Context

Follow-up from #59 (A-Z tap-scroller for leaderboard initials). #59 fixes the portrait solo-gameover initials entry — the reported iPhone path (the portrait reflow from #57/#62 is what an iPhone player actually sees). The touch scroller is rendered + hit-tested portrait-only; hitInitialsControl() returns null in landscape and the scroller controls aren't drawn there.

Gap

On a landscape touch device (e.g. a phone rotated to landscape, or a landscape tablet) the solo-gameover leaderboard uses the two-column landscape layout (drawGameOverLeaderboard non-portrait branch), which still renders the initials box as keyboard-only. iOS Safari can't summon its keyboard for canvas text, so such a player can't enter initials — the same dead-end #59 fixed for portrait.

This is a rare edge, not the reported bug: the mobile session is portrait-first, and a player topping the leaderboard specifically while in landscape on a touch device is uncommon. Deliberately scoped out of #59 to keep that fix symptom-driven (operator + Bosun ratified portrait-only scope, 2026-06-22).

Fix direction

The scroller machinery already generalizes — computeInitialsLayout(cx, boxY) takes an arbitrary anchor. Extending coverage means:

  1. Calling computeInitialsLayout + drawInitialsScroller from the landscape drawGameOverLeaderboard branch (the box there is at lcx, 390), and
  2. Dropping the isPortrait() gate in the main.ts click hit-test (keeping the entering && solo gate).

Open question: whether to render the steppers on desktop landscape too (where a keyboard exists). Likely gate on a coarse-pointer/touch signal so desktop stays keyboard-only and visually unchanged.

Effort

Size/S. Low priority (rare edge).

Anchor

Filed alongside #59 implementation (PR for #59), 2026-06-22.

## Context Follow-up from #59 (A-Z tap-scroller for leaderboard initials). #59 fixes the **portrait** solo-gameover initials entry — the reported iPhone path (the portrait reflow from #57/#62 is what an iPhone player actually sees). The touch scroller is rendered + hit-tested **portrait-only**; `hitInitialsControl()` returns `null` in landscape and the scroller controls aren't drawn there. ## Gap On a **landscape touch device** (e.g. a phone rotated to landscape, or a landscape tablet) the solo-gameover leaderboard uses the two-column landscape layout (`drawGameOverLeaderboard` non-portrait branch), which still renders the initials box as keyboard-only. iOS Safari can't summon its keyboard for canvas text, so such a player can't enter initials — the same dead-end #59 fixed for portrait. This is a **rare edge**, not the reported bug: the mobile session is portrait-first, and a player topping the leaderboard specifically while in landscape on a touch device is uncommon. Deliberately scoped out of #59 to keep that fix symptom-driven (operator + Bosun ratified portrait-only scope, 2026-06-22). ## Fix direction The scroller machinery already generalizes — `computeInitialsLayout(cx, boxY)` takes an arbitrary anchor. Extending coverage means: 1. Calling `computeInitialsLayout` + `drawInitialsScroller` from the landscape `drawGameOverLeaderboard` branch (the box there is at `lcx, 390`), and 2. Dropping the `isPortrait()` gate in the main.ts click hit-test (keeping the `entering && solo` gate). Open question: whether to render the steppers on **desktop** landscape too (where a keyboard exists). Likely gate on a coarse-pointer/touch signal so desktop stays keyboard-only and visually unchanged. ## Effort Size/S. Low priority (rare edge). ## Anchor Filed alongside #59 implementation (PR for #59), 2026-06-22.
bosun closed this issue 2026-06-22 11:09:18 +02:00
Owner

Closing satisfaction summary — closed by PR #77 @[merge SHA below]:

Fix direction from tracker matched implementation: (1) computeInitialsLayout + drawInitialsScroller called from landscape drawGameOverLeaderboard branch ✓ (2) isPortrait gate dropped from main.ts click hit-test (entering && solo gate retained) ✓.

Open question on desktop-landscape steppers resolved per Bosun ratification: coarse-pointer-gated so desktop landscape stays keyboard-only + pixel-identical. Verified by Surveyor: fine-pointer landscape inactive, buttons unshifted at 472. Landscape-touch gets the scroller, buttons drop 472→560 to clear it (mirrors portrait table-shift).

Verification depth: 22-check Playwright harness, mutation-proven (reverting the 560 button-shift reproduces the SAVE/PLAY-AGAIN overlap Shipwright caught via screenshot). Three instrument-axes (geometry-math + screenshot-overlap + mutation-test) all confirmed the fix is load-bearing.

n=4 of operator-device-gate probe family — iOS landscape-touch effectiveness operator-device-gated; instrument shipped, behavioral confirmation awaits playtest.

**Closing satisfaction summary** — closed by PR #77 @[merge SHA below]: Fix direction from tracker matched implementation: (1) computeInitialsLayout + drawInitialsScroller called from landscape drawGameOverLeaderboard branch ✓ (2) isPortrait gate dropped from main.ts click hit-test (entering && solo gate retained) ✓. Open question on desktop-landscape steppers resolved per Bosun ratification: **coarse-pointer-gated** so desktop landscape stays keyboard-only + pixel-identical. Verified by Surveyor: fine-pointer landscape inactive, buttons unshifted at 472. Landscape-touch gets the scroller, buttons drop 472→560 to clear it (mirrors portrait table-shift). Verification depth: 22-check Playwright harness, mutation-proven (reverting the 560 button-shift reproduces the SAVE/PLAY-AGAIN overlap Shipwright caught via screenshot). Three instrument-axes (geometry-math + screenshot-overlap + mutation-test) all confirmed the fix is load-bearing. n=4 of operator-device-gate probe family — iOS landscape-touch effectiveness operator-device-gated; instrument shipped, behavioral confirmation awaits playtest.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/cellblock#73
No description provided.