diff --git a/src/components/sidebar/Sidebar.tsx b/src/components/sidebar/Sidebar.tsx index 0b7b436..2d00da5 100644 --- a/src/components/sidebar/Sidebar.tsx +++ b/src/components/sidebar/Sidebar.tsx @@ -1,4 +1,4 @@ -import type { ReactNode } from "react"; +import { useState, useRef, useEffect, type ReactNode } from "react"; import { Rss, BookOpen, Image as ImageIcon, Mic2, Search, Bookmark, Mail, Bell, Users, Zap, Radio, Wifi, Settings, Heart, PenLine, @@ -47,11 +47,48 @@ export function Sidebar() { const c = sidebarCollapsed; + // Resizable width when expanded (issue #6), persisted to localStorage. + const SIDEBAR_WIDTH_KEY = "wrystr_sidebar_width"; + const MIN_WIDTH = 160; + const MAX_WIDTH = 360; + const DEFAULT_WIDTH = 192; // matches the old w-48 + const asideRef = useRef(null); + const [width, setWidth] = useState(() => { + const saved = parseInt(localStorage.getItem(SIDEBAR_WIDTH_KEY) ?? "", 10); + return Number.isFinite(saved) && saved >= MIN_WIDTH && saved <= MAX_WIDTH ? saved : DEFAULT_WIDTH; + }); + const [dragging, setDragging] = useState(false); + + useEffect(() => { + if (!dragging) return; + const onMove = (e: MouseEvent) => { + const left = asideRef.current?.getBoundingClientRect().left ?? 0; + setWidth(Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, e.clientX - left))); + }; + const onUp = () => setDragging(false); + document.body.style.userSelect = "none"; + document.body.style.cursor = "col-resize"; + window.addEventListener("mousemove", onMove); + window.addEventListener("mouseup", onUp); + return () => { + document.body.style.userSelect = ""; + document.body.style.cursor = ""; + window.removeEventListener("mousemove", onMove); + window.removeEventListener("mouseup", onUp); + }; + }, [dragging]); + + useEffect(() => { + localStorage.setItem(SIDEBAR_WIDTH_KEY, String(width)); + }, [width]); + return ( ); }