[GH-ISSUE #6278] [Bug]: Inconsistent Keyboard Shortcut Behavior on Non-QWERTY Layouts #51793

Open
opened 2026-04-30 19:23:18 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @jpgaubier on GitHub (Dec 1, 2025).
Original GitHub issue: https://github.com/actualbudget/actual/issues/6278

Verified issue does not already exist?

  • I have searched and found no existing issue

What happened?

When using non-QWERTY keyboard layouts (e.g., Dvorak), application keyboard shortcuts behave inconsistently. Some shortcuts respect the OS-assigned logical key mapping, while others appear to be hard-coded to physical key positions.

How can we reproduce the issue?

Switch system keyboard layout to Dvorak (or any non-QWERTY layout).

Open the application and attempt to use common shortcuts:

Ctrl+Z → Undo works correctly, respecting the OS-assigned key mapping (logical "Z").

Delete → Requires pressing the physical "D" key on the keyboard, rather than the logical "D" key in the layout ("H" in Dvorak).

Where are you hosting Actual?

Docker

What browsers are you seeing the problem on?

Firefox

Operating System

Linux

Originally created by @jpgaubier on GitHub (Dec 1, 2025). Original GitHub issue: https://github.com/actualbudget/actual/issues/6278 ### Verified issue does not already exist? - [x] I have searched and found no existing issue ### What happened? When using non-QWERTY keyboard layouts (e.g., Dvorak), application keyboard shortcuts behave inconsistently. Some shortcuts respect the OS-assigned logical key mapping, while others appear to be hard-coded to physical key positions. ### How can we reproduce the issue? Switch system keyboard layout to Dvorak (or any non-QWERTY layout). Open the application and attempt to use common shortcuts: Ctrl+Z → Undo works correctly, respecting the OS-assigned key mapping (logical "Z"). Delete → Requires pressing the physical "D" key on the keyboard, rather than the logical "D" key in the layout ("H" in Dvorak). ### Where are you hosting Actual? Docker ### What browsers are you seeing the problem on? Firefox ### Operating System Linux
GiteaMirror added the bug label 2026-04-30 19:23:18 -05:00
Author
Owner

@hw0lff commented on GitHub (Dec 19, 2025):

I'm pretty sure the problem is using KeyEvent.code over KeyEvent.key as it is fairly often misused.

Exempt from the linked MDN docs:

For example, the code returned is "KeyQ" for the Q key on a QWERTY layout keyboard, but the same code value also represents the ' key on Dvorak keyboards and the A key on AZERTY keyboards. That makes it impossible to use the value of code to determine what the name of the key is to users if they're not using an anticipated keyboard layout.

To determine what character corresponds with the key event, use the KeyboardEvent.key property instead.

In this case just using Option 2 from react-hotkeys-hooks should fix many of the problems.

When using Hotkeys I associate the function/meaning with the character produced not the position on the keyboard.
So "delete" means D not the position of D in QWERTY.
Same goes for "categories" and C...

As a counter example, if one wants to implemnent movement with the WASD keys, they should use the layout independent KeyEvent.code because the user associates the action with the position of the keys, not the produced character.
In contrast to that using UDLR for up, down, left, right is again layout dependent.

<!-- gh-comment-id:3675421379 --> @hw0lff commented on GitHub (Dec 19, 2025): I'm pretty sure the problem is using [KeyEvent.code](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code) over [KeyEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) as it is fairly often misused. Exempt from the linked MDN docs: > For example, the code returned is "KeyQ" for the Q key on a QWERTY layout keyboard, but the same code value also represents the ' key on Dvorak keyboards and the A key on AZERTY keyboards. That makes it impossible to use the value of code to determine what the name of the key is to users if they're not using an anticipated keyboard layout. > To determine what character corresponds with the key event, use the [KeyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) property instead. In this case just using [Option 2 from react-hotkeys-hooks](https://react-hotkeys-hook.vercel.app/docs/documentation/useHotkeys/ignore-layouts#option-2---listen-to-the-produced-key-layout-dependent) should fix many of the problems. When using Hotkeys I associate the function/meaning with the character produced not the position on the keyboard. So "delete" means D not the position of D in QWERTY. Same goes for "categories" and C... As a counter example, if one wants to implemnent movement with the WASD keys, they should use the layout independent KeyEvent.code because the user associates the action with the position of the keys, not the produced character. In contrast to that using UDLR for up, down, left, right is again layout dependent.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#51793