Skip to content

feat: add image paste support to chat input#68

Merged
morgmart merged 7 commits intomainfrom
worktree-image-paste
Apr 2, 2026
Merged

feat: add image paste support to chat input#68
morgmart merged 7 commits intomainfrom
worktree-image-paste

Conversation

@morgmart
Copy link
Copy Markdown
Collaborator

@morgmart morgmart commented Apr 1, 2026

Category: new-feature
User Impact: Users can now paste screenshots and images directly into the chat input with Cmd+V and send them to the AI alongside their message.

Problem: Pasting an image from the clipboard into the chat input did nothing — there was no way to share a screenshot or visual context without describing it in text.

Solution: Added clipboard paste handling to the chat textarea that captures image items, displays them as thumbnails above the input, and forwards them as base64 content blocks to the ACP agent. The ACP driver already supported images via (base64, mimeType) pairs — this PR wires that capability end-to-end from the UI through to the backend.

File changes

src/features/chat/ui/ChatInput.tsx
Added onPaste handler that intercepts clipboard image items and converts them to base64. Added PastedImageThumb local component that renders a thumbnail with a hover-reveal remove button and click-to-expand lightbox. Images appear above the persona tag so they're always at the top of the input area. canSend updated to allow sending with images even when text is empty.

src/features/chat/ui/ChatView.tsx
Updated handleSend (and the deferred-send ref used during persona switches) to accept and forward an optional images array to sendMessage.

src/features/chat/hooks/useChat.ts
Updated sendMessage to accept images?: { base64, mimeType }[], embed them as ImageContent blocks in the local user message for display in the timeline, and forward them to acpSendMessage.

src/shared/api/acp.ts
Added images?: [string, string][] to AcpSendMessageOptions and passes it through to the Tauri invoke call.

src-tauri/src/commands/acp.rs
Added images: Vec<(String, String)> parameter to the acp_send_message Tauri command and passes it through to AcpService::send_prompt.

src-tauri/src/services/acp/mod.rs
Added images parameter to send_prompt and passes &images to driver.run() instead of the previous hardcoded &[].

src/shared/ui/dialog.tsx
New shadcn-style Dialog component (adapted from shadcn/ui GitHub, using @radix-ui/react-dialog to match the project's existing Radix pattern). Animation-free content to avoid the transform-origin issue that caused dialogs to slide in from a corner.

src/shared/ui/ImageLightbox.tsx
New reusable lightbox component built on Dialog. Sized to fit the viewport, closes on overlay click or Escape. Positioned in shared/ui since image viewing will be needed in the message timeline too.

package.json / pnpm-lock.yaml
Added @radix-ui/react-dialog dependency for the Dialog primitive.

Reproduction Steps

  1. Run the app and open a chat session
  2. Take a screenshot (Cmd+Shift+4 on macOS) or copy any image to the clipboard
  3. Click into the chat input and press Cmd+V
  4. A thumbnail should appear above the input — hover it to reveal the remove button, click it to open the lightbox
  5. Type a message (optional) and send — the image is included with the prompt to the AI

Screenshots/Demos

Before: Cmd+V in the chat input did nothing.

After: Pasted images appear as thumbnails above the input with hover-to-remove and click-to-expand behavior. Images are forwarded to the AI with the message.

Users can now paste screenshots and images directly into the chat input with Cmd+V. Pasted images show as thumbnails with a click-to-expand lightbox and a hover-reveal remove button. Images are forwarded to the ACP agent as base64 content blocks alongside the text prompt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@morgmart morgmart requested a review from wesbillman as a code owner April 1, 2026 22:30
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89aff4de70

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

morgmart and others added 5 commits April 1, 2026 15:40
Revoke only runs on component unmount (via a ref to latest images),
not on every add/remove. Previously the effect's cleanup re-ran on
every images state change, revoking URLs that were still in use.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add 'image' case to renderContentBlock in MessageBubble so pasted
images appear in the chat history after sending. Base64 sources are
rendered as data: URLs; URL sources rendered directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Pass a single space as prompt when images are present but text is empty,
  preventing goose from rejecting empty-text ACP content blocks
- Make images in the message timeline clickable via lightbox (ClickableImage)
- Suppress Radix Dialog aria-describedby warning in ImageLightbox
- Remove temporary debug console.logs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MessageBubble.tsx was 516 lines (limit 500). Moves ClickableImage
into its own file to bring it under the limit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@morgmart morgmart merged commit 00ad218 into main Apr 2, 2026
6 checks passed
@morgmart morgmart deleted the worktree-image-paste branch April 2, 2026 00:10
tellaho added a commit to tellaho/goose2 that referenced this pull request Apr 2, 2026
Merges 7 commits from main into tho/boss-ui:
- Image paste support in chat input (block#68)
- Tab name text unselectable (block#67)
- Chat title immediate update on send (block#66)
- Artifact v1 file viewing (block#63)
- Cmd+W tab close (block#64)
- Chat activity/unread state tracking (block#62)
- Sidebar hierarchy polish + faster reloads (block#61)

Key conflict resolutions:
- Keep Tailwind v4 CSS-based config (delete tailwind.config.js)
- Keep boss-ui dialog.tsx, add showCloseButton prop from main
- Add text-foreground-subtle token to boss-ui theme system
- Keep ToolCallAdapter (boss-ui), adopt ToolChainCards pattern from main
- Delete MarkdownContent/ToolCallCard (replaced by boss-ui ai-elements)
- Adopt SessionActivityIndicator from main into sidebar
- Adopt ClickableImage/ImageLightbox from main
- Merge drag-and-drop image support into ChatInput
- Keep boss-ui hover:bg-accent/50 treatment throughout sidebar

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant