From a657ad1b93b9171285d7d0574d057022532976b2 Mon Sep 17 00:00:00 2001 From: Steven RYDELL Date: Wed, 29 Jul 2026 06:11:06 +0200 Subject: [PATCH] Sync sidebar with programmatic navigation Collapsible groups now auto-open when the active page lands inside them (while remaining manually toggleable), and the sidebar scrolls the active item into view. Previously, navigating via the command palette left the sidebar collapsed on the wrong spot. --- src/components/layout/Sidebar.tsx | 47 +++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index d69be26..b6b4af5 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -4,7 +4,7 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -import { useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import * as LucideIcons from 'lucide-react'; const { ChevronDown, Lock } = LucideIcons; @@ -74,6 +74,27 @@ function subtreeHasVisibleLink(items: LayoutSubItem[], edition: string): boolean return false; } +interface AutoOpenCollapsibleProps { + containsActive: boolean; + children: React.ReactNode; +} + +// A collapsible that opens itself whenever the active page lands inside it, +// while still allowing the user to toggle it manually afterwards. +function AutoOpenCollapsible({ containsActive, children }: AutoOpenCollapsibleProps) { + const [open, setOpen] = useState(containsActive); + const [prevContainsActive, setPrevContainsActive] = useState(containsActive); + if (containsActive !== prevContainsActive) { + setPrevContainsActive(containsActive); + if (containsActive) setOpen(true); + } + return ( + + {children} + + ); +} + function checkLinkVisible(viewName: string): boolean { const schema = useSchemaStore.getState().schema; if (!schema) return true; @@ -120,6 +141,7 @@ function SidebarSubItem({ item, depth, sectionName, currentPath, navigate, editi return (