From 04686dcc7dd7f04bffa6face71b9d155f39195b8 Mon Sep 17 00:00:00 2001 From: Zzy Date: Fri, 21 Aug 2026 23:54:49 +0800 Subject: [PATCH] fix: preserve bottom cap during width drags --- src/client/Sidebar.tsx | 15 ++++++++++++--- tests/sidebar-layout-push.spec.ts | 11 +++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 tests/sidebar-layout-push.spec.ts diff --git a/src/client/Sidebar.tsx b/src/client/Sidebar.tsx index 552dd62..914d4fb 100644 --- a/src/client/Sidebar.tsx +++ b/src/client/Sidebar.tsx @@ -235,6 +235,15 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { const state = snapshot.state const sessionId = snapshot.sessionId const summaryCwd = sessionId === undefined ? undefined : sessionList.byId[sessionId]?.cwd + const pushedBottomHeight = (bottomOpen: boolean, bottomHeight: number): number => layoutPushSize({ + narrow, + panelOpen: false, + bottomOpen, + width: 0, + bottomHeight, + viewportWidth: viewport.width, + viewportHeight: viewport.height, + }).height // The collapsed toggle cluster reclaims the top-right corner, so the DSH // session header's right-aligned utilities (the "Session log" download @@ -776,7 +785,7 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { // (clamped) instead of rolling back the flick. if (draggingWidth) { width = clampWidth(widthDrag.current.startWidth + (widthDrag.current.startX - event.clientX)) - height = state?.bottomOpen === true ? Math.min(state.bottomHeight, window.innerHeight) : 0 + height = pushedBottomHeight(state?.bottomOpen === true, state?.bottomHeight ?? 0) } else if (draggingBottom) { width = Math.min(state?.width ?? 0, window.innerWidth) height = clampHeight(bottomDrag.current.startHeight + (bottomDrag.current.startY - event.clientY)) @@ -1110,7 +1119,7 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { if (!event.currentTarget.hasPointerCapture(event.pointerId)) return const { startX, startWidth } = widthDrag.current const width = clampWidth(startWidth + (startX - event.clientX)) - const height = state.bottomOpen ? Math.min(state.bottomHeight, window.innerHeight) : 0 + const height = pushedBottomHeight(state.bottomOpen, state.bottomHeight) scheduleDrag(width, height) }} onPointerUp={(event) => { @@ -1124,7 +1133,7 @@ export function Sidebar(props: { ctx: Context; store: SidebarStore }) { // pointermove (the rAF pending value) can be stale. Commit // from the up position (v0.13.1 semantics; issue #247). const width = clampWidth(startWidth + (startX - event.clientX)) - const height = state.bottomOpen ? Math.min(state.bottomHeight, window.innerHeight) : 0 + const height = pushedBottomHeight(state.bottomOpen, state.bottomHeight) commitDrag(width, height, s => setWidth(s, width)) setDraggingWidth(false) }} diff --git a/tests/sidebar-layout-push.spec.ts b/tests/sidebar-layout-push.spec.ts new file mode 100644 index 0000000..8f355fb --- /dev/null +++ b/tests/sidebar-layout-push.spec.ts @@ -0,0 +1,11 @@ +import { readFileSync } from 'node:fs' +import { describe, expect, it } from 'vitest' + +const source = readFileSync('src/client/Sidebar.tsx', 'utf8') + +describe('Sidebar layout-push integration', () => { + it('does not bypass the shared bottom-height cap during width drags', () => { + expect(source).not.toContain('Math.min(state.bottomHeight, window.innerHeight)') + expect(source.match(/pushedBottomHeight\(/g)).toHaveLength(3) + }) +})