From 572e9706e5bfac21aebafa12cbd1372015a096d0 Mon Sep 17 00:00:00 2001 From: Louis Knight-Webb Date: Mon, 12 Jan 2026 17:14:48 +0000 Subject: [PATCH] Prevent WorkspacesSidebar re-render on workspace switch (Vibe Kanban) (#1973) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * The refactoring is complete. Here's a summary of what was changed: ## Summary **File modified:** `vibe-kanban/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx` **Change:** Restructured `renderContent()` so that `WorkspacesSidebar` is rendered **outside** the `ExecutionProcessesProvider`. ### Before: ```tsx {renderSidebar()} // Inside provider ... ... ... ``` ### After: ```tsx {renderSidebar()} // OUTSIDE provider - won't remount <> ... ... ... ``` **Result:** When switching workspaces, the `ExecutionProcessesProvider`'s key changes, which unmounts/remounts only panes 2-4. The sidebar pane stays mounted and won't re-render unnecessarily. * The implementation is complete. Here's a summary of what was changed: ## Summary **File modified:** `vibe-kanban/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx` ### Changes: 1. **Created nested Allotments structure:** - **Outer Allotment** (2 panes): Sidebar + Content container - **Inner Allotment** (3 panes): Main + Changes/Logs + Git Panel 2. **Separated resize handlers:** - `handleOuterPaneResize`: Handles sidebar width only - `handleInnerPaneResize`: Handles main, changes/logs, and git panel widths 3. **Removed old `handlePaneResize`** which was designed for the flat 4-pane structure ### Result: ``` Outer Allotment ├── Sidebar Pane (OUTSIDE providers - won't remount) └── Content Pane └── ExecutionProcessesProvider (keyed) └── ReviewProvider └── Inner Allotment ├── Main Pane ├── Changes/Logs Pane └── Git Panel Pane ``` Now when switching workspaces: - The `ExecutionProcessesProvider` with its key will remount the inner Allotment (ensuring clean state) - The sidebar stays mounted because it's outside the keyed provider - Layout looks the same as before (sidebar on left, 3 panes on right) --- .../ui-new/containers/WorkspacesLayout.tsx | 116 ++++++++++-------- 1 file changed, 66 insertions(+), 50 deletions(-) diff --git a/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx b/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx index 99640d98..fa67242c 100644 --- a/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx +++ b/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx @@ -495,26 +495,6 @@ export function WorkspacesLayout() { [setFileTreeHeight] ); - // Handle pane resize end - const handlePaneResize = useCallback( - (sizes: number[]) => { - // sizes[0] = sidebar, sizes[1] = main, sizes[2] = changes/logs panel, sizes[3] = git panel - if (sizes[0] !== undefined) setSidebarWidth(sizes[0]); - if (sizes[3] !== undefined) setGitPanelWidth(sizes[3]); - - const total = sizes.reduce((sum, s) => sum + (s ?? 0), 0); - if (total > 0) { - // Store changes/logs panel as percentage of TOTAL container width - const centerPaneWidth = sizes[2]; - if (centerPaneWidth !== undefined) { - const percent = Math.round((centerPaneWidth / total) * 100); - setChangesPanelWidth(`${percent}%`); - } - } - }, - [setSidebarWidth, setGitPanelWidth, setChangesPanelWidth] - ); - // Navigate to logs panel and select a specific process const handleViewProcessInPanel = useCallback( (processId: string) => { @@ -698,23 +678,39 @@ export function WorkspacesLayout() { /> ); + // Handle inner pane resize (main, changes/logs, git panel) + const handleInnerPaneResize = useCallback( + (sizes: number[]) => { + // sizes[0] = main (no persistence needed, uses LayoutPriority.High) + // sizes[1] = changes/logs panel + // sizes[2] = git panel + if (sizes[2] !== undefined) setGitPanelWidth(sizes[2]); + + const total = sizes.reduce((sum, s) => sum + (s ?? 0), 0); + if (total > 0) { + const centerPaneWidth = sizes[1]; + if (centerPaneWidth !== undefined) { + const percent = Math.round((centerPaneWidth / total) * 100); + setChangesPanelWidth(`${percent}%`); + } + } + }, + [setGitPanelWidth, setChangesPanelWidth] + ); + + // Handle outer pane resize (sidebar only) + const handleOuterPaneResize = useCallback( + (sizes: number[]) => { + if (sizes[0] !== undefined) setSidebarWidth(sizes[0]); + }, + [setSidebarWidth] + ); + // Render layout content (create mode or workspace mode) const renderContent = () => { - const allotmentContent = ( - - -
{renderSidebar()}
-
- + // Inner Allotment with panes 2-4 (main, changes/logs, git panel) + const innerAllotment = ( + ); - if (isCreateMode) { - return ( - - - {allotmentContent} - - - ); - } - - return ( + // Wrap inner Allotment with providers + const wrappedInnerContent = isCreateMode ? ( + + + {innerAllotment} + + + ) : ( - {allotmentContent} + {innerAllotment} ); + + return ( + + {/* Sidebar pane - OUTSIDE providers, won't remount on workspace switch */} + +
{renderSidebar()}
+
+ + {/* Container for provider-wrapped inner content */} + + {wrappedInnerContent} + +
+ ); }; return (