Skip to content

Refactor sidebar and chat boundaries to reduce rerenders#1890

Open
justsomelegs wants to merge 17 commits intopingdotgg:mainfrom
justsomelegs:legs/sidebar-rerenders
Open

Refactor sidebar and chat boundaries to reduce rerenders#1890
justsomelegs wants to merge 17 commits intopingdotgg:mainfrom
justsomelegs:legs/sidebar-rerenders

Conversation

@justsomelegs
Copy link
Copy Markdown
Contributor

@justsomelegs justsomelegs commented Apr 10, 2026

What Changed

Refactored both the sidebar and chat surfaces to make updates more atomic, reduce broad rerender paths, and preserve behavior in the diff/timeline flows that were touched along the way.

Before:
latest.before.on.main.mp4
After:
new.after.mp4

Main changes:

  • Split sidebar state access so rows, project sections, and keyboard hint UI subscribe closer to where data is rendered
  • Added sidebar-specific selector/controller modules for project ordering, thread row snapshots, keyboard traversal, and sidebar-local view state
  • Moved volatile thread UI like shortcut hints, running state, and relative activity time into smaller leaf components/selectors
  • Removed the mirrored project-ordering path through the sidebar view store and now derive ordered project keys directly from source state
  • Tightened logical project key typing across the sidebar so grouped project keys stay distinct from physical project IDs
  • Narrowed chat subscriptions by splitting large thread reads into smaller runtime/message/timeline selectors
  • Separated historical vs live timeline rendering so streaming updates and active-turn UI do not force broad timeline rerenders
  • Reduced composer/chat rerender fanout around optimistic messages, connection state, markdown rows, and current-thread runtime reads
  • Cleaned up selector duplication/dead code introduced during the rerender work
  • Fixed three regressions found during branch audit:
    • full-conversation diffs now retry transient checkpoint-not-ready errors again
    • diff panel git-repo detection now uses the resolved thread/project cwd consistently
    • historical timeline rows now render correctly in non-virtual/static environments while keeping the browser fast path virtualized

Files added/extracted:

  • apps/web/src/components/sidebar/sidebarConstants.ts
  • apps/web/src/components/sidebar/sidebarControllers.tsx
  • apps/web/src/components/sidebar/sidebarProjectSnapshots.ts
  • apps/web/src/components/sidebar/sidebarSelectors.ts
  • apps/web/src/components/sidebar/sidebarViewStore.ts
  • apps/web/src/components/chat/MessagesTimelineContainer.tsx

Files heavily updated:

  • apps/web/src/components/Sidebar.tsx
  • apps/web/src/components/Sidebar.logic.ts
  • apps/web/src/components/ChatView.tsx
  • apps/web/src/components/chat/MessagesTimeline.tsx
  • apps/web/src/components/DiffPanel.tsx
  • apps/web/src/storeSelectors.ts
  • apps/web/src/logicalProject.ts
  • apps/web/src/lib/providerReactQuery.ts

Why

The sidebar and chat surfaces were still subscribed to state that was broader than necessary. In practice that meant:

  • switching threads rerendered too much of the sidebar
  • holding Ctrl for jump hints rerendered more than the affected thread metadata
  • streaming chat updates caused broader sidebar/chat work than needed
  • active timeline updates were invalidating more of the message list than necessary
  • some one-off synchronous state reads were rebuilding selector scaffolding without getting real memoization benefit

This change narrows subscriptions, moves derived and volatile state closer to leaf components, and splits hot chat/timeline state from colder historical state. The result is less work during streaming, thread switching, and sidebar interaction, while keeping end-user behavior consistent.

The follow-up audit fixes are included here because they were caused by this refactor and are part of making the branch PR-ready rather than leaving known correctness regressions behind.

UI Changes

Behavior is visually mostly unchanged. The main user-facing goal is narrower update scope and smoother behavior under load, especially in:

  • sidebar thread switching
  • sidebar shortcut hint display
  • chat streaming / active-turn updates
  • timeline rendering
  • diff panel loading for whole-conversation diffs

Validation

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test -- src/lib/providerReactQuery.test.ts src/lib/gitStatusState.test.ts src/components/chat/MessagesTimeline.test.tsx src/components/ChatView.logic.test.ts

Note:

  • bun lint still reports the same pre-existing warning in apps/web/src/environments/runtime/catalog.test.ts:98

Checklist

  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes
  • I validated formatting, linting, and typechecking

Note

Reduce sidebar and chat rerenders by decomposing components and introducing targeted store selectors

  • Splits MessagesTimeline into historical and live sections, with MessagesTimelineContainer orchestrating data assembly and ChatMessagesPane encapsulating scroll/optimistic-message logic behind an imperative ref.
  • Introduces scoped snapshot selectors (e.g. createThreadBranchToolbarSnapshotSelectorByRef, createThreadBranchActionSnapshotSelectorByRef, createThreadStaticShellSelectorByRef) that return stable minimal objects, limiting rerenders to only the fields each component actually needs.
  • Refactors SidebarThreadRow to be self-contained — resolving its own data, navigation, context-menu actions, rename/archive flows, and status indicators via new sidebar selectors and a new sidebarViewStore.
  • Extracts sidebar keyboard and selection logic into SidebarKeyboardController and SidebarSelectionController; project snapshots and sorting are now built via buildSidebarProjectSnapshots and createSidebarSortedProjectKeysSelector.
  • Moves send/interrupt handlers in ChatView to useEffectEvent-backed functions reading latest snapshots via store getters, reducing stale-closure risk.
  • Risk: MessagesTimeline callers must now supply separate historicalTimelineEntries and liveTimelineEntries props; ChatComposer consumers must supply draftThreadActivities and no longer pass activeThread.

Macroscope summarized 5371a21.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 10, 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: a6581bca-3462-473f-b7a7-ae0e4ace0570

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:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list. labels Apr 10, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp bot commented Apr 10, 2026

Approvability

Verdict: Needs human review

Diff is too large for automated approval analysis. A human reviewer should evaluate this PR.

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

@juliusmarminge
Copy link
Copy Markdown
Member

is the before here from the latest version? i did a bunch of fixes for this release. it shouldn't be like that

@justsomelegs
Copy link
Copy Markdown
Contributor Author

yeah it was from the latest version of main, the chat composer was fixed but the sidebar would re-render on every update just cause it was not using the new atomic stores in the best way.

@justsomelegs
Copy link
Copy Markdown
Contributor Author

justsomelegs commented Apr 10, 2026

correction it was 3 commits behind but it still does now after pulling those down unless, i could be wrong though let me know :)

@justsomelegs justsomelegs force-pushed the legs/sidebar-rerenders branch from c7c7f99 to 6764399 Compare April 11, 2026 20:54
@justsomelegs justsomelegs changed the title Refactor sidebar rerender boundaries anad reduce the re-renders Refactor sidebar and chat boundaries to reduce rerenders Apr 11, 2026
# Conflicts:
#	apps/web/src/components/ChatView.tsx
#	apps/web/src/components/Sidebar.logic.ts
#	apps/web/src/components/Sidebar.tsx
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:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants