fix: tune sidebar and context panel sizing

Keep the left sidebar open when the context panel opens
Reduce right sidebar and context panel default widths
Collapse only the sync button label at medium widths
This commit is contained in:
Bohdan Triapitsyn
2026-05-22 01:33:11 +03:00
parent 6fd3afd25a
commit 2d85cc86be
5 changed files with 16 additions and 59 deletions
@@ -19,7 +19,6 @@ import { DrawerProvider } from '@/contexts/DrawerContext';
import { useUIStore } from '@/stores/useUIStore';
import { useUpdateStore } from '@/stores/useUpdateStore';
import { useDeviceInfo } from '@/lib/device';
import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
import { useVisualViewport } from '@/hooks/useVisualViewport';
import { useI18n } from '@/lib/i18n';
import { cn } from '@/lib/utils';
@@ -39,30 +38,11 @@ const MultiRunWindow = lazyWithChunkRecovery(() => import('@/components/views/Mu
// Mobile drawer width as screen percentage
const MOBILE_DRAWER_WIDTH_PERCENT = 85;
const DESKTOP_SIDEBAR_MIN_WIDTH = 250;
const DESKTOP_SIDEBAR_MIN_WIDTH = 280;
const DESKTOP_SIDEBAR_MAX_WIDTH = 500;
const DESKTOP_RIGHT_SIDEBAR_MIN_WIDTH = 400;
const DESKTOP_RIGHT_SIDEBAR_MIN_WIDTH = 360;
const DESKTOP_RIGHT_SIDEBAR_MAX_WIDTH = 860;
const normalizeDirectoryKey = (value: string): string => {
if (!value) return '';
const raw = value.replace(/\\/g, '/');
const hadUncPrefix = raw.startsWith('//');
let normalized = raw.replace(/\/+$/g, '');
normalized = normalized.replace(/\/+/g, '/');
if (hadUncPrefix && !normalized.startsWith('//')) {
normalized = `/${normalized}`;
}
if (normalized === '') {
return raw.startsWith('/') ? '/' : '';
}
return normalized;
};
export const MainLayout: React.FC = () => {
const { t } = useI18n();
const RIGHT_SIDEBAR_AUTO_CLOSE_WIDTH = 1140;
@@ -87,21 +67,8 @@ export const MainLayout: React.FC = () => {
const visualViewport = useVisualViewport();
const sidebarWidth = useUIStore((state) => state.sidebarWidth);
const rightSidebarWidth = useUIStore((state) => state.rightSidebarWidth);
const effectiveDirectory = useEffectiveDirectory() ?? '';
const directoryKey = React.useMemo(() => normalizeDirectoryKey(effectiveDirectory), [effectiveDirectory]);
const isContextPanelOpen = useUIStore((state) => {
if (!directoryKey) {
return false;
}
const panelState = state.contextPanelByDirectory[directoryKey];
const tabs = panelState?.tabs ?? [];
const activeTab = tabs.find((tab) => tab.id === panelState?.activeTabId) ?? tabs[tabs.length - 1];
return Boolean(panelState?.isOpen && activeTab);
});
const setSidebarOpen = useUIStore((state) => state.setSidebarOpen);
const rightSidebarAutoClosedRef = React.useRef(false);
const bottomTerminalAutoClosedRef = React.useRef(false);
const leftSidebarAutoClosedByContextRef = React.useRef(false);
// Mobile drawer state
const [mobileLeftDrawerOpen, setMobileLeftDrawerOpen] = React.useState(false);
@@ -247,22 +214,6 @@ export const MainLayout: React.FC = () => {
};
}, []);
React.useEffect(() => {
if (isContextPanelOpen) {
const currentlyOpen = useUIStore.getState().isSidebarOpen;
if (currentlyOpen) {
setSidebarOpen(false);
leftSidebarAutoClosedByContextRef.current = true;
}
return;
}
if (leftSidebarAutoClosedByContextRef.current) {
setSidebarOpen(true);
leftSidebarAutoClosedByContextRef.current = false;
}
}, [isContextPanelOpen, setSidebarOpen]);
React.useEffect(() => {
if (typeof window === 'undefined') {
return;
@@ -4,7 +4,7 @@ import { useUIStore } from '@/stores/useUIStore';
import { useI18n } from '@/lib/i18n';
export const RIGHT_SIDEBAR_CONTENT_WIDTH = 420;
const RIGHT_SIDEBAR_MIN_WIDTH = 400;
const RIGHT_SIDEBAR_MIN_WIDTH = 360;
const RIGHT_SIDEBAR_MAX_WIDTH = 860;
interface RightSidebarProps {
@@ -19,7 +19,7 @@ export const RightSidebar: React.FC<RightSidebarProps> = ({ isOpen, children, cl
const setRightSidebarWidth = useUIStore((state) => state.setRightSidebarWidth);
const [isResizing, setIsResizing] = React.useState(false);
const startXRef = React.useRef(0);
const startWidthRef = React.useRef(rightSidebarWidth || 420);
const startWidthRef = React.useRef(rightSidebarWidth || RIGHT_SIDEBAR_CONTENT_WIDTH);
const resizingWidthRef = React.useRef<number | null>(null);
const activeResizePointerIDRef = React.useRef<number | null>(null);
const sidebarRef = React.useRef<HTMLElement | null>(null);
@@ -165,12 +165,12 @@ export const CommitSection: React.FC<CommitSectionProps> = ({
{commitAction === 'commitAndPush' ? (
<>
<Icon name="loader-4" className="size-4 animate-spin" />
<span className="commit-actions__label">{t('gitView.commit.pushing')}</span>
<span className="commit-actions__label commit-actions__label--push">{t('gitView.commit.pushing')}</span>
</>
) : (
<>
<Icon name="arrow-up" className="size-3.5" />
<span className="commit-actions__label">{t('gitView.commit.push')}</span>
<span className="commit-actions__label commit-actions__label--push">{t('gitView.commit.push')}</span>
</>
)}
</Button>
+6
View File
@@ -760,6 +760,12 @@ html:not(.dark) .chat-scroll {
}
}
@container commit-actions (max-width: 22rem) {
.commit-actions__label--push {
display: none;
}
}
@container commit-actions (max-width: 19rem) {
.commit-actions__label {
display: none;
+4 -4
View File
@@ -96,13 +96,13 @@ const isLegacyDefaultTemplates = (value: unknown): boolean => {
);
};
const CONTEXT_PANEL_DEFAULT_WIDTH = 600;
const CONTEXT_PANEL_MIN_WIDTH = 360;
const CONTEXT_PANEL_DEFAULT_WIDTH = 380;
const CONTEXT_PANEL_MIN_WIDTH = 380;
const CONTEXT_PANEL_MAX_WIDTH = 1400;
const CONTEXT_PANEL_MAX_TABS = 12;
const CONTEXT_PANEL_MAX_LABEL_LENGTH = 120;
const LEFT_SIDEBAR_MIN_WIDTH = 300;
const RIGHT_SIDEBAR_MIN_WIDTH = 400;
const LEFT_SIDEBAR_MIN_WIDTH = 280;
const RIGHT_SIDEBAR_MIN_WIDTH = 360;
const normalizeDirectoryPath = (value: string): string => {
if (!value) return '';