Add SteadyHands touch-first minigame to minigames-kit

Add SteadyHands touch-first minigame to minigames-kit

#13 in Riparion/riparion-retro — merged 2026-06-09

Summary

Adds SteadyHands, a continuous precision-tracing minigame to minigames-kit. A target reticle wanders a seeded path; the player drags to keep an offset cursor (rendered above the fingertip, sniper-scope pattern) on it, so the finger never occludes the target. Built mobile-first for touchscreens. Accuracy = fraction of the run held on target; result struct leaves scoring to the host (mirrors TimingBar's contract).

Kit component only — game-wiring into oregon-trail is a deliberate follow-up. Bumps minigames-kit 0.1.2 → 0.1.3.

What's included

  • src/steady_hands.rs — pure helpers (target_position, on_target, accuracy/streak accumulation), SteadyHandsResult, the SteadyHands component with touch drag handling, and 9 unit tests.
  • examples/steady_hands.rs — standalone demo (just steady-hands).
  • Feature/module/example registration + justfile recipes.

Verified end-to-end under phone-emulated Playwright

Driving the example under a 390×844 iPhone profile (touch via CDP) surfaced three real bugs, all fixed here:

  1. Unreachable targets — the offset cursor can only reach y = 1 − cursor_offset, but the target drifted lower. Capped the target's vertical band to the cursor's reach (guarded by a new unit test).
  2. Stale pointer rect — the Tailwind Play CDN applies utilities lazily on the first DOM mutation, reflowing the field in the same frame as get_client_rect (justify-center caused a 186px jump that froze the cursor's Y). Fixed by styling layout inline so it's stable from first paint; captured rect now matches live within 1px.
  3. Touch-move correlation in the driver (needs a stable touch-point id).

Final run: FOLLOW "Held steady — 65%", IDLE "Slipped — 0%". 9 host tests pass, wasm example builds, clippy clean, workspace builds.

🤖 Generated with Claude Code

Last updated 2026-06-10