mirror of
https://github.com/tiennm99/sokoban.git
synced 2026-10-11 03:13:52 +00:00
6.4 KiB
6.4 KiB
Phase 01 — Tighten Mobile Vertical Layout
Priority: P1
Status: pending
Mode: CSS only, gated @media (pointer: coarse). Zero JS, zero markup.
Context Links
- Review:
plans/reports/ui-ux-260428-2218-mobile-dpad-board-spacing.md - Prior fix that established the current flex layout: commit
c80b9ce(kill footer mistouch / dock-board overlap). - Footer-on-desktop restore: commit
d5b8aef.
Overview
Close the visible "too far" band between board and D-pad on phones by:
- Anchoring the board to the bottom of
.board-wrap(R1 — main win). - Removing redundant bottom padding on
#app(R2 — dock owns its own bottom inset). - Tightening the
.gameflex gap (R3).
All three are CSS-only and live behind one media query so desktop is untouched.
Key Insights (from review report)
- Seam between board and dock = exactly
16px(.game gap) — fine on its own. - Real culprit:
<Board>is fixed-pixel and renders top-left insideflex:1.board-wrap. Short puzzles leave ~319px of invisible dead space below the board on a Pixel 7. - Compounding:
#appadds 24px bottom padding under the dock that already pads12px + safe-area. - Combined fix moves the seam to ~10px.
Requirements
Functional
- F1. On
@media (pointer: coarse)the puzzle board's bottom edge sits within ~12px of the dock top edge for puzzles that fit the viewport. - F2. On
@media (pointer: fine)(desktop) the layout is pixel-identical to currentmain. - F3. Tall puzzles still scroll inside
.board-wrapwithout overlapping the dock.
Non-functional
- N1. No JS changes.
- N2. No new files; edit in place.
- N3. Touch targets unchanged (D-pad arrows stay 56px, action buttons stay 44px).
Architecture
Affected layers:
#app ← R2 (mobile padding override)
└── .game ← R3 (mobile gap override)
├── .hud
├── .board-wrap ← R1 (mobile flex-end anchoring) + max-width tweak
│ └── <Board> (fixed-pixel, untouched)
└── <MobileControls> (.mobile-dock — untouched in this phase)
Related Code Files
Modify
src/app.css— add coarse-pointer override on#apppadding.src/views/GameView.svelte— add coarse-pointer overrides on.board-wrap(flex-end anchoring + max-width) and.game(gap 10px).
Read for context (do not modify)
src/views/MobileControls.svelte— confirms dock keeps its ownpadding-bottom: 12px + env(safe-area-inset-bottom).
Create
- None.
Delete
- None.
Implementation Steps
1. src/app.css — R2 mobile padding override
After the existing #app rule, add:
@media (pointer: coarse) {
#app {
padding: 12px 12px 0;
}
}
Rationale: dock already pads 12px + env(safe-area-inset-bottom). Doubling was wasteful. Lateral 12px is plenty around the board.
2. src/views/GameView.svelte — R1 board anchoring + R3 gap
Inside the existing <style> block, append (or merge into the existing @media (pointer: coarse) rule that hides .desktop-actions):
@media (pointer: coarse) {
.game { gap: 10px; }
.board-wrap {
display: flex;
align-items: flex-end;
justify-content: center;
max-width: calc(100vw - 24px); /* matches new #app lateral padding */
}
}
Rationale:
align-items: flex-endpins the inner<Board>to the bottom edge of the wrapper, so dead space accumulates above (invisible behind HUD) instead of below (between board and dock).justify-content: centerpreserves horizontal centering already implied by<Board>'s container; explicit for clarity.max-widthtightens with the new 12px lateral#apppadding (was 48px-aware).
3. Verify build
npm run build
Expect zero errors and similar bundle size.
4. Smoke-test in dev server (manual, browser)
npm run dev
Then in DevTools:
- Toggle device toolbar → Pixel 7 (412×915).
- Open Microban 1. Confirm dock sits ~10-16px below board.
- Open a tall finale level (level index 154 — "The Dungeon"). Confirm board scrolls; player visible after initial scroll position settles. If first frame is jarring, log and address in follow-up phase.
- Disable device toolbar → desktop. Confirm pixel-identical layout to pre-change
main(compare via screenshot or hard refresh).
Todo List
- Add
@media (pointer: coarse)rule tosrc/app.css(R2). - Add/merge
@media (pointer: coarse)rule insrc/views/GameView.sveltefor.gamegap and.board-wrapanchoring (R1 + R3). npm run build— must succeed clean.- Manual smoke test on Microban 1 (short) + a finale level (tall) via DevTools mobile preset.
- Manual smoke test on desktop — no regression.
- Stage + commit (await user instruction).
Success Criteria
npm run buildpasses.- Visual: on coarse-pointer viewport, Microban 1 dock sits within ~16px of board bottom.
- Desktop unchanged.
- No new console warnings.
Risk Assessment
| Risk | Likelihood | Mitigation |
|---|---|---|
| Tall puzzle initial scroll lands at bottom and disorients player | Low-Med | Most levels fit the viewport on phones; for those that don't, player sprite is usually near targets which sit on the board interior. If reports come in, follow-up with scrollTop = (scrollHeight - clientHeight) JS only when overflow exists. |
| Landscape orientation regresses | Low | Landscape on phones already has narrow vertical room; flex-end still safer than top-aligned. Spot-check during smoke test. |
| Safe-area insets on iOS still leave gap because dock padding compounds | Very low | padding: 12px 12px 0 keeps top inset; bottom belongs to dock; horizontally we use 12px literal (no horizontal safe-area inset on most phones in portrait). |
Security Considerations
None. CSS-only change.
Next Steps
- Verify visually on a real device (PWA install) once merged.
- If R1 trade-off is felt on tall levels, follow-up phase to apply
align-items: flex-endonly when.board-wrapheight >= board height (likely needs a small JS class toggle on resize). - Consider R4 (arrow size 56→52) only if more vertical room is wanted later.
Unresolved Questions
- Should we add
scroll-behavior: smoothon.board-wrapto soften the initial bottom-scroll on tall levels? Defer until visual feedback. - Action button height — keep 44px (current) or revisit? Out of scope this phase.