cmux NEXT New Tab: paste and drop images and files, sent with the first prompt
Leo, 2026-10-19: "i cant paste in pictures in the new tab area but it works in the existing chats...?"
Cause
The New Tab page's prompt is its own <textarea> (newtab/NewTabScreen.tsx), not the chat composer (Composer.tsx). The chat composer's paste listener, document-level file drop (installFileDropLifecycle) and attachment chips all lived inside Composer, so on the New Tab page:
- a pasted image or copied file did nothing;
- a dropped file did nothing;
- even with a way to stage attachments, the page's first send (
screenActions.onAsk→chat.send { text }) carried only text.
Fix
- The chat composer's attachment code moves to
composer/attachmentIntake.tsx, and both composers use it:useAttachmentIntakecovers paste on the composer's field, file drop anywhere on the page, the moved-chat upload fallback and refusal notes.AttachmentStrip/AttachmentChip/PdfAttachmentChiprender the chips. They are moved, not changed.Composer.tsxis 257 lines shorter.
- The New Tab page stages a pasted image, a copied file, a screenshot or a dropped file under the same chips, with the same remove and preview.
onAskpasses the staged attachments. The chat's firstchat.sendcarries{ text, attachments }, and attachments alone are a prompt, as in a chat. A plain prompt sends exactly as before.
Tests
test/new-tab-paste-attachments.test.ts(browser lane, Chromium + WebKit, the pane's dev entry as a New Tab page on the mock transport):- case 1: paste a PNG on the field → chip → Return → the chat's first message shows the text and the image (
data:image/png); - case 2: drop a file on the page → chip → × removes it; a pasted image with no text → Return → the first message has the image.
- All 4 cases fail at base
dde0ebbee3(no chip appears) and pass with the fix.
- case 1: paste a PNG on the field → chip → Return → the chat's first message shows the text and the image (
test/new-tab-ask-attachments.test.ts:onAsksends{ text, attachments }, attachments alone, and a plain prompt unchanged. 2 of 3 fail at base.- Chat composer regressions, on Huge Blue:
agent-pane-attach-typing(3/3) andagent-pane-sent-images(1/1) pass;- all
new-tab-*andcomposer*jsdom tests pass (139/0); - lint, fmt and typecheck are clean.
The classic New Tab layout (NewTabPage, Debug Settings layout "a") is unchanged.
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Fixes the New Tab page so pasted or dropped images and files stage as chips and are sent with the first prompt, matching the chat composer.
- Moves the chat composer's attachment intake (paste, document-level drop, upload fallback, refusal notes) and its chips into
composer/attachmentIntake.tsx, shared byComposerand the New Tab field. onAsknow passes staged attachments to the chat's firstchat.send; attachments alone act as a prompt. Plain prompts send exactly as before, and the classic New Tab layout is unchanged.- With attachments staged, Return starts a chat with the text and attachments instead of opening a suggested page, tab, or workspace; in shell mode a paste stays text.
Covered by browser tests (Chromium + WebKit) for paste and drop, and jsdom tests for onAsk sending attachments.