From d04145cdf1e0f884771f76bdb05cabe77de78a49 Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sat, 13 Jun 2026 21:45:02 +0000 Subject: [PATCH] fix(mobile-chat): send cursor matches attach-only enabled state (#2762 residual) The #2762 multi-send fix removed from the send button's disabled prop and background/color styles, but left the cursor expression using . With files attached and no draft text, the button was enabled but showed a not-allowed cursor. - Update cursor to . - Add regression test: attach-only message shows enabled Send button with pointer cursor. Refs #2762 Test plan: - npx vitest run src/components/mobile/__tests__/MobileChat.test.tsx - npx vitest run src/components/mobile Co-Authored-By: Claude --- canvas/src/components/mobile/MobileChat.tsx | 5 ++++- .../mobile/__tests__/MobileChat.test.tsx | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/canvas/src/components/mobile/MobileChat.tsx b/canvas/src/components/mobile/MobileChat.tsx index 791dff84..df5f064f 100644 --- a/canvas/src/components/mobile/MobileChat.tsx +++ b/canvas/src/components/mobile/MobileChat.tsx @@ -847,7 +847,10 @@ export function MobileChat({ height: 36, borderRadius: 999, border: "none", - cursor: (draft.trim() || pendingFiles.length === 0) && !uploading ? "pointer" : "not-allowed", + cursor: + (draft.trim() || pendingFiles.length > 0) && reachable && !uploading + ? "pointer" + : "not-allowed", flexShrink: 0, background: (draft.trim() || pendingFiles.length > 0) && reachable && !uploading diff --git a/canvas/src/components/mobile/__tests__/MobileChat.test.tsx b/canvas/src/components/mobile/__tests__/MobileChat.test.tsx index 287da44a..5cba90fe 100644 --- a/canvas/src/components/mobile/__tests__/MobileChat.test.tsx +++ b/canvas/src/components/mobile/__tests__/MobileChat.test.tsx @@ -258,12 +258,28 @@ describe("MobileChat — composer", () => { expect(sendBtn).toBeTruthy(); }); - it("Send button is disabled when textarea is empty (no draft)", () => { + it("Send button is disabled when textarea is empty (no draft)", async () => { const { container } = renderChat(mockAgentId); const sendBtn = container.querySelector('[aria-label="Send"]') as HTMLButtonElement; expect(sendBtn.disabled).toBe(true); }); + // Regression #2762-follow-up: the send cursor used `pendingFiles.length === 0`, + // so attaching a file without typing text left the button enabled but showed a + // `not-allowed` cursor. It must be consistent with the disabled prop. + it("Send button is enabled and shows pointer cursor when files are attached but draft is empty", async () => { + const { container } = renderChat(mockAgentId); + const fileInput = container.querySelector('input[type="file"]') as HTMLInputElement; + const file = new File(["hello"], "note.txt", { type: "text/plain" }); + await act(async () => { + fireEvent.change(fileInput, { target: { files: [file] } }); + }); + + const sendBtn = container.querySelector('[aria-label="Send"]') as HTMLButtonElement; + expect(sendBtn.disabled).toBe(false); + expect(sendBtn.style.cursor).toBe("pointer"); + }); + // Regression #224: the composer textarea must render with font-size // ≥ 16px. iOS Safari and PWAs auto-zoom the viewport when a focused // input has a computed font-size below 16px — the layout jumps and -- 2.52.0