fix(shortcuts): match single-letter hotkeys by layout-aware key#3525
Open
haacked wants to merge 3 commits into
Open
fix(shortcuts): match single-letter hotkeys by layout-aware key#3525haacked wants to merge 3 commits into
haacked wants to merge 3 commits into
Conversation
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
haacked
marked this pull request as ready for review
July 16, 2026 20:43
Contributor
|
Reviews (1): Last reviewed commit: "fix(shortcuts): match single-letter hotk..." | Re-trigger Greptile |
haacked
added a commit
that referenced
this pull request
Jul 17, 2026
Biome ci flagged the test file as unformatted (lines exceeded print width). Fixes #3525
react-hotkeys-hook 4.6.2 matches a hotkey's letter against both the layout-aware event.key and the physical event.code. For a single-letter shortcut like "mod+i" (Inbox), that means any key at the physical QWERTY-"I" position triggers it — so on a Dvorak layout Cmd+C (whose key sits at that physical slot) navigates to the inbox instead of copying. Every single-letter mod+<letter> shortcut has the same problem on non-QWERTY layouts. Patch the library matcher to derive the key from event.key, falling back to the physical event.code only when a modifier (e.g. macOS Option) turns event.key into a non-alphanumeric glyph. Special keys (arrows, escape, space) and Option shortcuts keep working via the fallback. Generated-By: PostHog Code Task-Id: 570b6a35-794b-45bb-933f-7b54751b014a
The layout-aware matcher fix only patched dist/react-hotkeys-hook.esm.js. Consumers that resolve the package's main field (Vitest's SSR module resolution, Node/Electron require(), Metro/React Native) load dist/index.js, which delegates to the untouched CJS bundles and keeps the physical-code matching bug. Apply the same matcher fix to dist/react-hotkeys-hook.cjs.development.js and dist/react-hotkeys-hook.cjs.production.min.js so every resolution path gets layout-aware matching. The regression test added alongside the original fix was failing in CI for exactly this reason; it now passes. Also fix an unrelated pre-existing quality-check failure: type the codex app-server model/list response as RawModel[] instead of any[].
Biome ci flagged the test file as unformatted (lines exceeded print width). Fixes #3525
haacked
force-pushed
the
posthog-code/fix-hotkeys-layout-aware
branch
from
July 17, 2026 21:08
43eb832 to
d0b6475
Compare
charlesvien
approved these changes
Jul 18, 2026
Contributor
Author
|
/trunk merge |
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.
Problem
On non-QWERTY keyboard layouts (Dvorak, AZERTY, …), single-letter shortcuts fire based on the physical key position rather than the letter the user actually typed. The reported case: selecting text in the chat composer and pressing Cmd+C navigates to the Inbox instead of copying. On Dvorak the key labelled "C" sits at the physical QWERTY-"I" slot, and the Inbox shortcut is
mod+i.Root cause:
react-hotkeys-hook@4.6.2matches a hotkey's key against both the layout-awareevent.keyand the physicalevent.code(mapKey(code)). Formod+iit fires wheneverevent.code === "KeyI", regardless of the logical letter. Every single-lettermod+<letter>shortcut (mod+k,mod+n,mod+b,mod+w,mod+o,mod+r,mod+s,mod+f,mod+j, …) has the same problem. The library version in use has no option to disable code-based matching (useKeyonly exists in v5).Closes #1797
Changes
Patch the
react-hotkeys-hookmatcher (patches/react-hotkeys-hook.patch, wired viapnpmpatchedDependencies) to derive the pressed key from the layout-awareevent.key. It falls back to the physicalevent.codeonly when a modifier (e.g. macOS Option) turnsevent.keyinto a non-alphanumeric glyph or dead key — so special keys (arrows, escape, space) and Option shortcuts keep working, while single-letter shortcuts now match the printed letter on every layout.No call sites change; the fix applies to all current and future
useHotkeysusages.How did you test this?
Added
packages/ui/src/features/command/hotkeysLayout.test.ts, a Vitest regression guard that rendersuseHotkeys("mod+i", …)and dispatches keydown events:Cmd+I(key: "i",code: "KeyI") → fires.Cmd+C(key: "c",code: "KeyI") → does not fire (the bug that hijacked copy).Manually tested by switching my system keyboard layout to Dvorak and confirming Cmd+C now copies selected text instead of navigating to the Inbox. Also re-checked other
mod+<letter>shortcuts on QWERTY to confirm no regression.Automatic notifications
Created with PostHog from a Slack thread