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

View File

@@ -26,6 +26,7 @@ type LayoutState = {
setLogsMode: (value: boolean) => void; setLogsMode: (value: boolean) => void;
setPreviewMode: (value: boolean) => void; setPreviewMode: (value: boolean) => void;
setSidebarVisible: (value: boolean) => void; setSidebarVisible: (value: boolean) => void;
setMainPanelVisible: (value: boolean) => void;
// Preview actions // Preview actions
triggerPreviewRefresh: () => void; triggerPreviewRefresh: () => void;
@@ -168,6 +169,8 @@ export const useLayoutStore = create<LayoutState>()(
setSidebarVisible: (value) => set({ isSidebarVisible: value }), setSidebarVisible: (value) => set({ isSidebarVisible: value }),
setMainPanelVisible: (value) => set({ isMainPanelVisible: value }),
triggerPreviewRefresh: () => triggerPreviewRefresh: () =>
set((s) => ({ previewRefreshKey: s.previewRefreshKey + 1 })), set((s) => ({ previewRefreshKey: s.previewRefreshKey + 1 })),
@@ -200,3 +203,7 @@ export const useIsGitPanelVisible = () =>
export const useIsChangesMode = () => useLayoutStore((s) => s.isChangesMode); export const useIsChangesMode = () => useLayoutStore((s) => s.isChangesMode);
export const useIsLogsMode = () => useLayoutStore((s) => s.isLogsMode); export const useIsLogsMode = () => useLayoutStore((s) => s.isLogsMode);
export const useIsPreviewMode = () => useLayoutStore((s) => s.isPreviewMode); 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);