From ef455fcef9d6cb1136275c26e49bc3c5d6661795 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 24 Aug 2026 06:25:09 -0400 Subject: [PATCH] refac --- src/lib/components/chat/ChatControls.svelte | 3 ++ .../common/ResizableSidePanel.svelte | 49 +++++++++++++++++-- src/lib/components/notes/NotePanel.svelte | 3 +- 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/lib/components/chat/ChatControls.svelte b/src/lib/components/chat/ChatControls.svelte index aa15ee4476..894b545162 100644 --- a/src/lib/components/chat/ChatControls.svelte +++ b/src/lib/components/chat/ChatControls.svelte @@ -310,6 +310,9 @@ open={$showControls} bind:width={controlsWidth} minWidth={350} + minSiblingWidth={360} + closeOnDragBelowMinWidth + onClose={() => showControls.set(false)} storageKey="chatControlsSize" className="h-full z-10 bg-white dark:bg-gray-900" > diff --git a/src/lib/components/common/ResizableSidePanel.svelte b/src/lib/components/common/ResizableSidePanel.svelte index c1d469f2fe..76da0e7c40 100644 --- a/src/lib/components/common/ResizableSidePanel.svelte +++ b/src/lib/components/common/ResizableSidePanel.svelte @@ -6,16 +6,36 @@ export let width = 350; export let minWidth = 300; export let maxWidth: number | null = null; + export let minSiblingWidth = 0; + export let closeOnDragBelowMinWidth = false; export let storageKey = ''; export let className = ''; export let resizerId = 'controls-resizer'; + export let onClose: () => void = () => {}; + let panelElement: HTMLDivElement | null = null; let isResizing = false; let startClientX = 0; let startWidth = 0; - const clamp = (value: number) => - maxWidth === null ? Math.max(minWidth, value) : Math.min(maxWidth, Math.max(minWidth, value)); + const getMaxWidth = () => { + const siblingMaxWidth = + minSiblingWidth > 0 && panelElement?.parentElement + ? Math.max(0, panelElement.parentElement.clientWidth - minSiblingWidth) + : null; + + if (maxWidth === null) { + return siblingMaxWidth; + } + return siblingMaxWidth === null ? maxWidth : Math.min(maxWidth, siblingMaxWidth); + }; + + const clamp = (value: number) => { + const resolvedMaxWidth = getMaxWidth(); + const minimum = resolvedMaxWidth === null ? minWidth : Math.min(minWidth, resolvedMaxWidth); + const clampedToMin = Math.max(minimum, value); + return resolvedMaxWidth === null ? clampedToMin : Math.min(resolvedMaxWidth, clampedToMin); + }; const persistWidth = () => { if (storageKey) { @@ -23,6 +43,11 @@ } }; + const close = () => { + open = false; + onClose(); + }; + const resizeStartHandler = (e: MouseEvent) => { if (!open) return; @@ -42,7 +67,13 @@ const resizeHandler = (endClientX: number) => { const dx = endClientX - startClientX; - width = clamp(side === 'right' ? startWidth - dx : startWidth + dx); + const nextWidth = side === 'right' ? startWidth - dx : startWidth + dx; + if (closeOnDragBelowMinWidth && nextWidth < minWidth) { + close(); + resizeEndHandler(); + return; + } + width = clamp(nextWidth); }; const resizeKeyHandler = (e: KeyboardEvent) => { @@ -63,6 +94,13 @@ } }); + $: if (open && panelElement) { + const clampedWidth = clamp(width); + if (clampedWidth !== width) { + width = clampedWidth; + } + } + onDestroy(() => { if (isResizing) { document.body.style.userSelect = ''; @@ -75,6 +113,9 @@ if (!isResizing) return; resizeHandler(e.clientX); }} + on:resize={() => { + if (open) width = clamp(width); + }} on:mouseup={resizeEndHandler} /> @@ -97,7 +138,7 @@ {/if} -
+
diff --git a/src/lib/components/notes/NotePanel.svelte b/src/lib/components/notes/NotePanel.svelte index 3f0eefc4bd..acf0781e8c 100644 --- a/src/lib/components/notes/NotePanel.svelte +++ b/src/lib/components/notes/NotePanel.svelte @@ -43,7 +43,8 @@ bind:open={show} bind:width={panelWidth} minWidth={350} - maxWidth={640} + minSiblingWidth={360} + closeOnDragBelowMinWidth className="h-full z-10" >