Skip to content

feat(input): touch activation — a tap presses any focusable - #212

Merged
doodlewind merged 1 commit into
mainfrom
feat/touch-activation
Aug 3, 2026
Merged

feat(input): touch activation — a tap presses any focusable#212
doodlewind merged 1 commit into
mainfrom
feat/touch-activation

Conversation

@doodlewind

Copy link
Copy Markdown
Collaborator

Phase 2 follow-through (#209/#210/#211): the pocket-youtube TextField journey exposed that "tap = CIRCLE = click" was only true for components with bespoke recognizers. Now it is true for every Focusable, by construction:

  • one whole-screen lowest-priority tap recognizer per mount — components registering later win taps outright (single-fire priority), so VirtualList/OSK behavior is untouched (52 web goldens byte-exact)
  • down holds active: on the nearest focusable via the hit fact walked through the cursor-hover filter (touchFocusable — one authority for "what can be pressed")
  • pan claims cancel the pressed look; the OSK modal block leaves it inert; no-touch hosts pay nothing

🤖 Generated with Claude Code

docs/TOUCH.md §0 promised that a bare <Focusable onPress> is a button on
touch hosts; only components with bespoke recognizers (VirtualList rows, the
OSK keys) actually delivered it. The pocket-youtube TextField journey caught
the hole: tapping the search field resolved a perfect hit fact and then
nobody turned it into a press.

touch-activation.ts installs ONE whole-screen, lowest-priority tap
recognizer per mount (registered first — gesture priority is
last-registered-first, so every component recognizer beats it): down holds
the active: pressed look on the nearest focusable (input.ts touchFocusable —
the hit fact walked through the same cursor-hover filter, one authority for
"what can be pressed"), tap fires pressNode, a pan claim anywhere cancels
through the standard path, and the OSK's modal block leaves it inert. On
hosts without touch it costs nothing.

Validated: touch-activation 4 (registered in the chain), canonical chain
(the known environmental symbian-runtime failure only), 52 web goldens
byte-exact — single-fire tap priority keeps VirtualList/OSK behavior
untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@doodlewind
doodlewind marked this pull request as ready for review August 3, 2026 08:03
@doodlewind
doodlewind merged commit 8910dac into main Aug 3, 2026
@doodlewind
doodlewind deleted the feat/touch-activation branch August 3, 2026 08:03
doodlewind added a commit that referenced this pull request Aug 4, 2026
Most of the fleet needed NOTHING: every Focusable-driven demo (hero, cards,
chrome, cursor, gallery, notifications, settings, im, note, library, music)
became tappable the moment #212 landed — a tap IS an activation. The new
hero sim journey pins that: four taps on the untouched demo cross the
count>3 gate through the default recognizer alone.

The three raw-button demos get the matching idiom, golden-safely:

- motions: a horizontal swipe turns the page (L/R + triggers unchanged) —
  a whole-screen axis-locked gesture, zero nodes added.
- stats: swipe between the two boards, mirroring LEFT/RIGHT.
- cafe: the status-bar hint is now the touch twin of START — tapping it
  places the order (menu rows already add on tap). The only visual is an
  active: press wash, so untouched frames stay byte-identical.

Not adapted here (different interaction classes, tracked as follow-ups):
zoomlab wants pinch-zoom (a two-contact recognizer the gesture layer does
not offer yet) and ipod-nano IS a click-wheel study.

Validated: canonical chain 0 fail, 54 web goldens byte-exact (the cafe
wrapper is pixel-neutral), Vita3K motions 5/5 + stats 3/3 byte-exact,
hero tap journey.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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