sidebar: squeeze the conversation layout instead of floating over it

The open panel now occupies layout space: #root (the AppFrame grid) gives
up the panel width on the right via margin-right driven by a
--dsh-sidebar-width CSS variable, and only the center column is flexible,
so the squeeze lands exactly on the agent output and the input bar (VSCode
sidebar behavior). The fixed panel covers the vacated strip; expand/
collapse animates the margin and the slide on the same theme duration,
width drags disable the transition, and prefers-reduced-motion is honored.
This commit is contained in:
Menghuan1918
2026-08-08 14:51:05 +08:00
parent 0621504e1b
commit 302bd85e62
3 changed files with 42 additions and 0 deletions
+13
View File
@@ -101,6 +101,19 @@ export function Sidebar(props: { ctx: Context }) {
const widthDrag = useRef({ startX: 0, startWidth: 0 })
const [draggingWidth, setDraggingWidth] = useState(false)
// Layout push: the app shell gives up the panel's width while it is open
// (0 while collapsed), so the conversation and input bar are squeezed
// instead of covered. Dragging disables the layout transition.
useEffect(() => {
const width = snapshot.state?.panelOpen === true ? snapshot.state.width : 0
document.documentElement.style.setProperty('--dsh-sidebar-width', `${width}px`)
}, [snapshot.state?.panelOpen, snapshot.state?.width])
useEffect(() => {
if (draggingWidth) document.body.setAttribute('data-dsh-sidebar-dragging', '')
else document.body.removeAttribute('data-dsh-sidebar-dragging')
}, [draggingWidth])
// Whether the panel currently fills the viewport (fullscreen expansion).
const fullscreen = state !== undefined && window.innerWidth - state.width < 8