Skip to content

feat(sidebar): drag-and-drop reordering of threads within a project#3069

Open
TheIcarusWings wants to merge 1 commit into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder
Open

feat(sidebar): drag-and-drop reordering of threads within a project#3069
TheIcarusWings wants to merge 1 commit into
pingdotgg:mainfrom
TheIcarusWings:t3code/thread-drag-reorder

Conversation

@TheIcarusWings

@TheIcarusWings TheIcarusWings commented Jun 13, 2026

Copy link
Copy Markdown

What

Adds drag-and-drop reordering of threads within their project in the sidebar — grab a thread row and move it among the other threads in the same project. This is reordering within one project, not moving threads between projects. It mirrors the existing project-reorder pattern (same @dnd-kit setup, same client-side persistence model).

Changes

  • contracts: add "manual" to SidebarThreadSortOrder (alongside updated_at/created_at), matching SidebarProjectSortOrder. New "Manual" option in the "Sort threads" menu.
  • threadSort: sortThreads returns input order for "manual", so the user-defined order is layered on top via orderItemsByPreferredIds (same shape as sortProjectsForSidebar).
  • uiStateStore: new threadOrderByProject: Record<projectKey, threadKey[]>. Because scopedThreadKey is stable, it persists directly to localStorage (no id→cwd remapping like projects need). New reorderThreads action; syncThreads prunes stale thread keys and drops emptied projects.
  • Sidebar: per-project DndContext + SortableContext + SortableThreadItem rendered only when manual sort is active (non-DnD fallback otherwise). dragInProgress / suppressClickAfterDrag refs guard click, cmd/shift multi-select and rename so they don't fire on a drag. Manual mode auto-expands the full list (skips preview slicing / "Show more") so the whole list is reorderable; auto-animate stays attached.

The order map is keyed per project now but keyed so it extends naturally to user-defined groups once folders land.

Verification

  • tsgo --noEmit passes (web + contracts).
  • Full web unit suite green (1055 tests); contracts 148. Added 8 store tests (reorder up/down, first-drag seeding, no-ops, sync pruning, persistence round-trip).
  • Manually tested on localhost: enabled Manual thread sort, dragged a thread within a project, confirmed the new order persists across reload, and that click / rename / multi-select still work.

🤖 Generated with Claude Code


Note

Low Risk
Client-only sidebar UX and localStorage; follows the existing project manual-sort pattern with unit tests for store and persistence.

Overview
Adds manual thread sorting in the sidebar: a new Manual option under sort threads (contracts + sortThreads), with drag-and-drop reordering within each project when that mode is active.

Persistence: threadOrderByProject in uiStateStore (per logical project key), reorderThreads, localStorage round-trip, and syncThreads pruning of removed threads/projects.

UI: Per-project @dnd-kit (SortableThreadItem, row drag handles, click suppression after drag, rename pointerDown guard). Manual mode shows the full thread list (no preview / Show more) and keeps thread-jump / prewarm order aligned with the visible list in the root Sidebar.

Reviewed by Cursor Bugbot for commit 83326f5. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add drag-and-drop manual reordering of threads within a project in the sidebar

  • Adds a 'manual' sort order option to SidebarThreadSortOrder in settings.ts; thread rows become draggable with visual feedback when this mode is active.
  • Wraps thread lists in DndContext/SortableContext (via a new SortableThreadItem component) with vertical constraints and custom collision detection when manual sorting is enabled.
  • Persists and restores per-project thread order in threadOrderByProject via localStorage; syncThreads prunes stale entries when threads are deleted.
  • In manual mode, the "Show more" overflow is disabled so all threads remain visible and in stored order.
  • Risk: handleThreadClick suppresses navigation during and immediately after a drag, which could feel unresponsive if drag detection fires on short taps.

Macroscope summarized 83326f5.

Add a "Manual" thread sort mode that lets you drag a thread row to reorder
it among the other threads in the same project, mirroring the existing
project-reorder pattern.

- contracts: add "manual" to SidebarThreadSortOrder
- threadSort: sortThreads returns input order for "manual" so a user-defined
  order can be layered on top (matches sortProjectsForSidebar)
- uiStateStore: persist threadOrderByProject directly (thread keys are stable,
  no id->cwd remapping); add reorderThreads action and prune stale keys /
  empty projects in syncThreads
- Sidebar: per-project DndContext + SortableContext + SortableThreadItem when
  manual sort is active; suppress click/multi-select/rename during drag; apply
  the order via orderItemsByPreferredIds and auto-expand the full list

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. 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

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: de76b5a2-05a1-4764-8d68-c43e58c5ce19

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
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Jun 13, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

// user-defined order on top via `orderItemsByPreferredIds`.
if (sortOrder === "manual") {
return [...threads];
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Manual sort ignores persisted order

Medium Severity

With sidebarThreadSortOrder set to manual, helpers that pick a thread via sortThreads still use raw store order instead of threadOrderByProject. Delete fallback and opening a project from search can navigate to a thread that is not first in the sidebar’s manual list.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 83326f5. Configure here.

@macroscopeapp

macroscopeapp Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

This PR introduces a complete new feature (drag-and-drop thread reordering) with new components, state management, and persistence logic. New user-facing features warrant human review. Additionally, there's an unresolved comment identifying a potential bug with manual sort order handling.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant