marcstraube / marcstraube/zappzarapp-node-browser-utils
fix(keyboard): ignoreEditableTargets misses inputs inside open Shadow DOM
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
Summary
ignoreEditableTargets (added in #164) reads event.target to decide whether focus is in an editable element. For events that cross an open Shadow DOM boundary, the browser retargets event.target to the shadow host, so a document-bound shortcut listener sees the host element — not the <input> the user is typing in. The shortcut can therefore still fire (and preventDefault) while typing into an input nested inside a web component's shadow root.
Reproduction (real browser)
<my-editor>
#shadow-root (open)
<input>
</my-editor>
With ShortcutManager.on(KeyboardShortcut.key('r'), rotate, { ignoreEditableTargets: true }):
- typing
rin the<input>→event.targetat the document listener is<my-editor>→isEditableTargetreturnsfalse→ the shortcut fires. Expected: skipped.
Proposed fix
Resolve the deepest target via event.composedPath()[0] instead of event.target in the dispatch path before calling isEditableTarget. In the non-shadow case composedPath()[0] === event.target, so the change is behavior-neutral there.
Caveats to handle:
- Closed shadow roots:
composedPath()excludes their internal nodes and yields the host — the best obtainable signal; document the residual gap. -
noUncheckedIndexedAccess:composedPath()[0]is typedEventTarget | undefined; widenisEditableTarget's parameter accordingly (theinstanceof Elementguard already handlesundefined).
Why this is a separate issue
It cannot be covered by the current happy-dom unit tests — happy-dom does not retarget shadow-boundary events (it already exposes the inner <input> as event.target), so the bug is neither reproducible nor coverable there. Closing this properly needs real-browser test infrastructure (e.g. Playwright), which the repo does not yet have. Adding that harness is part of the work here.
Acceptance criteria
- A bare-key shortcut with
ignoreEditableTargets: truedoes not fire while typing in an<input>nested in an open shadow root. - No regression for light-DOM editable-target detection.
- Real-browser test coverage for the shadow-DOM case.
Context
Documented as a known limitation in documentation/keyboard.md. Follow-up to #164.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the ignoreEditableTargets dispatch path and isEditableTarget implementation, then review documentation/keyboard.md and the existing happy-dom tests. Add the real-browser test infrastructure described in the issue and verify the shadow-DOM, light-DOM, and closed-shadow-root acceptance criteria.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend, testing-qa, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100