Skip to content

[Fix] Dragging files into the chat input fails unless Shift is held - #2184

Draft
zoomote2[bot] wants to merge 1 commit into
mainfrom
fix/chat-drag-drop-no-shift-2t9fhxuwf9qlx
Draft

zoomote2[bot] wants to merge 1 commit into
mainfrom
fix/chat-drag-drop-no-shift-2t9fhxuwf9qlx

Conversation

@zoomote2

@zoomote2 zoomote2 Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

​Opened on behalf of @taltas. Follow up by mentioning @roomote, in the web UI, or in Discord.

Related GitHub Issue

Closes: #2139

Description

Users cannot drag files from the Explorer into the chat input. The drop works only when they hold Shift. It also fails about 9 times of 10 with Shift held.

Root cause: PR #1953 added a Shift gate to the onDragOver handler of the chat input. The handler did not call preventDefault() when Shift was not held. The browser then treated the input as an invalid drop target. The drop event never fired. This affects local and remote (SSH) workspaces alike.

The drop was also not stable with Shift held. A drop target is valid only when the last dragover event before the drop was canceled. Users press Shift after they start the drag. When the pointer does not move after that, no new dragover event fires. The last event still reports shiftKey: false. The drop fails.

This PR removes the gate for file-oriented drags. The handler now calls preventDefault() when the drag payload contains a file-oriented data transfer type:

  • Files - drags from the OS file manager.
  • text/uri-list - URI list drags.
  • ResourceURIs, application/vnd.code.files, application/vnd.code.uri-list - types that VS Code sets for Explorer and editor tab drags (see fillEditorsDragData in the VS Code workbench).

VS Code sets these types in local and remote (SSH) workspaces alike. The remote payload also works: the drop handler receives the plain-text path, and convertToMentionPath already strips vscode-remote:// prefixes.

Plain text drags inside the input, such as moving a selection, keep the native browser behavior. Shift still works as before. It is no longer necessary.

Test Procedure

  • Added 7 Vitest cases in webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsx under dragover acceptance. They cover: Explorer-style drags without Shift (accepted), OS file drags without Shift (accepted), each single file type (accepted), plain text drags without Shift (rejected, native behavior kept), and plain text drags with Shift (accepted).
  • pnpm --dir webview-ui exec vitest run src/components/chat/__tests__/ChatTextArea.spec.tsx: 73 of 73 tests pass.
  • pnpm --dir webview-ui exec eslint on both changed files: clean, no new suppressions.
  • pnpm --dir webview-ui run check-types: clean.
  • Full pnpm test from the repository root: 11,316 tests pass, 14 of 14 turbo tasks succeed. One unrelated test in src/__tests__/extension.spec.ts failed once under full-suite parallel load. It passed on retry and in isolation, on both clean and patched trees.
  • Manual step for reviewers with a Remote-SSH setup: drag a file from the Explorer into the chat input with no modifier key held. The input shows the dashed drop border. Release the mouse. The file appears as a mention.

Pre-Submission Checklist

  • Issue Linked: This PR is linked to issue [BUG] Does the current version's UI no longer support dragging and dropping files into the dialog box? #2139.
  • Scope: My changes are focused on the linked issue.
  • Self-Review: I reviewed my own code with care.
  • Writing Style: The PR title and description use Simplified Technical English.
  • Testing: New tests were added to cover my changes.
  • Visual Snapshot (UI changes only): This change is behavior-only. The drop-zone highlight styling did not change. Only the conditions that trigger it changed. Per webview-ui/AGENTS.md, behavior-only changes belong in Vitest, not in a *.visual.tsx snapshot.
  • Documentation Impact: Documentation updates are required. See the Documentation Updates section below.
  • Contribution Guidelines: I read and agree to the Contributor Guidelines.

Visual Snapshots

None. This change does not alter static rendered state. The Zoo Code webview runs only inside VS Code, so no browser screenshot of the extension UI was possible in this environment.

Videos (interaction / animation only)

None. The drag interaction cannot be recorded in this environment because the webview runs only inside VS Code. The Vitest suite covers the acceptance logic.

Documentation Updates

  • No documentation updates are required.
  • Yes, documentation updates are required. docs/tips-and-tricks.md told users to hold Shift while they drag files. A paired PR in Zoo-Code-Org/Zoo-Code-Docs removes that instruction. See the Related PRs section.

Additional Notes

  • Upstream Roo Code has the same Shift gate today. This fix is Zoo-Code specific for now.
  • The ResourceURIs, application/vnd.code.files, and application/vnd.code.uri-list type names come from the VS Code workbench drag-and-drop source. They are stable public drag payload markers used across VS Code versions.

Related PRs

Get in Touch

Discord: taltas1 (opened by Roomote on behalf of Toray Altas)

@coderabbitai

coderabbitai Bot commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one): 1
  • coderabbit-review-active

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@zoomote2

zoomote2 Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Author

1 issue outstanding. See session

  • webview-ui/src/components/chat/ChatTextArea.tsx:39-53 — two of the five file-drag types (ResourceURIs, application/vnd.code.files) can never match a real drag: Chromium lowercases custom drag types in DataTransfer.types (VS Code's containsDragType works around exactly this), and the real VS Code type names are ResourceURLs and CodeEditors/CodeFiles. Acceptance should compare case-insensitively and use the real names; today the fix works only via the lowercase-safe text/uri-list and application/vnd.code.uri-list entries.

Reviewed 92e4812

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Review status

This PR was opened by an automated account. A human maintainer must verify the change intent, provenance, and validation before merging.

Current step: Mark the PR ready. Required CI must pass before CodeRabbit starts.

Review-state labels are managed by this workflow; do not edit them manually. community-approved is managed the same way — do not add or remove it manually. It signals a fresh community code approval for the current head as an advisory priority only; maintainer review is still required.

@codecov

codecov Bot commented Oct 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Comment on lines +39 to +53
// Data transfer types that signal a file-oriented drag rather than an in-webview
// text selection drag. "Files" covers drags from the OS file manager; the
// remaining types are set by VS Code when dragging resources from the Explorer
// or editor tabs, in local and remote workspaces alike (see fillEditorsDragData
// in VS Code's workbench drag-and-drop code).
const FILE_DRAG_DATA_TRANSFER_TYPES = [
"Files",
"text/uri-list",
"ResourceURIs",
"application/vnd.code.files",
"application/vnd.code.uri-list",
]

const isFileDrag = (dataTransfer: DataTransfer): boolean =>
FILE_DRAG_DATA_TRANSFER_TYPES.some((type) => dataTransfer.types.includes(type))

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Two of these five types can never match a real drag in the webview, and the matching itself is case-sensitive against an API that lowercases.

  • Chromium exposes custom drag types in DataTransfer.types lowercased. VS Code's own containsDragType helper (vs/platform/dnd/browser/dnd.ts) lowercases both sides for exactly this reason, with the comment "somehow the types are lowercase". So types.includes("ResourceURIs") can never succeed.
  • The spelling is also stale: VS Code's DataTransfers.RESOURCES is "ResourceURLs", not "ResourceURIs" (verified in vs/base/browser/dnd.ts on current main and 1.96; this repo pins VS Code types at 1.100).
  • application/vnd.code.files is not a VS Code type. fillEditorsDragData sets text/plain, text/uri-list, application/vnd.code.uri-list (INTERNAL_URI_LIST), ResourceURLs, and CodeEditors; the internal constants are CodeDataTransfers.EDITORS = "CodeEditors" and CodeDataTransfers.FILES = "CodeFiles".

The fix still works today because Explorer/editor-tab drags also carry application/vnd.code.uri-list and text/uri-list, which happen to be all-lowercase and match exactly. But the two dead entries give false confidence — the new tests pass only because they synthesize exact-case payloads Chromium cannot produce — and acceptance would silently regress to the issue #2139 behavior if VS Code ever stops setting the uri-list types. Comparing case-insensitively (mirroring containsDragType) and using the real type names removes both risks:

Suggested change
// Data transfer types that signal a file-oriented drag rather than an in-webview
// text selection drag. "Files" covers drags from the OS file manager; the
// remaining types are set by VS Code when dragging resources from the Explorer
// or editor tabs, in local and remote workspaces alike (see fillEditorsDragData
// in VS Code's workbench drag-and-drop code).
const FILE_DRAG_DATA_TRANSFER_TYPES = [
"Files",
"text/uri-list",
"ResourceURIs",
"application/vnd.code.files",
"application/vnd.code.uri-list",
]
const isFileDrag = (dataTransfer: DataTransfer): boolean =>
FILE_DRAG_DATA_TRANSFER_TYPES.some((type) => dataTransfer.types.includes(type))
// Data transfer types that signal a file-oriented drag rather than an in-webview
// text selection drag. Chromium exposes custom drag types in DataTransfer.types
// lowercased (VS Code works around the same behavior in its containsDragType
// helper), so every entry here is lowercase. "files" covers drags from the OS
// file manager; the remaining types are set by VS Code when dragging resources
// from the Explorer or editor tabs, in local and remote workspaces alike (see
// fillEditorsDragData in VS Code's workbench drag-and-drop code).
const FILE_DRAG_DATA_TRANSFER_TYPES = [
"files",
"text/uri-list",
"resourceurls",
"codeeditors",
"codefiles",
"application/vnd.code.uri-list",
]
const isFileDrag = (dataTransfer: DataTransfer): boolean => {
const dragTypes = dataTransfer.types.map((type) => type.toLowerCase())
return FILE_DRAG_DATA_TRANSFER_TYPES.some((type) => dragTypes.includes(type))
}

This branch has not been deployed

No deployments
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.

[BUG] Does the current version's UI no longer support dragging and dropping files into the dialog box?

1 participant