fix(useHold): resolve taps without depending on key-up#35
Merged
Conversation
On TV platforms that don't reliably emit a key-up for the OK button (notably LG webOS), the only tap path lived in releaseHold gated on the key-up / onEnterRelease event, so rail cards routed through useHold never opened. The hold-to-watchlist gesture was unaffected because it fires from the key-down timer. Resolve tap vs hold from the timer and auto-repeat instead of key-up: - key-down starts the hold timer - an auto-repeat key-down (e.repeat) marks the key held -> timer fires onHold - key-up before the timer fires onEnter immediately (no latency where key-up is delivered) - if neither key-up nor auto-repeat arrives, the timer resolves to a tap -> onEnter, keeping taps working on webOS A fresh key-down also resets stale state so a hold whose key-up was swallowed doesn't wedge the next press. performOnEnterImmediately is preserved. Adds tests covering tap, webOS tap, hold, no-double-fire, recovery, and performOnEnterImmediately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Problem
On LG webOS TVs, rail cards on the home page never open, while the featured film and search results work. Featured/search call
onSelectdirectly insideonEnter(fires on key-down), but rail cards route throughuseHold(to support press-and-hold → watchlist).With
performOnEnterImmediatelydefaulting tofalse, the tap action (onEnter) only ran insidereleaseHold— i.e. it waited for the OK button's key-up /onEnterReleaseevent. webOS remotes don't reliably emit a key-up for the OK button on many LG models, soreleaseHoldnever ran and the card never opened. The hold-to-watchlist gesture was unaffected because it fires from the key-down timer.The root flaw: the primary action was gated behind a key-release event that TV remotes don't guarantee.
Fix
Resolve tap vs. hold from the timer and auto-repeat rather than from key-up, in
src/primitives/useHold.ts:e.repeat, which focusManager already passes to the handler) marks the key as still held → the timer resolves to a hold →onHold.onEnterfires immediately (no latency on platforms that deliver key-up).onEnterafterholdThresholdms. This is the key-up-independent path that keeps taps working on webOS.A fresh key-down also resets stale state, so a hold whose key-up was swallowed doesn't wedge the next press (a pure-timer version would dead-end).
performOnEnterImmediatelyis preserved unchanged for existing consumers.Tradeoffs
holdThresholdms latency only when key-up is missing (webOS); where key-up is delivered, taps stay instant.Tests
Adds
tests/useHold.spec.ts(6 cases): tap-with-keyup, webOS tap (no keyup), hold-with-repeat +onRelease, no-double-fire, recovery after a keyup-less hold, andperformOnEnterImmediately. All pass. No new typecheck errors.Reviewer notes
This fixes the library for every webOS consumer of
useHold. Worth confirming on an LG unit by loggingstartHoldvsreleaseHoldon OK — ifstartHoldfires butreleaseHolddoesn't, that's the definitive signature of this bug.🤖 Generated with Claude Code