Skip to content

Commit 648ccb1

Browse files
Add draggable sidebar resize handle
Sidebar width is now adjustable between 120px and 500px by dragging a resize handle on its right edge. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 4dbeafd commit 648ccb1

1 file changed

Lines changed: 49 additions & 3 deletions

File tree

src/components/layouts/SidebarLayout.tsx

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
import { useCallback, useRef, useState } from "react";
12
import { SessionList } from "../SessionList";
23
import { SessionPanel } from "../SessionPanel";
34
import type { SessionState } from "../../lib/types";
45

6+
const MIN_WIDTH = 120;
7+
const MAX_WIDTH = 500;
8+
const DEFAULT_WIDTH = 200;
9+
510
interface SidebarLayoutProps {
611
sessions: SessionState[];
712
activeId: string | null;
@@ -17,16 +22,47 @@ export function SidebarLayout({
1722
onNewSession,
1823
onOpenSettings,
1924
}: SidebarLayoutProps) {
25+
const [sidebarWidth, setSidebarWidth] = useState(DEFAULT_WIDTH);
26+
const dragging = useRef(false);
27+
28+
const onMouseDown = useCallback(
29+
(e: React.MouseEvent) => {
30+
e.preventDefault();
31+
dragging.current = true;
32+
33+
const onMouseMove = (ev: MouseEvent) => {
34+
if (!dragging.current) return;
35+
const newWidth = Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, ev.clientX));
36+
setSidebarWidth(newWidth);
37+
};
38+
39+
const onMouseUp = () => {
40+
dragging.current = false;
41+
document.removeEventListener("mousemove", onMouseMove);
42+
document.removeEventListener("mouseup", onMouseUp);
43+
document.body.style.cursor = "";
44+
document.body.style.userSelect = "";
45+
};
46+
47+
document.body.style.cursor = "col-resize";
48+
document.body.style.userSelect = "none";
49+
document.addEventListener("mousemove", onMouseMove);
50+
document.addEventListener("mouseup", onMouseUp);
51+
},
52+
[],
53+
);
54+
2055
return (
2156
<div style={{ display: "flex", height: "100vh" }}>
2257
<div
2358
style={{
24-
width: 200,
25-
minWidth: 160,
59+
width: sidebarWidth,
60+
minWidth: MIN_WIDTH,
61+
maxWidth: MAX_WIDTH,
2662
backgroundColor: "var(--bg-primary)",
27-
borderRight: "1px solid var(--border-primary)",
2863
display: "flex",
2964
flexDirection: "column",
65+
flexShrink: 0,
3066
}}
3167
>
3268
<div
@@ -61,11 +97,21 @@ export function SidebarLayout({
6197
</div>
6298
</div>
6399

100+
<div onMouseDown={onMouseDown} style={resizeHandleStyle} />
101+
64102
<SessionPanel sessionId={activeId} />
65103
</div>
66104
);
67105
}
68106

107+
const resizeHandleStyle: React.CSSProperties = {
108+
width: 4,
109+
cursor: "col-resize",
110+
backgroundColor: "transparent",
111+
borderRight: "1px solid var(--border-primary)",
112+
flexShrink: 0,
113+
};
114+
69115
const iconBtnStyle: React.CSSProperties = {
70116
background: "none",
71117
border: "none",

0 commit comments

Comments
 (0)