Skip to content

feat(desktop): project sidebar shell and Lanes redesign - #1304

Merged
arul28 merged 5 commits into
mainfrom
t3code/web-render-local-dev
Sep 24, 2026
Merged

arul28 merged 5 commits into
mainfrom
t3code/web-render-local-dev

Conversation

@arul28

@arul28 arul28 commented Sep 24, 2026 •

Copy link
Copy Markdown
Owner

Problem

The desktop shell used a top tab rail, and the Lanes tab was a multi-pane cockpit that did not match the Work list.

Change and boundary

One project sidebar now hosts Work, Lanes, Files, PRs, and Automations at a shared width, with CTO and History opening over the page you left. The Lanes tab is a state-grouped sidebar plus one selected lane (dashboard and Git pane). Settings gains an Account section, and the window gradient is limited to the top bar, the Work new-chat pane, and the project picker.

This stays in the desktop renderer, shared keybindings, and one project-config change that drops the unused lane banner budget key. iOS and the TUI do not get this shell.

Verification

  • cd apps/desktop && npx vitest run on the edited renderer files after the quality fixes: 65 passed (ProjectSidebar, PRsPage, lane history, lane sidebar, App keep-alive).
  • After rebasing onto origin/main: TerminalsPage, ProjectSidebar, PRsPage, and App keep-alive, 100 passed.
  • Desktop typecheck was clean on the pre-rebase tree (0 TS errors in the desktop project).

Authored with Grok 4.7 via Cursor.

Made with Cursor


Devin Review

@vercel

vercel Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
ade Ignored Ignored Preview Sep 24, 2026 3:14pm UTC

@coderabbitai

coderabbitai Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 154 files, which is 54 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

Check out review usage here.

⚙️ Run configuration

Configuration used: Repository: arul28/ADE/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 990997dd-377f-4588-98ec-da6157e9fb2d

📥 Commits

Reviewing files that changed from the base of the PR and between 615879b and 8a8bec9.

⛔ Files ignored due to path filters (12)
  • docs/ARCHITECTURE.md is excluded by !docs/**
  • docs/features/chat/README.md is excluded by !docs/**
  • docs/features/cto/README.md is excluded by !docs/**
  • docs/features/lanes/README.md is excluded by !docs/**
  • docs/features/lanes/stacking.md is excluded by !docs/**
  • docs/features/onboarding-and-settings/README.md is excluded by !docs/**
  • docs/features/onboarding-and-settings/configuration-schema.md is excluded by !docs/**
  • docs/features/personal-chats/README.md is excluded by !docs/**
  • docs/features/pull-requests/README.md is excluded by !docs/**
  • docs/features/terminals-and-sessions/README.md is excluded by !docs/**
  • docs/features/terminals-and-sessions/ui-surfaces.md is excluded by !docs/**
  • docs/features/web-client/README.md is excluded by !docs/**
📒 Files selected for processing (154)
  • apps/desktop/lint-baseline.json
  • apps/desktop/src/main/services/config/projectConfigService.ts
  • apps/desktop/src/renderer/browserMock.ts
  • apps/desktop/src/renderer/components/account/AccountAvatar.tsx
  • apps/desktop/src/renderer/components/account/AccountPage.tsx
  • apps/desktop/src/renderer/components/account/AccountSignedOutBanner.test.tsx
  • apps/desktop/src/renderer/components/account/AccountSignedOutBanner.tsx
  • apps/desktop/src/renderer/components/account/YourMacsCard.tsx
  • apps/desktop/src/renderer/components/app/App.tsx
  • apps/desktop/src/renderer/components/app/App.workKeepAlive.test.tsx
  • apps/desktop/src/renderer/components/app/AppShell.aiStatus.test.tsx
  • apps/desktop/src/renderer/components/app/AppShell.tsx
  • apps/desktop/src/renderer/components/app/CursorCloudFleetRow.tsx
  • apps/desktop/src/renderer/components/app/CursorCloudQuickViewButton.tsx
  • apps/desktop/src/renderer/components/app/SettingsPage.test.tsx
  • apps/desktop/src/renderer/components/app/SettingsPage.tsx
  • apps/desktop/src/renderer/components/app/TabNav.test.tsx
  • apps/desktop/src/renderer/components/app/TabNav.tsx
  • apps/desktop/src/renderer/components/app/TopBar.test.tsx
  • apps/desktop/src/renderer/components/app/TopBar.tsx
  • apps/desktop/src/renderer/components/app/commandPaletteWork.tsx
  • apps/desktop/src/renderer/components/app/projectSidebar/ProjectSidebar.test.tsx
  • apps/desktop/src/renderer/components/app/projectSidebar/ProjectSidebar.tsx
  • apps/desktop/src/renderer/components/app/projectSidebar/ProjectSidebarSlot.tsx
  • apps/desktop/src/renderer/components/app/projectSidebar/ProjectSidebarToggle.tsx
  • apps/desktop/src/renderer/components/app/projectSidebar/projectSidebarPrefs.ts
  • apps/desktop/src/renderer/components/app/projectSidebar/projectSidebarTabs.ts
  • apps/desktop/src/renderer/components/app/projectSidebar/settingsReturnRoute.ts
  • apps/desktop/src/renderer/components/app/projectSidebar/useProjectSidebarShortcuts.test.tsx
  • apps/desktop/src/renderer/components/app/projectSidebar/useProjectSidebarShortcuts.ts
  • apps/desktop/src/renderer/components/automations/AdeActionEditor.tsx
  • apps/desktop/src/renderer/components/automations/AutomationsPage.tsx
  • apps/desktop/src/renderer/components/automations/AutomationsTemplatesPage.tsx
  • apps/desktop/src/renderer/components/automations/AutomationsWorkspace.tsx
  • apps/desktop/src/renderer/components/automations/builder/StepStack.tsx
  • apps/desktop/src/renderer/components/automations/builder/VariableMenu.tsx
  • apps/desktop/src/renderer/components/automations/list/RuleList.tsx
  • apps/desktop/src/renderer/components/automations/templates/TemplateGallery.tsx
  • apps/desktop/src/renderer/components/automations/templates/draftHandoff.ts
  • apps/desktop/src/renderer/components/cto/CtoPage.tsx
  • apps/desktop/src/renderer/components/cto/CtoSettingsPage.tsx
  • apps/desktop/src/renderer/components/cto/CtoTalkButton.tsx
  • apps/desktop/src/renderer/components/files/FilesExplorer.tsx
  • apps/desktop/src/renderer/components/files/v2/EditorGroup.tsx
  • apps/desktop/src/renderer/components/files/v2/EditorGroups.tsx
  • apps/desktop/src/renderer/components/files/v2/FilesWorkbench.test.tsx
  • apps/desktop/src/renderer/components/files/v2/FilesWorkbench.tsx
  • apps/desktop/src/renderer/components/history/HistoryPage.tsx
  • apps/desktop/src/renderer/components/history/TimelineToolbar.tsx
  • apps/desktop/src/renderer/components/lanes/CommitTimeline.tsx
  • apps/desktop/src/renderer/components/lanes/LaneAgentList.tsx
  • apps/desktop/src/renderer/components/lanes/LaneDiffPane.test.tsx
  • apps/desktop/src/renderer/components/lanes/LaneDiffPane.tsx
  • apps/desktop/src/renderer/components/lanes/LaneGitActionsPane.test.tsx
  • apps/desktop/src/renderer/components/lanes/LaneGitActionsPane.tsx
  • apps/desktop/src/renderer/components/lanes/LaneRebaseBanner.test.tsx
  • apps/desktop/src/renderer/components/lanes/LaneRebaseBanner.tsx
  • apps/desktop/src/renderer/components/lanes/LaneStackPane.tsx
  • apps/desktop/src/renderer/components/lanes/LaneWorkPane.tsx
  • apps/desktop/src/renderer/components/lanes/LanesPage.test.ts
  • apps/desktop/src/renderer/components/lanes/LanesPage.tsx
  • apps/desktop/src/renderer/components/lanes/ManageLaneDialog.test.tsx
  • apps/desktop/src/renderer/components/lanes/ManageLaneDialog.tsx
  • apps/desktop/src/renderer/components/lanes/PushDivergenceGuard.test.tsx
  • apps/desktop/src/renderer/components/lanes/detail/LaneBranchSwitcher.tsx
  • apps/desktop/src/renderer/components/lanes/detail/LaneSplitBody.tsx
  • apps/desktop/src/renderer/components/lanes/laneAgents.test.ts
  • apps/desktop/src/renderer/components/lanes/laneAgents.ts
  • apps/desktop/src/renderer/components/lanes/lanePageModel.ts
  • apps/desktop/src/renderer/components/lanes/laneUtils.test.ts
  • apps/desktop/src/renderer/components/lanes/laneUtils.ts
  • apps/desktop/src/renderer/components/lanes/overview/LaneChangesSection.tsx
  • apps/desktop/src/renderer/components/lanes/overview/LaneChatsSection.tsx
  • apps/desktop/src/renderer/components/lanes/overview/LaneDashboard.test.tsx
  • apps/desktop/src/renderer/components/lanes/overview/LaneDashboard.tsx
  • apps/desktop/src/renderer/components/lanes/overview/LaneHistoryFeed.tsx
  • apps/desktop/src/renderer/components/lanes/overview/LaneIdentity.tsx
  • apps/desktop/src/renderer/components/lanes/overview/LanePrSection.tsx
  • apps/desktop/src/renderer/components/lanes/overview/LaneStackSection.tsx
  • apps/desktop/src/renderer/components/lanes/overview/laneHistoryModel.test.ts
  • apps/desktop/src/renderer/components/lanes/overview/laneHistoryModel.ts
  • apps/desktop/src/renderer/components/lanes/overview/laneOverviewModel.test.ts
  • apps/desktop/src/renderer/components/lanes/overview/laneOverviewModel.ts
  • apps/desktop/src/renderer/components/lanes/overview/sectionUi.tsx
  • apps/desktop/src/renderer/components/lanes/overview/useLaneOverviewData.ts
  • apps/desktop/src/renderer/components/lanes/sidebar/LaneSidebarBulkRebaseDialog.tsx
  • apps/desktop/src/renderer/components/lanes/sidebar/LaneSidebarContextMenu.tsx
  • apps/desktop/src/renderer/components/lanes/sidebar/LaneSidebarGroupHeader.tsx
  • apps/desktop/src/renderer/components/lanes/sidebar/LaneSidebarList.test.tsx
  • apps/desktop/src/renderer/components/lanes/sidebar/LaneSidebarList.tsx
  • apps/desktop/src/renderer/components/lanes/sidebar/LaneSidebarPrChip.tsx
  • apps/desktop/src/renderer/components/lanes/sidebar/LaneSidebarRow.test.tsx
  • apps/desktop/src/renderer/components/lanes/sidebar/LaneSidebarRow.tsx
  • apps/desktop/src/renderer/components/lanes/sidebar/PointMenu.tsx
  • apps/desktop/src/renderer/components/lanes/sidebar/laneSidebarModel.test.ts
  • apps/desktop/src/renderer/components/lanes/sidebar/laneSidebarModel.ts
  • apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.test.ts
  • apps/desktop/src/renderer/components/lanes/useLaneWorkSessions.ts
  • apps/desktop/src/renderer/components/onboarding/HelpMenu.tsx
  • apps/desktop/src/renderer/components/projects/ProjectWelcomePage.tsx
  • apps/desktop/src/renderer/components/prs/PRsPage.test.tsx
  • apps/desktop/src/renderer/components/prs/PRsPage.tsx
  • apps/desktop/src/renderer/components/prs/shared/GitHubPrSearchInput.tsx
  • apps/desktop/src/renderer/components/prs/shared/GitHubRepoSyncBar.tsx
  • apps/desktop/src/renderer/components/prs/shared/PrMergeDialog.tsx
  • apps/desktop/src/renderer/components/prs/shared/PrReactionBar.tsx
  • apps/desktop/src/renderer/components/prs/shared/PrsListHost.tsx
  • apps/desktop/src/renderer/components/prs/tabs/GitHubTab.tsx
  • apps/desktop/src/renderer/components/prs/tabs/GitHubTabView.tsx
  • apps/desktop/src/renderer/components/prs/tabs/IntegrationTab.tsx
  • apps/desktop/src/renderer/components/prs/tabs/RebaseTab.tsx
  • apps/desktop/src/renderer/components/prs/tabs/WorkflowsTab.tsx
  • apps/desktop/src/renderer/components/settings/NotificationsSection.test.tsx
  • apps/desktop/src/renderer/components/settings/NotificationsSection.tsx
  • apps/desktop/src/renderer/components/settings/SettingsSidebarHeader.tsx
  • apps/desktop/src/renderer/components/settings/providers/accounts/ProviderAccountsPanel.tsx
  • apps/desktop/src/renderer/components/settings/settingsManifest.ts
  • apps/desktop/src/renderer/components/shared/AdeDiffViewer.tsx
  • apps/desktop/src/renderer/components/terminals/SessionListPane.test.tsx
  • apps/desktop/src/renderer/components/terminals/SessionListPane.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalsPage.test.tsx
  • apps/desktop/src/renderer/components/terminals/TerminalsPage.tsx
  • apps/desktop/src/renderer/components/terminals/WorkKanbanBoard.test.tsx
  • apps/desktop/src/renderer/components/terminals/WorkKanbanBoard.tsx
  • apps/desktop/src/renderer/components/terminals/WorkToolPickerBackdrop.test.tsx
  • apps/desktop/src/renderer/components/terminals/WorkToolPickerBackdrop.tsx
  • apps/desktop/src/renderer/components/terminals/WorkViewArea.tsx
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.test.ts
  • apps/desktop/src/renderer/components/terminals/useWorkSessions.ts
  • apps/desktop/src/renderer/components/terminals/workToolPanels.tsx
  • apps/desktop/src/renderer/components/terminals/workToolPickerBackdropRenderer.ts
  • apps/desktop/src/renderer/components/terminals/workToolPickerBackdropShader.ts
  • apps/desktop/src/renderer/components/ui/AnchoredMenu.test.tsx
  • apps/desktop/src/renderer/components/ui/AnchoredMenu.tsx
  • apps/desktop/src/renderer/components/work/SessionLifecycleChips.tsx
  • apps/desktop/src/renderer/components/work/WorkSurfaceHeader.test.tsx
  • apps/desktop/src/renderer/components/work/WorkSurfaceHeader.tsx
  • apps/desktop/src/renderer/index.css
  • apps/desktop/src/renderer/lib/appZoom.ts
  • apps/desktop/src/renderer/lib/laneNavigation.ts
  • apps/desktop/src/renderer/lib/layoutSettle.test.ts
  • apps/desktop/src/renderer/lib/layoutSettle.ts
  • apps/desktop/src/renderer/lib/scrollingIndicator.test.ts
  • apps/desktop/src/renderer/lib/scrollingIndicator.ts
  • apps/desktop/src/renderer/lib/terminalAttention.ts
  • apps/desktop/src/renderer/lib/webClientMode.ts
  • apps/desktop/src/renderer/main.tsx
  • apps/desktop/src/renderer/state/appStore.test.ts
  • apps/desktop/src/renderer/state/appStore.ts
  • apps/desktop/src/renderer/webclient/main.tsx
  • apps/desktop/src/shared/keybindings.ts
  • apps/desktop/src/shared/types/config.ts
  • getting-started/first-lane.mdx
  • lanes/stacks.mdx

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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.

@devin-ai-integration devin-ai-integration 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.

Note

Newer findings are available below. Devin Review posted a newer report on this PR, in addition to the findings presented here.

Devin Review found 3 potential issues.

2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

Comment on lines +489 to +492
const detailLaneId = useMemo(() => {
if (selectedLaneId && lanesById.has(selectedLaneId) && !deletingLaneIds.has(selectedLaneId)) return selectedLaneId;
return selectableFilteredLaneIds[0] ?? sortedSelectableLaneIds[0] ?? null;
}, [selectedLaneId, lanesById, deletingLaneIds, selectableFilteredLaneIds, sortedSelectableLaneIds]);

@devin-ai-integration devin-ai-integration Bot Sep 24, 2026 •

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.

🟡 Collapsed matches leave lane dashboard blank

When a filter matches only collapsed-group lanes, selectableFilteredLaneIds is empty and the selected lane can fall outside the filter. detailLaneId becomes null despite matching lanes, leaving the dashboard blank.

Learn more

The sidebar builds selectableFilteredLaneIds from laneSidebarVisibleLaneIds, which excludes collapsed State groups. Filtering can match lanes whose group is collapsed, leaving that list empty. In that case, the new selection branch discards the previous selection but cannot choose a matching replacement.

Example: Select lane A, collapse the Behind group containing lane B, then search for B. B matches the filter, but the dashboard is blank because no visible row qualifies.

Recommended fix: When a filter matches lanes but none have visible rows, either expand the matching group before choosing a lane or fall back to a non-deleting ID from filteredLanes; ensure the resulting selection can be revealed.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread apps/desktop/src/renderer/components/lanes/detail/LaneSplitBody.tsx Outdated
Comment thread apps/desktop/src/renderer/components/lanes/overview/LaneDashboard.tsx Outdated
arul28 and others added 2 commits September 24, 2026 10:35
Replace the hover rail with one fixed-width project sidebar. It has a tab
strip (Work, Lanes, Files, PRs, Automations), a body that each tab fills
through a portal, and a footer with CTO, History and Settings.

- Top bar: sidebar toggle, project tabs, status. The window gradient now
  covers the top bar, the new chat pane and the welcome screen as one field.
- Settings: an Account section, and feedback, help and zoom in its sidebar.
- CTO and History open over the page you were on. The sidebar stays as it
  was, and the footer becomes one Back button.
- Lanes: the sidebar lane list is the lane manager. It groups lanes by
  state, has a State or Stack toggle and bulk actions on group headers.
  The main area shows the selected lane with the Git pane beside it.
- Work, Files, PRs and Automations lists live in the sidebar. Headers share
  one rail height. Scrollbars show only while scrolling. Menus that could
  be clipped now open on top of the page.
- Remove dead code: the old rail, the Git pane page skin, the gradient
  header variant, the lane Work pane and the lane banner budget setting.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@arul28
arul28 force-pushed the t3code/web-render-local-dev branch from 2aa98c5 to 2fca71a Compare September 24, 2026 14:38
Co-authored-by: Cursor <cursoragent@cursor.com>

@devin-ai-integration devin-ai-integration 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.

Devin Review found 3 new potential issues.

4 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

}, [laneId]);

const prs = useLaneOverviewPrs(lane);
const { current: currentPr, earlier: earlierPrs } = useMemo(() => splitLanePrs(prs.all), [prs.all]);

@devin-ai-integration devin-ai-integration Bot Sep 24, 2026 •

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.

🟡 Historical pull requests disappear from dashboard

When a lane has only earlier-branch PRs, splitLanePrs(prs.current) returns no prominent PR. The PR section requires currentPr, so none of those PRs appear on the dashboard.

Learn more

The lane PR hook separates current-branch PRs from the historical collection in useLaneOverviewPrs. The PR section renders only when currentPr exists in LaneDashboard. Choosing the prominent PR solely from prs.current leaves that section empty when the branch has changed but earlier PRs still belong to the lane.

Example: A lane once had PR #12 on feature/old and now points at feature/new, which has no PR. prs.current is empty and prs.all contains #12; the dashboard shows no PR section instead of #12.

Recommended fix: Fall back to splitLanePrs(prs.all).current when prs.current is empty, then exclude that PR from the earlier list. Preserve current-branch priority when current PRs exist.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

}, [commits, historySessions, lane, operations, prs.all, trailerProviderBySha]);
const filtered = useMemo(() => filterLaneHistory(history, filter), [filter, history]);
// The primary lane's commit list is paged, so a full page may hide older rows.
const hasMoreCommits = lane?.laneType === "primary" && commits.length >= commitLimit;

@devin-ai-integration devin-ai-integration Bot Sep 24, 2026 •

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.

🟡 Git pane collapses to zero width

In a narrow window, dragging the splitter right lets clampGitColumnWidth return zero. The Git pane disappears, and its saved width resets on reload because readStoredWidth rejects zero.

Learn more

The splitter calls clampGitColumnWidth on every mouse move and saves the resulting value on release. With an 800px container, dragging far right sends a negative requested width; the narrow-window branch clamps it to zero. readStoredWidth ignores zero on the next mount, so the pane then returns at its default size.

Example: At 800px, drag the divider fully right. The Git pane reaches 0px rather than retaining a usable minimum and resets after restarting.

Recommended fix: Set a positive Git minimum for narrow containers that fits alongside a dashboard minimum; clamp both panes to feasible sizes for very small container widths. Keep persisted-width behavior consistent with the permitted minimum.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

arul28 and others added 2 commits September 24, 2026 10:56
Co-authored-by: Cursor <cursoragent@cursor.com>
…lit honest

Co-authored-by: Cursor <cursoragent@cursor.com>
@arul28
arul28 merged commit f00b1b6 into main Sep 24, 2026
40 checks passed
@arul28
arul28 deleted the t3code/web-render-local-dev branch September 24, 2026 15:30
arul28 added a commit that referenced this pull request Sep 24, 2026
Take main's sidebar and Lanes redesign (#1304) and unified notices (#1305):
- The Mac Desktop hover peek moves into the new lane sidebar row.
- The reconnect sign-in link rides in the shared Banner's detail.
- The Apple strip takes main's Banner; the Mac Desktop strip moves to the
  same Banner, and the now-unused shared ToolStatusStrip shell is removed.
- The backdrop keeps main's field slicing (no header-only constants) plus
  this lane's render scale and idle freeze.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant