From fe682d85357794f65b2829cd85322531bc0d2d94 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sun, 18 Jan 2026 20:37:55 +0000 Subject: [PATCH] fix: Shift+Enter now inserts newline when Ctrl+Enter to send is enabled Fixes #10386 When enterBehavior is set to "newline" (Ctrl+Enter to send mode), Shift+Enter was incorrectly triggering onSend() due to event.shiftKey being included in the send condition. This commit removes event.shiftKey from the condition so that: - Enter: inserts a new line - Shift+Enter: inserts a new line (consistent with standard text editing) - Ctrl/Cmd+Enter: sends the message Updated the test to reflect the corrected behavior. --- .../src/components/chat/ChatTextArea.tsx | 7 ++++--- .../chat/__tests__/ChatTextArea.spec.tsx | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/webview-ui/src/components/chat/ChatTextArea.tsx b/webview-ui/src/components/chat/ChatTextArea.tsx index 654f2e1011e..be308c51314 100644 --- a/webview-ui/src/components/chat/ChatTextArea.tsx +++ b/webview-ui/src/components/chat/ChatTextArea.tsx @@ -495,13 +495,14 @@ export const ChatTextArea = forwardRef( // Handle Enter key based on enterBehavior setting if (event.key === "Enter" && !isComposing) { if (enterBehavior === "newline") { - // New behavior: Enter = newline, Shift+Enter or Ctrl+Enter = send - if (event.shiftKey || event.ctrlKey || event.metaKey) { + // New behavior: Enter = newline, Ctrl/Cmd+Enter = send + // Shift+Enter also inserts newline (consistent with standard text editing) + if (event.ctrlKey || event.metaKey) { event.preventDefault() resetHistoryNavigation() onSend() } - // Otherwise, let Enter create newline (don't preventDefault) + // Otherwise, let Enter/Shift+Enter create newline (don't preventDefault) } else { // Default behavior: Enter = send, Shift+Enter = newline if (!event.shiftKey) { diff --git a/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx index 0b63a68f4ec..a621f14e3ef 100644 --- a/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx @@ -1081,7 +1081,7 @@ describe("ChatTextArea", () => { expect(shiftEnterEvent.defaultPrevented).toBe(false) }) - it("should treat Ctrl/Cmd/Shift+Enter as send and plain Enter as newline in newline mode", () => { + it("should treat Ctrl/Cmd+Enter as send and plain Enter/Shift+Enter as newline in newline mode", () => { const onSend = vi.fn() ;(useExtensionState as ReturnType).mockReturnValue({ @@ -1096,11 +1096,13 @@ describe("ChatTextArea", () => { const textarea = container.querySelector("textarea")! + // Plain Enter should NOT send (allows newline) const plainEnterEvent = new KeyboardEvent("keydown", { key: "Enter", bubbles: true, cancelable: true }) fireEvent(textarea, plainEnterEvent) expect(onSend).not.toHaveBeenCalled() expect(plainEnterEvent.defaultPrevented).toBe(false) + // Ctrl+Enter SHOULD send const ctrlEnterEvent = new KeyboardEvent("keydown", { key: "Enter", ctrlKey: true, @@ -1111,6 +1113,7 @@ describe("ChatTextArea", () => { expect(onSend).toHaveBeenCalledTimes(1) expect(ctrlEnterEvent.defaultPrevented).toBe(true) + // Shift+Enter should NOT send (allows newline, consistent with standard text editing) const shiftEnterEvent = new KeyboardEvent("keydown", { key: "Enter", shiftKey: true, @@ -1118,8 +1121,19 @@ describe("ChatTextArea", () => { cancelable: true, }) fireEvent(textarea, shiftEnterEvent) + expect(onSend).toHaveBeenCalledTimes(1) // Still 1, not incremented + expect(shiftEnterEvent.defaultPrevented).toBe(false) // Should not prevent default + + // Cmd+Enter (metaKey) SHOULD send + const metaEnterEvent = new KeyboardEvent("keydown", { + key: "Enter", + metaKey: true, + bubbles: true, + cancelable: true, + }) + fireEvent(textarea, metaEnterEvent) expect(onSend).toHaveBeenCalledTimes(2) - expect(shiftEnterEvent.defaultPrevented).toBe(true) + expect(metaEnterEvent.defaultPrevented).toBe(true) }) }) })