Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

AZERTY digit hotkeys (2/7/9) broken by letter-key early return

Closed
#149 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
74/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
react, typescript
Domain
frontend

Research direction

Start in match.ts at matchesKeyboardEvent and trace the letter-key early return alongside the event.code Digit fallback. Reproduce the reported AZERTY cases through useHotkey("Mod+2", callback), then verify that the physical Digit2, Digit7, Digit9, and Digit0 keys match while existing punctuation and letter-key behavior remains unchanged.

Written by the indexing model from the issue text.

Description

TanStack Hotkeys version

v0.8.0 (via @tanstack/react-hotkeys v0.10.0)

Framework/Library version

React 18

Describe the bug and the steps to reproduce it

On a French AZERTY keyboard, the unshifted number row produces accented letters instead of digits for several keys: 2→é, 7→è, 9→ç (the rest, e.g. 1→&, 3→", 4→', produce punctuation). Because of this, useHotkey("Mod+2", callback) never fires — event.key is "é", not "2".

The library already handles this correctly for AZERTY digits that map to punctuation (Mod+1, Mod+3, ...): they fall through to the event.code "Digit" fallback in matchesKeyboardEvent (match.ts). But 2/7/9 map to event.key values that are themselves single Unicode letters (é/è/ç), and the letter-key branch returns early before that fallback is ever reached:

// match.ts
const eventKey = normalizeKeyName(event.key); // "é" -> "É"
const hotkeyKey = parsed.key;                 // "2"
if (eventKey !== "Dead" && eventKey.length === 1 && hotkeyKey.length === 1) {
  if (eventKey.toUpperCase() === hotkeyKey.toUpperCase()) return true;
  if (isSingleLetterKey(eventKey) && (/^[A-Za-z]$/.test(eventKey) || !event.altKey)) return false;
  //  ^ isSingleLetterKey uses /^\p{Letter}$/u, which matches "É" too — this
  //    returns false and NEVER reaches the event.code "Digit" fallback below.
}
if (event.code && (eventKey === "Dead" || eventKey.length === 1 && hotkeyKey.length === 1)) {
  if (event.code.startsWith("Digit")) { /* this never runs for É/È/Ç */ }
  ...
}

Steps to reproduce:

  1. Switch the OS keyboard layout to French (AZERTY)
  2. Register useHotkey("Mod+2", callback)
  3. Press Cmd+2 (physical digit-2 key, unshifted)
  4. Callback never fires — event.key is "é"

For comparison, useHotkey("Mod+1", callback) works, because event.key on that key is "&" (punctuation, not a Unicode letter), so it skips the early-return branch and correctly falls through to the event.code check.

All AZERTY digit keys whose unshifted glyph is a letter are affected:

Hotkey event.key on AZERTY event.code Matched?
Mod+1 & Digit1 Yes
Mod+2 é Digit2 No
Mod+3 " Digit3 Yes
Mod+4 ' Digit4 Yes
Mod+5 ( Digit5 Yes
Mod+6 - Digit6 Yes
Mod+7 è Digit7 No
Mod+8 _ Digit8 Yes
Mod+9 ç Digit9 No
Mod+0 à Digit0 No

The fix is likely to make the letter-key early-return only fire when event.code doesn't itself resolve to a Digit*/Key* match — i.e. give the event.code fallback priority whenever it's available, rather than letting the event.key-based letter check short-circuit first. This is the same root cause as #63 (Alt+punctuation on macOS): a modifier can remap the unshifted glyph on a physical key to something that isn't the "expected" character class, and event.key-first matching keeps special-casing one remap (dead keys) without generalizing to others (AZERTY digit-row letters).

Do you intend to try to help solve this bug with your own PR?

None

Terms & Code of Conduct
  • I agree to follow this project's Code of Conduct
  • I understand that if my bug cannot be reliably reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.
Dominant language
TypeScript
Stars
733
Forks
47
Avg merge
18h 46m
Merged PRs (30d)
9

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from TanStack/hotkeys

All issues in TanStack/hotkeys

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.