From 5570b1379185a4301b871977a192366825f2a775 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 31 May 2026 23:19:05 +0200 Subject: [PATCH] webui: sidebar, don't auto-navigate when expanding a section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clicking a section header (Status / Configure / Maintenance) used to fold the previously-open section AND fire a click on the first page link inside the just-opened section. That meant going from "Status > Overview" to "Configure > Hardware" was three clicks worth of page loads: Configure header expands and lands you on Configure > Interfaces, then you click Hardware and wait again. Toggle now just expands or collapses its own section. Sibling sections stay open until a real page-link click, at which point updateActiveNav() already closes the others to leave only the section containing the active page open. Configure's enter-POST (running → candidate snapshot) still fires the first time the Configure accordion opens per page lifecycle, so the candidate datastore is ready by the time the user clicks a Configure page. Signed-off-by: Joachim Wiberg --- src/webui/static/js/app.js | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/webui/static/js/app.js b/src/webui/static/js/app.js index aa5c2ae7..b1ff6671 100644 --- a/src/webui/static/js/app.js +++ b/src/webui/static/js/app.js @@ -996,7 +996,14 @@ } }); - // Mutual exclusion, persistence, and auto-navigation to first page link + // Persistence + Configure enter-hook. + // + // Toggling a section header just expands or collapses that section — + // it does NOT close sibling sections, and it does NOT auto-navigate + // to the first page in the section. This lets the user browse the + // available pages under a header without paying for a navigation + // they didn't ask for. The actual mutual-exclusion (other sections + // collapse) happens in updateActiveNav after a real page-link click. groups.forEach(function(d) { var label = d.querySelector(':scope > summary'); if (!label) return; @@ -1010,26 +1017,8 @@ if (d.id !== 'nav-configure') { localStorage.setItem(key, d.open ? 'open' : 'closed'); } - if (d.open) { - if (d.id === 'nav-configure') { - enterConfigure(); - } - groups.forEach(function(other) { - if (other !== d && other.open) { - other.removeAttribute('open'); - if (other.id !== 'nav-configure') { - var otherLabel = other.querySelector(':scope > summary'); - if (otherLabel) { - localStorage.setItem('nav-top:' + otherLabel.textContent.trim(), 'closed'); - } - } - } - }); - // Navigate to the first page link if none in this section is active - if (!d.querySelector('.nav-link.active')) { - var first = d.querySelector('a.nav-link[hx-get]'); - if (first) first.click(); - } + if (d.open && d.id === 'nav-configure') { + enterConfigure(); } }); });