Skip to content

feat(focus): let useFocusManager listen on a given event target - #63

Merged
chiefcll merged 2 commits into
mainfrom
focus-manager-event-target
Sep 17, 2026
Merged

chiefcll merged 2 commits into
mainfrom
focus-manager-event-target

Conversation

@chiefcll

@chiefcll chiefcll commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • useFocusManager(keyMap?, target = document): the focus manager binds keydown and keyup on the target it is given instead of always on document.
  • New types, exported from @solidtv/solid and @solidtv/solid/primitives: KeyEventTarget, the two listener methods the focus manager uses, and KeyEventLike, the three event fields it reads (key, keyCode, repeat). The target is typed against KeyEventLike rather than KeyboardEvent on purpose: TypeScript compares callback parameters covariantly, so a host whose events are a subset of KeyboardEvent could not otherwise satisfy the parameter without a cast. Handlers on such a host receive the host's event object.
  • Docs: an "Event Target" section in docs/primitives/useFocusManager.md.

Browser apps are unchanged: the argument defaults to document.

Why

A host without a DOM has nowhere to hand remote presses. The NativeScript port of SolidTV for Apple TV (solid-tv/renderer#199 and its Phase 2 follow-up) reports presses through a KeyBridge that exposes these two methods and raises events shaped like KeyboardEvent. The canvas polyfill there does install a document, but its addEventListener is a no-op without a native emitter, so binding there silently drops every key.

Test plan

  • tests/focusManagerTarget.test.tsx: listeners land on the given target, document events are ignored when a target is given, and cleanup removes the listeners from the target.
  • pnpm test, pnpm build, pnpm lint
  • The NativeScript harness type-checks useFocusManager(undefined, keyBridge) against the built package without a cast.

🤖 Generated with Claude Code

The focus manager bound keydown and keyup on `document`. A host without a
DOM, such as a NativeScript app that reports remote presses through its own
bridge, had nowhere to hand those events. `useFocusManager` now takes the
target as a second argument, typed as the two listener methods it uses, and
still defaults to `document`, so browser apps are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chiefcll
chiefcll force-pushed the focus-manager-event-target branch from b943900 to 49f8c76 Compare September 17, 2026 17:59
The suite runs its files without isolation, so a document key listener
left by another file in the same worker reached the focused element and
failed the assertion on CI. Assert that useFocusManager registers no key
listener on document instead, which is the property under test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chiefcll
chiefcll merged commit 7ebdf27 into main Sep 17, 2026
1 check passed
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