Files
github-actions[bot] 70d35bab31
Merge-upstream / merge (push) Canceled after 0s
🗽 Sync 2026-09-13 02:49:28
2026-09-13 02:49:28 +08:00

2.2 KiB

Sidebar & menu

  • header.ut: near-minimal shell — empty #sidebar plus 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 in menu-shadcn.js.
  • sidebar-shadcn.js: state machine for theme (light/dark/device), sidebar collapse/expand, accordion, and mobile drawer — exposed as window.ShadcnSidebar after the shadcn-sidebar-ready event fires.
  • menu-shadcn.js: resolves the admin branch of ui.menu.load(), then renders a two-level sidebar; ICON_MAP maps a LuCI menu node's name to /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 from L.env after 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.