From e380a2dad1399841d67afaf620568f946f942f4e Mon Sep 17 00:00:00 2001 From: "posthog[bot]" <206114724+posthog[bot]@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:12:53 +0000 Subject: [PATCH] fix(terminal): stop Cmd+K clear from opening the command menu The terminal's custom key handler cleared the terminal on Cmd/Ctrl+K but only called preventDefault(), so the native keydown kept bubbling to the document-level mod+k hotkey, which opened the command menu on every clear. Add stopPropagation()/stopImmediatePropagation() in the k branch only. The w/r/1-9 branches intentionally return false so their events bubble to the global handlers, so they are left untouched. Generated-By: PostHog Code Task-Id: af84822e-2140-4b7d-8b01-2df4f2bff502 --- .../features/terminal/TerminalManager.test.ts | 62 +++++++++++++++++++ .../src/features/terminal/TerminalManager.ts | 4 ++ 2 files changed, 66 insertions(+) diff --git a/packages/ui/src/features/terminal/TerminalManager.test.ts b/packages/ui/src/features/terminal/TerminalManager.test.ts index c3700af330..fb9667161d 100644 --- a/packages/ui/src/features/terminal/TerminalManager.test.ts +++ b/packages/ui/src/features/terminal/TerminalManager.test.ts @@ -266,3 +266,65 @@ describe("TerminalManager.destroyForTask", () => { host.remove(); }); }); + +describe("TerminalManager custom key handling", () => { + const sessionId = "key-handler-test"; + + beforeEach(() => { + mocks.check.mockReset().mockResolvedValue(true); + mocks.create.mockReset().mockResolvedValue(undefined); + mocks.write.mockReset().mockResolvedValue(undefined); + mocks.resize.mockReset().mockResolvedValue(undefined); + mocks.terminalInstances.length = 0; + }); + + afterEach(() => { + terminalManager.destroy(sessionId); + }); + + function keyHandler() { + terminalManager.create({ sessionId, persistenceKey: "task-key" }); + const instance = mocks.terminalInstances[0]; + return instance.attachCustomKeyEventHandler.mock.calls[0][0] as ( + event: KeyboardEvent, + ) => boolean; + } + + function fakeEvent(overrides: Partial): KeyboardEvent { + return { + key: "k", + type: "keydown", + ctrlKey: false, + metaKey: false, + shiftKey: false, + preventDefault: vi.fn(), + stopPropagation: vi.fn(), + stopImmediatePropagation: vi.fn(), + ...overrides, + } as unknown as KeyboardEvent; + } + + it("clears the terminal and stops ctrl+k from bubbling to the command menu", () => { + const handler = keyHandler(); + const event = fakeEvent({ key: "k", ctrlKey: true, type: "keydown" }); + + const result = handler(event); + + expect(result).toBe(false); + expect(mocks.terminalInstances[0].clear).toHaveBeenCalledTimes(1); + expect(event.preventDefault).toHaveBeenCalledTimes(1); + expect(event.stopPropagation).toHaveBeenCalledTimes(1); + expect(event.stopImmediatePropagation).toHaveBeenCalledTimes(1); + }); + + it("lets ctrl+w keep bubbling so global handlers can act", () => { + const handler = keyHandler(); + const event = fakeEvent({ key: "w", ctrlKey: true }); + + const result = handler(event); + + expect(result).toBe(false); + expect(event.stopPropagation).not.toHaveBeenCalled(); + expect(event.stopImmediatePropagation).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/ui/src/features/terminal/TerminalManager.ts b/packages/ui/src/features/terminal/TerminalManager.ts index d75d173bb9..e8ce975bb6 100644 --- a/packages/ui/src/features/terminal/TerminalManager.ts +++ b/packages/ui/src/features/terminal/TerminalManager.ts @@ -135,6 +135,10 @@ function attachKeyHandlers(term: XTerm) { if (event.key === "k" && cmdOrCtrl && event.type === "keydown") { event.preventDefault(); + // Stop the keydown from bubbling to the document-level mod+k hotkey, + // which would otherwise open the command menu on every terminal clear. + event.stopPropagation(); + event.stopImmediatePropagation(); term.clear(); return false; }