2.2 KiB
Sidebar & menu
header.ut: near-minimal shell — empty#sidebarplus a parser-blocking inline script right after it that replays the sidebar cache (below) before first paint; sidebar chrome + nav are otherwise built client-side inmenu-shadcn.js.sidebar-shadcn.js: state machine for theme (light/dark/device), sidebar collapse/expand, accordion, and mobile drawer — exposed aswindow.ShadcnSidebarafter theshadcn-sidebar-readyevent fires.menu-shadcn.js: resolves theadminbranch ofui.menu.load(), then renders a two-level sidebar;ICON_MAPmaps a LuCI menu node'snameto/shadcn/icons/*.svg; deeper levels render as#tabmenu.syncRoute()re-marks the active sidebar item (same longest-link-prefix rule as the header.ut replay), breadcrumb and tabs fromL.envafter a router swap without rebuilding the sidebar;closeSurfaces()closes palette/drawer/popover.
Sidebar cache (anti-flash)
menu-shadcn.js snapshots #sidebar.innerHTML + scroll position into sessionStorage['shadcn.sidebar.cache'] ({v, lang, html, scroll}) after render and on pagehide. The header.ut inline script replays it pre-paint on the next navigation, recomputes the active highlight for the current URL (longest link-path prefix — keep in sync with menu-shadcn's dispatchpath matching), restores accordion/scroll state, and sets data-shadcn-built / data-shadcn-restored on #sidebar.
When restored, renderSidebarChrome only re-syncs the hostname, and renderSidebarNav preserves accordion/scroll across its authoritative rebuild.
Restored HTML loses inline JS handlers (innerHTML serialization), so anything that must work before the re-render needs a delegated listener — e.g. the logout click in header.ut, which clears the cache and sets window.shadcnSuppressSidebarCache so the pagehide re-cache stays suppressed.
Bump v whenever the sidebar markup changes shape.
Cross-document @view-transition rules live in components/_view-transitions.css (only #sidebar gets its own snapshot group — the topbar must not, or its top-layer snapshot escapes .content-card's rounded-corner clipping during transitions); they assume the cache keeps the sidebar's first frame populated.