feat(dial): snap to the closest altitude on drag release #31

Merged
benstull merged 1 commits from worktree-session-0037-altitude-snap-on-release into main 2026-06-30 17:51:39 +00:00
Owner

When the operator drags the altitude dial (vs. tapping a label), releasing between altitudes now auto-scrubs the short way to the closest altitude and settles there — a grab-and-release always lands on a discrete altitude, just like a click. Previously onDialUp held the half-finished blend wherever the knob stopped.

  • onDialUp: a real turn (moved >= 6) now calls autoScrub(Math.round(pos)); tap path unchanged; reduced motion handled by autoScrub.
  • New altitude-lock e2e: a partial drag settles on an integer altitude after release (TDD red→green).
  • Full altitude-lock (14) + a11y + i18n e2e suites green.

Session 0037. Static-Cloudflare app (exempt from §9/PPE) — needs operator redeploy after merge.

🤖 Generated with Claude Code

When the operator drags the altitude dial (vs. tapping a label), releasing between altitudes now auto-scrubs the short way to the **closest** altitude and settles there — a grab-and-release always lands on a discrete altitude, just like a click. Previously `onDialUp` held the half-finished blend wherever the knob stopped. - `onDialUp`: a real turn (`moved >= 6`) now calls `autoScrub(Math.round(pos))`; tap path unchanged; reduced motion handled by `autoScrub`. - New `altitude-lock` e2e: a partial drag settles on an integer altitude after release (TDD red→green). - Full altitude-lock (14) + a11y + i18n e2e suites green. Session 0037. Static-Cloudflare app (exempt from §9/PPE) — needs operator redeploy after merge. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
benstull added 1 commit 2026-06-30 17:51:33 +00:00
A drag is a way of grabbing the altitude dial, not a free-standing encoder
detent. Until now onDialUp held the live blend wherever the knob stopped (the
"no auto-complete" model), so a grab-and-release could leave the experience
parked mid-morph between two altitudes.

Now a real turn (moved >= 6) auto-scrubs the short way to Math.round(pos) and
settles there (frac 0 locks) — a grab-and-release always lands on a discrete
altitude, exactly like a tap or label click. The tap path (moved < 6 ->
jumpToScale) is unchanged, and reduced motion is handled by autoScrub (jump to
target, no tween).

Adds an altitude-lock e2e asserting a partial drag settles on an integer
altitude after release. Full altitude-lock (14) + a11y + i18n suites green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
benstull merged commit 5696b94328 into main 2026-06-30 17:51:39 +00:00
Sign in to join this conversation.