diff --git a/apps/client/src/services/shortcuts.spec.ts b/apps/client/src/services/shortcuts.spec.ts index f2170da30..c8f2d9b64 100644 --- a/apps/client/src/services/shortcuts.spec.ts +++ b/apps/client/src/services/shortcuts.spec.ts @@ -62,9 +62,10 @@ describe("shortcuts", () => { }); describe("keyMatches", () => { - const createKeyboardEvent = (key: string, code?: string) => ({ + const createKeyboardEvent = (key: string, code?: string, extraProps: Partial = {}) => ({ key, - code: code || `Key${key.toUpperCase()}` + code: code || `Key${key.toUpperCase()}`, + ...extraProps } as KeyboardEvent); it("should match regular letter keys using key code", () => { @@ -102,17 +103,23 @@ describe("shortcuts", () => { consoleSpy.mockRestore(); }); + it("should match azerty keys", () => { + const event = createKeyboardEvent("A", "KeyQ"); + expect(keyMatches(event, "a")).toBe(true); + expect(keyMatches(event, "q")).toBe(false); + }); + it("should match letter keys using code when key is a special character (macOS Alt behavior)", () => { // On macOS, pressing Option/Alt + A produces 'å' as the key, but code is still 'KeyA' - const macOSAltAEvent = createKeyboardEvent("å", "KeyA"); + const macOSAltAEvent = createKeyboardEvent("å", "KeyA", { altKey: true }); expect(keyMatches(macOSAltAEvent, "a")).toBe(true); // Option + H produces '˙' - const macOSAltHEvent = createKeyboardEvent("˙", "KeyH"); + const macOSAltHEvent = createKeyboardEvent("˙", "KeyH", { altKey: true }); expect(keyMatches(macOSAltHEvent, "h")).toBe(true); // Option + S produces 'ß' - const macOSAltSEvent = createKeyboardEvent("ß", "KeyS"); + const macOSAltSEvent = createKeyboardEvent("ß", "KeyS", { altKey: true }); expect(keyMatches(macOSAltSEvent, "s")).toBe(true); }); }); @@ -216,6 +223,15 @@ describe("shortcuts", () => { consoleSpy.mockRestore(); }); + it("matches azerty", () => { + const event = createKeyboardEvent({ + key: "a", + code: "KeyQ", + ctrlKey: true + }); + expect(matchesShortcut(event, "Ctrl+A")).toBe(true); + }); + it("should match Alt+letter shortcuts on macOS where key is a special character", () => { // On macOS, pressing Option/Alt + A produces 'å' but code remains 'KeyA' const macOSAltAEvent = createKeyboardEvent({ diff --git a/apps/client/src/services/shortcuts.ts b/apps/client/src/services/shortcuts.ts index 63db45302..c367ecac3 100644 --- a/apps/client/src/services/shortcuts.ts +++ b/apps/client/src/services/shortcuts.ts @@ -215,9 +215,12 @@ export function keyMatches(e: KeyboardEvent, key: string): boolean { // For letter keys, use the physical key code for consistency // On macOS, Option/Alt key produces special characters, so we must use e.code if (key.length === 1 && key >= 'a' && key <= 'z') { - // e.code is like "KeyA", "KeyB", etc. - const expectedCode = `Key${key.toUpperCase()}`; - return e.code === expectedCode || e.key.toLowerCase() === key.toLowerCase(); + if (e.altKey) { + // e.code is like "KeyA", "KeyB", etc. + const expectedCode = `Key${key.toUpperCase()}`; + return e.code === expectedCode || e.key.toLowerCase() === key.toLowerCase(); + } + return e.key.toLowerCase() === key.toLowerCase(); } // For regular keys, check both key and code as fallback