Skip to content

feat(ui): image paste from clipboard in editor #425

Description

@amelia751

Summary

Users should be able to paste images from the clipboard directly into the editor (both visual/BlockNote mode and source/CodeMirror mode). The pasted image gets uploaded as an asset and inserted as a markdown image reference. This is a standard feature in Notion, Confluence, Obsidian, GitHub, and every modern editor.

Proposed behavior

  1. Paste (Ctrl+V / Cmd+V) with image data on clipboard → upload to POST /api/kiwi/assets → insert ![](assets/<filename>) at cursor position.
  2. Drag-and-drop — same flow for images dragged into the editor area.
  3. File naming: paste-<timestamp>.<ext> (e.g., paste-20260623-143022.png).
  4. Show a loading placeholder while uploading (e.g., ![Uploading...]()), then replace with the real URL on success.
  5. Support formats: PNG, JPEG, GIF, WebP.
  6. Error handling: if upload fails, show a toast notification and remove the placeholder.

Implementation notes

  • Visual mode (BlockNote): BlockNote already handles some paste events. Hook into the editor.onPaste or use a ProseMirror plugin to intercept clipboardData.items with type.startsWith('image/').
  • Source mode (CodeMirror): Use CodeMirror's EditorView.domEventHandlers to handle paste and drop events.
  • Upload endpoint: POST /api/kiwi/assets (already exists, accepts multipart form data).
  • Prioritize shadcn components. Use shadcn Sonner / toast for upload progress and error notifications — install via npx shadcn@latest add sonner if not present. Alternatively use the existing toast mechanism if one exists in the codebase.
  • Max file size: respect the [assets] max_file_size config (default 10MB).
  • For drag-and-drop, add a visual drop zone overlay using a div with dashed border that appears on dragover.

Acceptance criteria

  • Pasting an image from clipboard uploads and inserts markdown image
  • Works in both visual (BlockNote) and source (CodeMirror) modes
  • Drag-and-drop images into editor works
  • Loading placeholder shown during upload
  • Error toast on upload failure
  • Respects max file size config
  • Unit/integration tests for paste handler

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions