Skip to content

Add level preset buttons + fix mobile canvas hit-test/aspect-ratio#14

Merged
mellonis merged 2 commits into
masterfrom
feat/level-presets
May 18, 2026
Merged

Add level preset buttons + fix mobile canvas hit-test/aspect-ratio#14
mellonis merged 2 commits into
masterfrom
feat/level-presets

Conversation

@mellonis

@mellonis mellonis commented May 18, 2026

Copy link
Copy Markdown
Owner

PR 1 of two staged PRs for #12 — adds the always-visible preset row and the runtime Game.setLevel API it needs. PR 2 (custom panel with sliders + flip animations) lands on top of this. Also includes two small mobile-related fixes that surfaced during testing.

Summary

  • Add three HTML buttons (Beginner / Intermediate / Expert) in #root below the canvas. Clicking switches the game's level at runtime; in-progress game is discarded.
  • Refactor Game's readonly levelFactory: () => Minesweeper constructor parameter into a mutable currentLevel: GameLevel tuple plus a public setLevel(cols, rows, mines) that triggers a fresh game via the existing canvas/widget rebuild path.
  • Fix wrong-cell tap on shrunk canvas: getCanvasCoords now scales the event offset back to the canvas's internal CSS coordinate space, so pointer math is correct when max-width: 100% shrinks the canvas on narrow viewports.
  • Fix aspect-ratio distortion on mobile: drop the inline style.height set by setupCanvas so the CSS height: auto rule can preserve the canvas aspect ratio when its width is constrained.

Test plan

  • npm run build clean (no type errors)
  • npm run lint clean
  • npm test — 19/19 passing
  • Browser at 1400×900 (desktop): all three presets switch at scale 1.0, no shrinking
  • Browser at 380×800 (mobile portrait): Expert renders at 468×296 (aspect 1.580, matches intended), Intermediate at 468×538 (aspect 0.870), Beginner unchanged
  • Browser at 380×800: synthesized tap calculated for cell (0,0) on shrunk Expert correctly reveals the top-left cell and flood-fills around it (verified visually)
  • Out of scope here — Responsive field for small viewports: scale-then-pan with minimap #13's job: at fractional CSS-scale (e.g. ~0.5×) the nearest-neighbor image-rendering: pixelated produces uneven cell sizes. The fix is responsive cell-size sizing + pan-with-snap on small viewports.

mellonis added 2 commits May 18, 2026 19:21
Three HTML buttons in #root (Beginner / Intermediate / Expert) switch the
game's level at runtime. Game's readonly levelFactory is replaced with a
mutable currentLevel tuple plus a public setLevel(cols, rows, mines)
that triggers a fresh game.

Refs #12.
Two issues surfaced on small viewports:

* getCanvasCoords used getBoundingClientRect without scaling the offset
  back to the canvas's internal CSS coordinate space, so taps landed on
  the wrong cell when max-width: 100% shrunk the canvas.

* setupCanvas set style.height inline, overriding the CSS height: auto
  rule, so a shrunk canvas had its width compressed but its height
  unchanged — distorted aspect ratio. Drop the inline height; CSS keeps
  the ratio when max-width: 100% kicks in.
@mellonis mellonis merged commit 11bc89d into master May 18, 2026
1 check passed
@mellonis mellonis deleted the feat/level-presets branch May 18, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant