feat(web): accept file drops into sidebar threads - #7892
Conversation
Dropping files from the OS onto a sidebar thread row now opens that thread and attaches the files in its composer, without sending. Rows reuse the workspace drop handlers (Files-type gate only), so pinned reordering and mention drags are unaffected. Files dropped on a row that is not the open thread are stashed and handed to the composer once the navigation lands; if the route bounces the stash is cleared. Ends with model/harness info: ox-alpha (opencode)
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
There was a problem hiding this comment.
One finding: the new sidebar drag-over highlight uses a Tailwind color token that does not exist, so the ring falls back to currentColor and changes appearance per row state. Details inline.
Posted via Macroscope — UI Consistency
Move the pending-drop hooks above ChatView's no-active-thread early return so hook order cannot change when a thread opens or closes. Only clear the pending stash when it still belongs to the drop that missed its landing, so a newer drop is never wiped by an older navigation. Use the existing ring-ring token for the row highlight instead of the nonexistent ring-sidebar-ring. Ends with: ox-alpha (opencode)
There was a problem hiding this comment.
One finding on the new drag-over highlight for sidebar thread rows: the outer ring is clipped by the row container's paint containment, leaving the drop target visually identical to hover. Details inline.
Posted via Macroscope — UI Consistency
The row li's content-visibility paint containment clips outer rings, so the drag-over affordance read as plain hover. Use an inset ring, the sidebar's own ring convention, tinted with primary to match the other file-drop surfaces instead of the focus-ring token. Ends with: ox-alpha (opencode)
ApprovabilityVerdict: Skipped Macroscope did not run approvability analysis for this PR. Macroscope could not determine whether this PR modifies its approvability configuration, so the PR was not approved automatically. A PR that may change the rules that govern approval is never approved automatically. |
The missing-thread redirect fires in an effect after navigation resolves, so the drop's landing check had already passed and the stash was never consumed or cleared. Clear it here, scoped to the dead thread, before navigating home. Ends with: ox-alpha (opencode)
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 16be904. Configure here.
An environment with no threads left leaves the route parked on the missing thread instead of redirecting home, so the stash survived. Move the release out of the redirect condition. Ends with: ox-alpha (opencode)

Closes #7396
What Changed
Each sidebar thread row (pinned, active, snoozed, settled) is now a drop target for files dragged from the OS. Dropping on a row opens that thread and attaches the files in its composer, ready to send; nothing is ever sent automatically. The row highlights while a file drag hovers over it.
Why
The chat workspace already accepts dropped files, but getting files into an older or background thread meant opening it first, then dragging again. Now one drag does it. Drop on the row, the thread opens, and the files ride the exact same composer path as a workspace drop, so validation, image compression, and focus behave identically.
Rows reuse the existing workspace drop handlers and only react to drags carrying real Files, so pinned-thread reordering and file-tree mention drags are untouched. When the dropped-on thread is not already open, the files are stashed briefly and handed to the composer once navigation lands; if the route bounces (thread gone), the stash is cleared instead of surprising the user later.
Video Demo
drag.mp4
Checklist
ox-alpha via opencode
Note
[!NOTE]
Add file drop support to web sidebar thread rows
SidebarThreadRowto highlight during drag-over and triggerhandleThreadFileDrop, which stashes files and navigates to the target thread.ChatViewContentand forwards files tocomposerRef.current?.addDroppedFiles(files).ChatThreadRouteViewif the target thread resolves as missing.SidebarThreadRownow navigates to that thread and stages the files for attachment instead of ignoring the drop.Macroscope summarized 8aefb76.
Note
Low Risk
UI-only drop/navigation handoff with a small Zustand stash; files still go through the existing composer attach path and are cleared if the thread is missing.
Overview
Lets users drag files from the OS onto any sidebar thread row. The thread opens and the files attach in its composer (same validation/compression/focus path as a workspace drop); nothing is sent automatically.
Rows reuse
makeWorkspaceFileDropHandlersand highlight on hover. If the target thread is not already open, files are stashed insidebarPendingFileDropStoreuntilChatViewconsumes them after navigation. Failed or missing-thread routes clear the stash so files cannot land on the wrong draft.Reviewed by Cursor Bugbot for commit 8aefb76. Bugbot is set up for automated code reviews on this repo. Configure here.