Sidebar redesign, dropdown fixes, and soft-delete UI #57

Merged
uz1mani merged 50 commits from staging into main 2026-03-19 00:08:16 +00:00
14 changed files with 1590 additions and 309 deletions
Showing only changes of commit 137ab4c2ba - Show all commits

View File

@@ -240,12 +240,15 @@ export default function Sidebar({
const [sites, setSites] = useState<Site[]>([]) const [sites, setSites] = useState<Site[]>([])
const [pendingHref, setPendingHref] = useState<string | null>(null) const [pendingHref, setPendingHref] = useState<string | null>(null)
const wasCollapsedRef = useRef(false) const wasCollapsedRef = useRef(false)
const [collapsed, setCollapsed] = useState(true) // Always start collapsed — no hydration mismatch const [ready, setReady] = useState(false)
const [collapsed, setCollapsed] = useState(true)
// Read saved state after mount — expands smoothly if user had it open // Read saved state and reveal sidebar in one frame — no flash
useEffect(() => { useEffect(() => {
const saved = localStorage.getItem(SIDEBAR_KEY) const saved = localStorage.getItem(SIDEBAR_KEY)
if (saved === 'false') setCollapsed(false) if (saved === 'false') setCollapsed(false)
// Reveal after state is set — React batches these, so sidebar appears at correct width
requestAnimationFrame(() => setReady(true))
}, []) }, [])
useEffect(() => { listSites().then(setSites).catch(() => {}) }, []) useEffect(() => { listSites().then(setSites).catch(() => {}) }, [])
@@ -339,8 +342,8 @@ export default function Sidebar({
<> <>
{/* Desktop — width transitions, internal layout never changes */} {/* Desktop — width transitions, internal layout never changes */}
<aside <aside
className="hidden md:flex flex-col shrink-0 border-r border-neutral-200/60 dark:border-neutral-800/60 bg-white/90 dark:bg-neutral-900/90 backdrop-blur-xl overflow-hidden" className={`hidden md:flex flex-col shrink-0 border-r border-neutral-200/60 dark:border-neutral-800/60 bg-white/90 dark:bg-neutral-900/90 backdrop-blur-xl overflow-hidden ${ready ? 'opacity-100' : 'opacity-0'}`}
style={{ width: collapsed ? COLLAPSED : EXPANDED, transition: 'width 200ms cubic-bezier(0.4, 0, 0.2, 1)' }} style={{ width: collapsed ? COLLAPSED : EXPANDED, transition: ready ? 'width 200ms cubic-bezier(0.4, 0, 0.2, 1)' : 'none' }}
> >
{sidebarContent(false)} {sidebarContent(false)}
</aside> </aside>