diff --git a/site/src/pages/AgentsPage/components/AgentChatInput.stories.tsx b/site/src/pages/AgentsPage/components/AgentChatInput.stories.tsx index f96eb754bb..baab81fcc5 100644 --- a/site/src/pages/AgentsPage/components/AgentChatInput.stories.tsx +++ b/site/src/pages/AgentsPage/components/AgentChatInput.stories.tsx @@ -81,6 +81,47 @@ export const SendsAndClearsInput: Story = { }, }; +/** + * CODAGT-210: On mobile viewports, Enter must insert a newline rather + * than submit the message, because Shift+Enter is cumbersome on + * on-screen keyboards. Users submit via the send button instead. + */ +export const MobileEnterInsertsNewline: Story = { + args: { + onSend: fn(), + initialValue: "Line one", + }, + play: async ({ canvasElement, args }) => { + const originalMatchMedia = window.matchMedia; + window.matchMedia = ((query: string) => + ({ + matches: query === "(max-width: 639px)", + media: query, + onchange: null, + addEventListener: () => undefined, + removeEventListener: () => undefined, + dispatchEvent: () => true, + addListener: () => undefined, + removeListener: () => undefined, + }) as MediaQueryList) as typeof window.matchMedia; + + try { + const canvas = within(canvasElement); + const editor = canvas.getByTestId("chat-message-input"); + await waitFor(() => { + expect(editor.textContent).toBe("Line one"); + }); + + await userEvent.click(editor); + await userEvent.keyboard("{Enter}"); + + expect(args.onSend).not.toHaveBeenCalled(); + } finally { + window.matchMedia = originalMatchMedia; + } + }, +}; + export const DisabledInput: Story = { args: { isDisabled: true, diff --git a/site/src/pages/AgentsPage/components/ChatMessageInput/ChatMessageInput.tsx b/site/src/pages/AgentsPage/components/ChatMessageInput/ChatMessageInput.tsx index 9135e52e86..2be8d6c671 100644 --- a/site/src/pages/AgentsPage/components/ChatMessageInput/ChatMessageInput.tsx +++ b/site/src/pages/AgentsPage/components/ChatMessageInput/ChatMessageInput.tsx @@ -30,6 +30,7 @@ import { useRef, } from "react"; import { cn } from "#/utils/cn"; +import { isMobileViewport } from "#/utils/mobile"; import { $createFileReferenceNode, FileReferenceNode, @@ -256,7 +257,9 @@ const PasteSanitizationPlugin: FC<{ }; // Handles Enter key behavior: plain Enter submits via the onEnter -// callback, Shift+Enter inserts a newline. +// callback, Shift+Enter inserts a newline. On mobile viewports, Enter +// always inserts a newline; users submit via the send button because +// Shift+Enter is cumbersome on touch keyboards (CODAGT-210). const EnterKeyPlugin: FC<{ onEnter?: () => void }> = function EnterKeyPlugin({ onEnter, }) { @@ -266,7 +269,7 @@ const EnterKeyPlugin: FC<{ onEnter?: () => void }> = function EnterKeyPlugin({ return editor.registerCommand( KEY_ENTER_COMMAND, (event: KeyboardEvent | null) => { - if (event?.shiftKey) { + if (event?.shiftKey || isMobileViewport()) { return false; } if (onEnter) {