feat(osk): TextField — the editable activation semantic - #210
Merged
Conversation
Tapping a text field did nothing (the hardware-day finding): the OSK was button-summoned app glue, not a semantic. The field and its keyboard are one vertical, so both now live in the osk module: - osk-controller.ts: the editing session extracted JSX-free (createOsk, verbatim) — bun test imports it directly, and the caret/commit/cancel contract gets its own unit suite (registered in the canonical chain). - TextField (osk.tsx): a Focusable whose ACTIVATION — touch tap via the hit fact, d-pad CIRCLE, cursor click, one pressNode pipeline — summons the system OSK bound to `value`/`onInput`; commit fires `onSubmit` and closes. The panel docks through the overlay Portal (hitPass keeps the empty layer transparent to bounds facts; the panel itself claims normally) with the OSK's own button+gesture modality. `ref` exposes the controller for shortcut keys (a △ binding calls `ref.open()`). The tap→type→search integration is pinned at the app level by the pocket-youtube sim journeys (the framework's JSX view layer is compiled, not bun-test-importable — the established boundary). Validated: osk-controller 7 (plain AND browser), im-sim 11, canonical chain (one pre-existing environmental failure: symbian-runtime's freshly linked executable is being held by macOS provenance on this machine — fails identically on the clean baseline, tracked separately), 52 web goldens byte-exact. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
doodlewind
marked this pull request as ready for review
August 3, 2026 07:52
This was referenced Aug 3, 2026
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.
Phase 2, change B (after #209). The hardware-day gap: tapping the search field did nothing, because "summon the keyboard" was a button binding in app code rather than a semantic the platform owns.
What changes
Any modality's activation — touch tap (via the #209 hit fact), d-pad CIRCLE, cursor click, one
pressNodepipeline — opens the system OSK bound to the field. Commit firesonSubmitand closes. Zero osk plumbing in apps;refexposes the controller for shortcut buttons (△).osk-controller.ts: the editing session extracted JSX-free (verbatimcreateOsk) so its caret/commit/cancel contract is directly unit-tested (7 cases, plain + browser, registered in the canonical chain)TextFieldinosk.tsx: field box + overlay-Portal-docked panel (hitPassfrom feat(input): touch hit facts — bounds hits resolved by the host, carried per contact #209 makes this composition work)createOsk/<Osk>placement-controlled usage (apps/im) unchangedNote
The tap→type→search integration lands as pocket-youtube sim journeys in the adoption PR (the JSX view layer is compiled, not bun-test-importable — the established boundary). One pre-existing environmental failure on this machine (symbian-runtime, macOS provenance holding a freshly linked test executable — fails identically on clean main) is unrelated.
🤖 Generated with Claude Code