Skip to content

feat(input): hold keys and buttons to repeat - #94

Merged
rowan-m merged 1 commit into
mainfrom
feat/hold-to-repeat
Sep 25, 2026
Merged

rowan-m merged 1 commit into
mainfrom
feat/hold-to-repeat

Conversation

@rowan-m

@rowan-m rowan-m commented Sep 25, 2026

Copy link
Copy Markdown
Owner

Holding a key or on-screen button now repeats its action, and keys and buttons share one interaction lifecycle with pointers.

Behaviour

  • Press: a key or button starts an interaction, just like a pointer down. The pin shows, the view stays in low-res preview, and the action runs once.
  • Hold: after 400ms the action repeats every 50ms (HOLD_DELAY_MS / HOLD_REPEAT_MS). Keys use this timer rather than the OS auto-repeat, so keys and buttons feel the same.
  • Release: once every pointer, key and button is released, the interaction finishes straight away. That means a new reference if the view moved, otherwise a full-res render. Previously each key press fell back to the 200ms debounce.
  • Scope: movement, zoom, rotation, hue and colour-cycling buttons repeat. Screenshot, share, fullscreen and ? don't.

Details

  • state.held tracks held keys and buttons. isInteracting(state) (pointers or held) replaces the pointer-only checks in Fractious, Renderer and the auto-reload busy check.
  • Keys are matched on e.code, so a Shift change between press and release can't leave a key stuck. Window blur releases everything.
  • Buttons use pointer capture. A keyboard-activated button click (Enter/Space) still does a single step, and long-press context menus are suppressed.
  • The help panel gets a "Hold a key or on-screen button to repeat it" line, and AGENTS.md is updated.

Checks: format, eslint, clippy, WGSL lint, depcruise, wasm + vitest tests (new hold tests) and size budgets pass (main JS 13.86 kB). Not verified here with real touch or mouse input: please try it on the preview, especially long-press on mobile and the repeat speed.

…fecycle

Pressing a shortcut key or on-screen control button now starts an interaction
like a pointer down: the pin shows and the view stays in low-res preview. The
action repeats while held (after 400ms, every 50ms) on our own timer rather than
the OS key auto-repeat, and the interaction finishes (new reference or full-res
render) once every pointer, key and button is released. Held controls live in
state.held, and isInteracting() replaces the pointer-only checks. Releases are
matched by physical key so Shift changes can't leave a key stuck, and everything
is released if the window loses focus.
@github-actions

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit e2099c7):

https://fractious-deep--pr94-feat-hold-to-repeat-zjo3wzsu.web.app

(expires Fri, 02 Oct 2026 09:59:08 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 348393a9746312ebab7a45ce5eba16e6d119af34

@rowan-m
rowan-m merged commit b876e56 into main Sep 25, 2026
2 checks passed
@rowan-m
rowan-m deleted the feat/hold-to-repeat branch September 25, 2026 10:36
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