Add level preset buttons + fix mobile canvas hit-test/aspect-ratio#14
Merged
Conversation
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.
This was referenced May 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR 1 of two staged PRs for #12 — adds the always-visible preset row and the runtime
Game.setLevelAPI 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
#rootbelow the canvas. Clicking switches the game's level at runtime; in-progress game is discarded.Game'sreadonly levelFactory: () => Minesweeperconstructor parameter into a mutablecurrentLevel: GameLeveltuple plus a publicsetLevel(cols, rows, mines)that triggers a fresh game via the existing canvas/widget rebuild path.getCanvasCoordsnow scales the event offset back to the canvas's internal CSS coordinate space, so pointer math is correct whenmax-width: 100%shrinks the canvas on narrow viewports.style.heightset bysetupCanvasso the CSSheight: autorule can preserve the canvas aspect ratio when its width is constrained.Test plan
npm run buildclean (no type errors)npm run lintcleannpm test— 19/19 passingimage-rendering: pixelatedproduces uneven cell sizes. The fix is responsive cell-size sizing + pan-with-snap on small viewports.