Skip to content

fix(ui): stop shortcuts from eating keystrokes in text fields#38

Merged
danielss-dev merged 1 commit into
mainfrom
fix/shortcuts-eat-text-field-keys
Jul 7, 2026
Merged

fix(ui): stop shortcuts from eating keystrokes in text fields#38
danielss-dev merged 1 commit into
mainfrom
fix/shortcuts-eat-text-field-keys

Conversation

@danielss-dev

Copy link
Copy Markdown
Owner

Summary

User report: typing in the file-search box still triggered keyboard shortcuts, so capital letters (which arrive as Shift+letter) could not be typed.

Root cause: Pierre's file tree renders in an open shadow root, and keydown events from its in-tree search box are retargeted — window-level listeners see the shadow host as e.target, so every e.target.closest('input…') guard in the app failed and view shortcuts (j/k, Shift+J/K, s, d, space…) swallowed the keystrokes.

  • Add eventInside() + EDITABLE_SELECTOR to lib/keys.ts — walks composedPath() (which crosses open shadow roots) with a closest() fallback, duck-typed so the module stays unit-testable in node.
  • Use it in every window/document-level key handler: the global dispatch in App.tsx, Review, LocalChanges, WorkspaceReview, the / focus-search handler in Commits, and MergeResolver's [/]/arrow stepping (which had no text-field guard at all despite its comment).
  • Tighten the text-field rule to only Mod+… combos may act while typing: isPlainKey() now flags any binding without Mod, so Shift-only and Alt-only bindings (typing: capitals, composed characters) never fire in text fields.

Test plan

  • pnpm exec tsc --noEmit — clean
  • pnpm exec vitest run — 200/200 passing, including new tests for the isPlainKey semantics and eventInside shadow-DOM retargeting/fallback paths
  • pnpm run build — succeeds

🤖 Generated with Claude Code

Pierre's file tree renders in an open shadow root, so keydowns from its
in-tree search box reach window listeners with e.target retargeted to the
shadow host — every e.target.closest('input…') guard missed it and view
shortcuts (j/k, Shift+J/K, s, d, space…) swallowed typing; capitals were
the visible casualty since they arrive as Shift+letter.

Add eventInside() to lib/keys.ts (walks composedPath so open shadow roots
are seen through, with a closest() fallback) plus a shared
EDITABLE_SELECTOR, and use them in every window/document-level key
handler (App global dispatch, Review, LocalChanges, WorkspaceReview,
Commits '/' focus, MergeResolver stepping — which had no text-field guard
at all).

Also tighten the text-field rule to "only Mod+ combos may act":
isPlainKey() now flags any binding without Mod, so Shift-only and
Alt-only bindings never fire while typing.
@danielss-dev danielss-dev merged commit 1258569 into main Jul 7, 2026
2 checks passed
@danielss-dev danielss-dev deleted the fix/shortcuts-eat-text-field-keys branch July 7, 2026 17:01
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