AZERTY digit hotkeys (2/7/9) broken by letter-key early return
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 74/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- react, typescript
- 領域
- frontend
調査の方向性
match.ts の matchesKeyboardEvent から開始し、event.code Digit フォールバックと並んでいる文字キーの早期リターンを追跡します。報告された AZERTY のケースを useHotkey("Mod+2", callback) で再現し、既存の句読点キーと文字キーの動作を変更しないまま、物理キー Digit2、Digit7、Digit9、Digit0 が一致することを確認します。
索引モデルが issue の本文から書いたものです。
説明
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:
- Switch the OS keyboard layout to French (AZERTY)
- Register
useHotkey("Mod+2", callback) - Press Cmd+2 (physical digit-2 key, unshifted)
- Callback never fires —
event.keyis"é"
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.
- 主要言語
- TypeScript
- スター
- 744
- フォーク
- 49
- 平均マージ
- 1日 16時間
- マージ済み PR(30日)
- 30
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
TanStack/hotkeys のほかの issue
-
Dependency Dashboardオープン
難易度 4/5 3〜5日 初心者へのやさしさ 25/100
メンテナーはふだん 1 日以内に返信
TanStack/hotkeys の issue をすべて見る
似ている issue
-
docs(api): openapi.yaml still documents gif-tools optimize colors as 2-256 instead of 2, 4, 16, 256オープンarea: backend documentation priority: low
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
snapotter-hq/SnapOtter#2919 ·
メンテナーはふだん 1 日以内に返信
-
accepted :+1: bug db/redis
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
beekeeper-studio/beekeeper-studio#4882 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
ready-for-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
konflux-ci/konflux-ui#1630 · コメント 1 件 ·
メンテナーはふだん 2 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 67/100
ahmedkhaleel2004/gitdiagram#233 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
simkimsia/netlify-axi#19 ·
メンテナーはふだん 1 日以内に返信