Skip to content

Sort sidebar projects and threads by recency#1372

Merged
juliusmarminge merged 6 commits intomainfrom
t3code/updated-sort-order
Mar 24, 2026
Merged

Sort sidebar projects and threads by recency#1372
juliusmarminge merged 6 commits intomainfrom
t3code/updated-sort-order

Conversation

@juliusmarminge
Copy link
Member

@juliusmarminge juliusmarminge commented Mar 24, 2026

Summary

  • Added configurable sidebar sort orders for projects and threads, with new app settings defaults.
  • Implemented shared sidebar sorting logic that ranks projects and threads by recency, falling back to creation time or manual order where appropriate.
  • Updated the sidebar UI to use the new ordering, disable drag reordering outside manual mode, and add a sort menu for changing project/thread sort behavior.
  • Added tests covering the new settings defaults and sidebar sorting behavior.

Testing

  • Not run (PR content only).
  • Added unit coverage for sidebar project/thread sorting logic in apps/web/src/components/Sidebar.logic.test.ts.
  • Added settings schema/default coverage in apps/web/src/appSettings.test.ts and store coverage in apps/web/src/store.test.ts.

Note

Medium Risk
Changes sidebar ordering behavior and gates drag-and-drop reordering behind a new setting, which could affect navigation expectations and any code relying on previous stable ordering.

Overview
Adds configurable sidebar sorting for projects and threads. New app settings sidebarProjectSortOrder and sidebarThreadSortOrder (default updated_at) are introduced and covered by tests.

Sidebar rendering now uses shared helpers (sortProjectsForSidebar, sortThreadsForSidebar) to order by latest user message recency with fallbacks to updatedAt/createdAt (or manual order for projects), and ensures the active thread stays visible in the collapsed preview.

Projects/threads now carry createdAt/updatedAt from the server read model into local Project/Thread state, the sidebar UI adds a sort menu, disables drag reordering unless in manual mode, and animates list changes via @formkit/auto-animate.

Written by Cursor Bugbot for commit a3bb36c. This will update automatically on new commits. Configure here.

Note

Sort sidebar projects and threads by recency with configurable sort order

  • Adds sortProjectsForSidebar and sortThreadsForSidebar functions in Sidebar.logic.ts that order items by latest user message timestamp, falling back to updatedAt/createdAt.
  • Introduces sidebarProjectSortOrder and sidebarThreadSortOrder app settings (default updated_at) with a new ProjectSortMenu UI in the sidebar header to change them.
  • Propagates createdAt/updatedAt from the server read model into Project and Thread state objects so sort timestamps are available.
  • Adds @formkit/auto-animate to animate list reordering; drag-and-drop manual reordering is disabled unless the sort order is set to Manual.
  • Collapsed thread lists now always include the active thread even if it falls beyond the preview limit.

Macroscope summarized a3bb36c.

- Add configurable project and thread sidebar sort orders
- Keep manual project reordering when enabled
- Animate sidebar list updates and cover new sort logic with tests
@coderabbitai
Copy link

coderabbitai bot commented Mar 24, 2026

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: 120b7f4d-a36b-4dc8-bf5c-39eba48cf0ab

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
  • Commit unit tests in branch t3code/updated-sort-order

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

@github-actions github-actions bot added size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Mar 24, 2026
- Avoid cloning thread arrays before sorting
- Cache loaded project favicons across sidebar renders
- Update sidebar sort labels for clearer wording
Copy link
Contributor

@cursor cursor bot left a comment

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.

There are 2 total unresolved issues (including 1 from previous review).

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: NaN comparator skips tiebreaker in project sorting
    • Added a !Number.isNaN(byTimestamp) guard to the comparator condition so that when both projects resolve to NEGATIVE_INFINITY the NaN result falls through to the name/id tiebreaker.

Create PR

Or push these changes by commenting:

@cursor push 659ca5e71b
Preview (659ca5e71b)
diff --git a/apps/web/src/components/Sidebar.logic.ts b/apps/web/src/components/Sidebar.logic.ts
--- a/apps/web/src/components/Sidebar.logic.ts
+++ b/apps/web/src/components/Sidebar.logic.ts
@@ -270,7 +270,7 @@
     const byTimestamp =
       getProjectSortTimestamp(right, threadsByProjectId.get(right.id) ?? [], sortOrder) -
       getProjectSortTimestamp(left, threadsByProjectId.get(left.id) ?? [], sortOrder);
-    if (byTimestamp !== 0) return byTimestamp;
+    if (byTimestamp !== 0 && !Number.isNaN(byTimestamp)) return byTimestamp;
     return left.name.localeCompare(right.name) || left.id.localeCompare(right.id);
   });
 }

- Keep the current thread visible in folded project thread lists
- Extract shared visible-thread selection logic and cover it with tests
- Treat missing or invalid timestamps as absent instead of zero
- Fall back to name and id ordering when projects have no sortable dates
- Add coverage for timestamp-less project sorting
Copy link
Contributor

@cursor cursor bot left a comment

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 prepared a fix for the issue found in the latest run.

  • ✅ Fixed: NaN from NEGATIVE_INFINITY subtraction breaks sort tiebreaker
    • Replaced subtraction-based comparison with explicit equality/greater-than checks (matching sortProjectsForSidebar), so two NEGATIVE_INFINITY values correctly produce 0 and fall through to the ID tiebreaker.

Create PR

Or push these changes by commenting:

@cursor push e09809f495
Preview (e09809f495)
diff --git a/apps/web/src/components/Sidebar.logic.ts b/apps/web/src/components/Sidebar.logic.ts
--- a/apps/web/src/components/Sidebar.logic.ts
+++ b/apps/web/src/components/Sidebar.logic.ts
@@ -270,8 +270,10 @@
   T extends Pick<Thread, "id" | "createdAt" | "updatedAt" | "messages">,
 >(threads: readonly T[], sortOrder: SidebarThreadSortOrder): T[] {
   return threads.toSorted((left, right) => {
+    const rightTimestamp = getThreadSortTimestamp(right, sortOrder);
+    const leftTimestamp = getThreadSortTimestamp(left, sortOrder);
     const byTimestamp =
-      getThreadSortTimestamp(right, sortOrder) - getThreadSortTimestamp(left, sortOrder);
+      rightTimestamp === leftTimestamp ? 0 : rightTimestamp > leftTimestamp ? 1 : -1;
     if (byTimestamp !== 0) return byTimestamp;
     return right.id.localeCompare(left.id);
   });

- Rename the sort timestamp test to better describe the no-threads fallback
- No behavior change
- Preserve deterministic id ordering when timestamps are missing
- Add coverage for updated_at sort fallback
@juliusmarminge juliusmarminge merged commit 28afb14 into main Mar 24, 2026
11 checks passed
@juliusmarminge juliusmarminge deleted the t3code/updated-sort-order branch March 24, 2026 19:40
waaeel added a commit to dinweldik/fatma that referenced this pull request Mar 25, 2026
Merged upstream improvements while preserving fork identity:
- Claude Code adapter support (pingdotgg#179)
- Context window usage meter (pingdotgg#1351)
- Sidebar project/thread sorting by recency (pingdotgg#1372)
- Git action progress streaming (pingdotgg#1214, pingdotgg#1388)
- Terminal history ANSI preservation (pingdotgg#1367)
- Word wrapping setting (pingdotgg#1326)
- Resizable chat sidebar (pingdotgg#1347)
- Configurable timestamp format (pingdotgg#855)
- Selective file staging in commit dialog (pingdotgg#872)
- Fuzzy workspace search (pingdotgg#256)
- Scroll-to-bottom pill (pingdotgg#619)
- Numerous bug fixes and improvements

Preserved fork customizations:
- Fatma branding (all @t3tools -> @fatma)
- Mobile UI (swipe gestures, bottom nav, mobile shells)
- VSCode-like source control (staged/unstaged, file diffs)
- PWA support
- Custom CI/CD workflows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
kkorenn pushed a commit to kkorenn/k1code that referenced this pull request Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant