Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/web
Steps to reproduce
- Use a MacBook Pro with a French AZERTY keyboard layout.
- Open T3 Code and keep focus outside the integrated terminal.
- Open the command palette and search for "Change appearance". It advertises Option+Shift+Cmd+A (⌥⇧⌘A).
- Close the palette and press that combination using the key labeled A on the AZERTY keyboard.
- Press it several times to distinguish a missed shortcut from a transition between System and the same effective light/dark mode.
Expected behavior
The advertised shortcut should cycle System → Light → Dark → System, using the A key from the active keyboard layout.
Actual behavior
The advertised shortcut does not appear to change the appearance on my MacBook Pro with an AZERTY keyboard.
Suspected cause (source inspection)
In apps/web/src/keybindings.ts, resolveEventKeys falls back to the letter in KeyboardEvent.code when event.key is not a Latin a–z character. Option can turn a letter into a symbol. On AZERTY, the key labeled A has code KeyQ, so this fallback can resolve it as q rather than a and miss the default mod+alt+shift+a binding.
For example, a synthetic event with key: "Æ", code: "KeyQ", metaKey: true, altKey: true and shiftKey: true exercises this mismatch. This is a unit-test input, not a captured keyboard-event log from my machine.
Related reports
- [Bug]: macOS option-modified explicit keybindings with letter keys fail at runtime #2261: Option-modified letter shortcuts failing on macOS (closed).
- [Bug]: Keyboard shortcuts react to both physical and layout-derived keys #4434 / Limit physical key fallback to non-Latin layout output #4469: Latin layout letters take precedence over physical positions, but the physical fallback remains for Option-generated symbols.
- [Bug]: Keybindings Editor does not respect users keyboard layout #13229: the recorder displays US key positions for non-US punctuation (open); related layout handling, but a different symptom.
I did not find an existing report specifically covering Option-modified A on AZERTY for appearance.cycle.
Impact
Minor bug or occasional failure
Version or commit
Personal build based on upstream v0.0.45; shortcut matching inspected in the upstream source as well.
Environment
macOS, MacBook Pro, French AZERTY keyboard. macOS 26.7.1
Logs or stack traces
Screenshots, recordings, or supporting files
No response
Workaround
Use the command palette → Change appearance and select a mode manually, or assign a shortcut without Option in Settings → Keybindings.
Activity
juliusmarminge commentedon Oct 5, 2026
Note
Grok responding on behalf of Julius.
Triage
Thanks @nbros for the careful report, and for working out which input would trigger it. Current
mainmatches what you describe: on a French AZERTY layout, shortcut matching reads that key asq.What I found
appearance.cycleismod+alt+shift+a(packages/shared/src/keybindings.ts), and it runs from the command palette's keydown listener.resolveEventKeysinapps/web/src/keybindings.tsuses a Latinevent.keyas is. When Option turns the key into a symbol, it falls back to the US letter fromevent.code. On AZERTY, the key labeled A isKeyQand Option+Shift+A producesÆ, so the event resolves toæandqand never matchesa.mod+alt+a) misses for the same reason. Option shortcuts on letters that sit in the same place as on QWERTY (B, N, T) still match. On AZERTY the affected letters are A, Q, Z, and W.Likely fix area
One option is to keep the #4469 rule for unmodified Latin letters and resolve an Option-generated symbol to the letter the active layout prints on that key, rather than the US letter in
event.code. Until then, your workarounds are good: use the command palette, or bind the command without Option in Settings → Keybindings.A maintainer will decide on the fix direction.
nbros commentedon Oct 14, 2026
I implemented the fix direction suggested in the triage in my fork, and it works on macOS with a French AZERTY layout: ⌥⇧⌘A cycles the appearance, and A no longer also matches Q.
navigator.keyboard.getLayoutMap(), so on AZERTYKeyQgivesa. It refreshes the map on window focus. When the Keyboard API is unavailable (some browsers, insecure remote origins), it falls back to the letters seen during ordinary typing without modifiers: the same physical key typesabefore Option turns it intoæ.packages/shared/src/keybindings.tsexposessetKeyboardLayoutLetterResolver(resolver), which the web client registers. InshortcutKeyFromEvent, a Latinevent.keystill wins. Otherwise the layout's base letter comes before the QWERTY letter fromevent.code.resolveEventKeysno longer adds theevent.codeletter alongside, since adding both made AZERTY A also trigger Q.navigator.keyboardhasgetLayoutMap()but is not anEventTarget, soaddEventListener("layoutchange", …)throws. That stopped the app from loading ("T3 Code could not load"). Subscribe only when the method exists; the focus refresh already picks up layout switches.Because the resolver runs in the client, shortcuts follow the keyboard of the machine in front of you, including when connected to a remote server. The fork covers this with unit tests for AZERTY (A vs Q, Option symbols, the fallback without the Keyboard API, and the missing
layoutchange).juliusmarminge commentedon Oct 22, 2026
Checked upstream main b5a226e49c with
vp run dev, isolated copied thread data, and Linux Chromium 154. Opened the command palette, confirmed Change appearance advertises Ctrl+Alt+Shift+A, closed it with focus outside the terminal, and pressed the shortcut three times. The stored appearance changedlight → dark → system; each event hadkey: "a", code: "KeyA", ctrlKey: true, altKey: true, shiftKey: true, metaKey: false.This does not verify the macOS French AZERTY path. This environment has no macOS input source, and the
Æ/KeyQexample in the report is explicitly synthetic. Please confirm the failure on a current upstream build without the fork fix and provide the native keydown values (key,code,metaKey,ctrlKey,altKey,shiftKey) for ⌥⇧⌘A, plus the exact French input-source name and whether this is Electron or a browser (and its version). Keeping this open pending that platform check.nbrosei commentedon Oct 22, 2026
Confirmed on the current official nightly, without the fork fix: ⌥⇧⌘A still doesn't cycle the appearance.
0.1.2-nightly.20261021.3473(built from1688f965), Electron app, Electron 44.9.3 / Chromium 152.0.7977.167, macOS 26.7.1 (25G241)com.apple.keylayout.French("French", not "French – PC"){"key":"Æ","code":"KeyQ","metaKey":true,"ctrlKey":false,"altKey":true,"shiftKey":true}Æ/KeyQreflects real Electron output and isn't synthetic. With Cmd held, Chromium on macOS still applies Option+Shift toevent.key. For reference, macOS'sUCKeyTranslateon this input source gives, forKeyQ:a/Awith ⇧ /æwith ⌥ /Æwith ⌥⇧.shortcutKeyFromEvent/resolveEventKeysare unchanged on currentmain(8acbefefc5):æisn't a Latin letter, so they fall back toKeyQ→qand resolve the event to{æ, q}. That never matchesmod+alt+shift+a.Your Linux/QWERTY check (
key: "a",code: "KeyA") takes the Latinevent.keypath, so it can't reproduce this.juliusmarminge commentedon Oct 22, 2026
The native event confirms the French macOS path. On upstream defb7e6e6b, I ran the web dev app with isolated copied state on Linux Chromium, set the client platform to MacIntel, and replayed the captured Æ/KeyQ event outside the terminal. The palette advertises ⌥⇧⌘A; three presses left appearance unchanged. The a/KeyA control changed it to light. A regression test with the French browser layout map also fails: expected appearance.cycle, received null. Native macOS/Electron input remains unverified on this VM.