fix: preserve Ctrl+C copy behaviour when text is selected

Resolves #195. Before sending an interrupt signal, check whether
the user has text selected. If so, let the browser handle Ctrl+C
as a native copy rather than interrupting Claude.
This commit is contained in:
2026-03-06 22:51:54 -08:00
committed by Naomi Carrigan
parent 80a59a0b22
commit 793043e192
2 changed files with 41 additions and 2 deletions
+3 -2
View File
@@ -240,9 +240,10 @@
return;
}
// Ctrl+C - Interrupt (only when processing)
// Ctrl+C - Interrupt (only when processing AND no text is selected)
if (event.ctrlKey && event.key === "c") {
if (get(isClaudeProcessing)) {
const hasSelection = Boolean(window.getSelection()?.toString());
if (get(isClaudeProcessing) && !hasSelection) {
event.preventDefault();
handleInterrupt();
return;
+38
View File
@@ -0,0 +1,38 @@
/**
* +page.svelte keyboard shortcut tests
*
* Tests the pure decision logic for the Ctrl+C keyboard shortcut handler.
* The handler should only intercept Ctrl+C (to send an interrupt signal) when:
* - Claude is currently processing a request, AND
* - No text is currently selected (so normal copy behaviour is preserved)
*
* Manual testing checklist:
* - [ ] Ctrl+C with text selected copies the text (browser default)
* - [ ] Ctrl+C with no text selected and Claude processing sends an interrupt
* - [ ] Ctrl+C with no text selected and Claude idle does nothing special
*/
import { describe, it, expect } from "vitest";
// Mirror the Ctrl+C interrupt decision logic from +page.svelte
function shouldInterruptOnCtrlC(isProcessing: boolean, hasSelection: boolean): boolean {
return isProcessing && !hasSelection;
}
describe("Ctrl+C interrupt logic", () => {
it("interrupts when Claude is processing and no text is selected", () => {
expect(shouldInterruptOnCtrlC(true, false)).toBe(true);
});
it("does not interrupt when text is selected, even if Claude is processing", () => {
expect(shouldInterruptOnCtrlC(true, true)).toBe(false);
});
it("does not interrupt when Claude is idle and no text is selected", () => {
expect(shouldInterruptOnCtrlC(false, false)).toBe(false);
});
it("does not interrupt when Claude is idle and text is selected", () => {
expect(shouldInterruptOnCtrlC(false, true)).toBe(false);
});
});