feat(web): drag sidebar threads between categories - #8001
Conversation
|
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.
UI consistency review of the new sidebar drag-and-drop surfaces. Two findings, both in newly added web UI code; everything else (primitive reuse, ScrollArea/SidebarContent viewportRef contract, Tailwind ownership, reduced-motion handling, drag-preview geometry vs. contain-intrinsic-size) looks consistent with the existing system.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 399a71d142
ℹ️ 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".
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR introduces a large new cross-category drag-and-drop system with custom collision handling, optimistic persistence, viewport management, and server lifecycle/event changes. Its scope and unresolved risks around compatibility and multi-step state updates warrant human review. Not approved because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
There was a problem hiding this comment.
One finding on the new sidebar drag board: the empty-section drop rail is missing for Snoozed, so an empty Snoozed section presents differently from the other three sections during a drag.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
One finding on the latest commit's removal of the empty Regular drop rail. The previously reported empty-Snoozed rail inconsistency (SidebarThreadBoard.tsx, snoozed boundary) is unchanged and still stands — not re-commented.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
UI consistency review of the sidebar drag-and-drop rework. The two items I raised on the previous head were addressed (aria-expanded now tracks the real shelf state via a separate dropActive presentation flag, and the grab cursor now lands on the [data-thread-row] surface). One earlier finding is still open (empty Snoozed renders a shelf header instead of the dashed EmptySectionRail the other three sections get — see the existing thread on SidebarThreadBoard.tsx), plus one new note below on coverage for the newly extracted pure drag logic.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
Reviewed the sidebar drag-and-drop UI for shared-primitive usage, Tailwind ownership, and interaction/accessibility preservation. The Regular boundary droppable and the missing pure-logic tests flagged earlier are addressed. One accessibility regression remains in the new board structure.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
One finding: the sidebar un-settle affordance loses its shared Tooltip, reverting a recently merged fix and diverging from the sibling icon buttons in the same row.
Posted via Macroscope — UI Consistency
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 8e613a3. Configure here.
| const pinnedPlan = current.action === "pin" ? planPinnedInsertion(current) : null; | ||
| if (current.action === "pin" && pinnedPlan === null) { | ||
| finishTransaction(); | ||
| return; |
There was a problem hiding this comment.
Silent pin drop abort
Medium Severity
Dropping a thread into Pinned can abort after the drop animation with no error toast when planPinnedInsertion returns null. That happens when neighbor key rematerialization includes a global pinned row (including settled-but-still-pinned) whose environment lacks threadPinReorder, even though the dragged thread itself can pin. The row snaps back and the pin never commits.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 8e613a3. Configure here.


What Changed
Why
The sidebar previously allowed reordering only inside Pinned.
The diff is larger than a normal UI patch because the old pinned-only implementation lived inside
Sidebar.tsx. This PR moves drag state, collision handling, pinned ordering, viewport anchoring, and board rendering into focused modules. The resulting design is documented indocs/internals/sidebar-thread-dnd.md.UI Changes
Before: drag and drop only reordered threads within Pinned.
After:
recording-a377fc69-049a-472c-9a65-b0a7aa970521.mp4
The recording covers pinned reorder, moves between every category, the snooze menu, card-to-compact morphing, auto-scroll, and viewport stability.
Verification
@t3tools/webtypecheck passed.Checklist
Model: GPT-5.6-sol
Harness: Codex in T3 Code
Note
High Risk
Changes orchestration event emission for pin/settle/snooze (companion cleanup events) and re-pin order-key behavior, plus a large interactive sidebar rewrite. Event consumers and racey pin reorders can behave differently.
Overview
Lets users drag threads between Pinned, Regular, Snoozed, and Settled on web. Dropping applies the destination lifecycle command; Pinned keeps the chosen slot, other sections snap to their normal sort. Dropping into Snoozed opens the duration menu. The old pinned-only sorter is replaced by a single dnd-kit board with overlay morphing, auto-scroll, and viewport anchoring.
Server lifecycle commands now treat those categories as exclusive. Pin, settle, snooze, and their reverses emit companion cleanup events so a thread lands in one shelf. Re-pinning with an
orderKeynow applies that placement instead of ignoring it. Snooze toasts/menus say Wake rather than Undo, matching that Wake no longer restores a previous category.Mobile row menus follow the same rules: snooze is offered from the rendered category, and snoozed rows only Wake.
Reviewed by Cursor Bugbot for commit 8e613a3. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add drag-and-drop support for sidebar threads across categories
SidebarThreadBoard,SidebarThreadDndShell, anduseSidebarThreadDndthat lets users move threads between Pinned, Regular, Snoozed, and Settled sections.useSidebarPinnedDnd, with scroll stabilization viauseSidebarDndLayout.thread.unsettled,thread.unsnoozed) to normalize threads to a single category.decider.tsnow emits additional events for lifecycle commands, which may break out-of-tree consumers expecting a single event per command. Re-pinning with anorderKeynow overwrites an existingpinOrderKey.Macroscope summarized 8e613a3.