Always show a panel (#1988)

## Summary

**Fixed:** Invalid layout state where only left and right sidebars are visible (no main content area).

### Changes Made:

**1. `frontend/src/stores/useLayoutStore.ts`**
- Added `setMainPanelVisible` setter function to the type and implementation
- Added `useIsRightMainPanelVisible` derived selector hook that checks if Changes/Logs/Preview panel is visible

**2. `frontend/src/components/ui-new/containers/WorkspacesLayout.tsx`**
- Imported `useIsRightMainPanelVisible` from the layout store
- Added `setMainPanelVisible` to the destructured store values
- Replaced verbose `isChangesMode || isLogsMode || isPreviewMode` checks with the helper
- Added guard effect that ensures the left main panel (chat) is visible when the right main panel is hidden - this prevents the invalid state after page reload

The guard effect automatically opens the main panel whenever the layout would otherwise show only sidebars:

```typescript
// Ensure left main panel (chat) is visible when right main panel is hidden
// This prevents invalid state where only sidebars are visible after page reload
useEffect(() => {
  if (!isMainPanelVisible && !isRightMainPanelVisible) {
    setMainPanelVisible(true);
  }
}, [isMainPanelVisible, isRightMainPanelVisible, setMainPanelVisible]);
```
This commit is contained in:
Louis Knight-Webb
2026-01-12 23:18:14 +00:00
committed by GitHub
parent aad1bd092b
commit d9fa2d1fa5
2 changed files with 30 additions and 11 deletions

View File

@@ -40,7 +40,10 @@ import {
useExpandedAll,
PERSIST_KEYS,
} from '@/stores/useUiPreferencesStore';
import { useLayoutStore } from '@/stores/useLayoutStore';
import {
useLayoutStore,
useIsRightMainPanelVisible,
} from '@/stores/useLayoutStore';
import { useDiffViewStore } from '@/stores/useDiffViewStore';
import { CommandBarDialog } from '@/components/ui-new/dialogs/CommandBarDialog';
import { useCommandBarShortcut } from '@/hooks/useCommandBarShortcut';
@@ -281,8 +284,12 @@ export function WorkspacesLayout() {
setLogsMode,
resetForCreateMode,
setSidebarVisible,
setMainPanelVisible,
} = useLayoutStore();
// Derived state: right main panel (Changes/Logs/Preview) is visible
const isRightMainPanelVisible = useIsRightMainPanelVisible();
// Read persisted draft for sidebar placeholder (works outside of CreateModeProvider)
const { scratch: draftScratch } = useScratch(
ScratchType.DRAFT_WORKSPACE,
@@ -435,16 +442,13 @@ export function WorkspacesLayout() {
// Ref to Allotment for programmatic control
const allotmentRef = useRef<AllotmentHandle>(null);
// Reset Allotment sizes when changes, logs, or preview panel becomes visible
// Reset Allotment sizes when right main panel becomes visible
// This re-applies preferredSize percentages based on current window size
useEffect(() => {
if (
(isChangesMode || isLogsMode || isPreviewMode) &&
allotmentRef.current
) {
if (isRightMainPanelVisible && allotmentRef.current) {
allotmentRef.current.reset();
}
}, [isChangesMode, isLogsMode, isPreviewMode]);
}, [isRightMainPanelVisible]);
// Reset changes and logs mode when entering create mode
useEffect(() => {
@@ -453,12 +457,20 @@ export function WorkspacesLayout() {
}
}, [isCreateMode, resetForCreateMode]);
// Show sidebar when no panel is open
// Show sidebar when right main panel is hidden
useEffect(() => {
if (!isChangesMode && !isLogsMode && !isPreviewMode) {
if (!isRightMainPanelVisible) {
setSidebarVisible(true);
}
}, [isChangesMode, isLogsMode, isPreviewMode, setSidebarVisible]);
}, [isRightMainPanelVisible, setSidebarVisible]);
// Ensure left main panel (chat) is visible when right main panel is hidden
// This prevents invalid state where only sidebars are visible after page reload
useEffect(() => {
if (!isMainPanelVisible && !isRightMainPanelVisible) {
setMainPanelVisible(true);
}
}, [isMainPanelVisible, isRightMainPanelVisible, setMainPanelVisible]);
// Command bar keyboard shortcut (CMD+K)
const handleOpenCommandBar = useCallback(() => {
@@ -748,7 +760,7 @@ export function WorkspacesLayout() {
<Allotment.Pane
minSize={300}
preferredSize={changesPanelWidth}
visible={isChangesMode || isLogsMode || isPreviewMode}
visible={isRightMainPanelVisible}
>
<div className="h-full overflow-hidden">
{isChangesMode && (

View File

@@ -26,6 +26,7 @@ type LayoutState = {
setLogsMode: (value: boolean) => void;
setPreviewMode: (value: boolean) => void;
setSidebarVisible: (value: boolean) => void;
setMainPanelVisible: (value: boolean) => void;
// Preview actions
triggerPreviewRefresh: () => void;
@@ -168,6 +169,8 @@ export const useLayoutStore = create<LayoutState>()(
setSidebarVisible: (value) => set({ isSidebarVisible: value }),
setMainPanelVisible: (value) => set({ isMainPanelVisible: value }),
triggerPreviewRefresh: () =>
set((s) => ({ previewRefreshKey: s.previewRefreshKey + 1 })),
@@ -200,3 +203,7 @@ export const useIsGitPanelVisible = () =>
export const useIsChangesMode = () => useLayoutStore((s) => s.isChangesMode);
export const useIsLogsMode = () => useLayoutStore((s) => s.isLogsMode);
export const useIsPreviewMode = () => useLayoutStore((s) => s.isPreviewMode);
// Derived selector: true when right main panel content is visible (Changes/Logs/Preview)
export const useIsRightMainPanelVisible = () =>
useLayoutStore((s) => s.isChangesMode || s.isLogsMode || s.isPreviewMode);