fix(layout): hoist AppLayout into a persistent AppShell router layout (MAPPS-366) #439
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/MAPPS-366-persistent-app-shell"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Navigating between the user dashboard and an admin dashboard blanked the page text for about half a second (icons did not flicker). Root cause: every page wrapped its own
AppLayout(top bar + sidebar + banners), while the only router layout wasAuthGuard(just anOutlet). So each SPA navigation swapped the whole page component through the Outlet, tearing down and rebuilding the entire shell every time. The MAPPS-203 / MAPPS-250 / MAPPS-287 workarounds (pushing sidebar scroll / collapse / title state up to the App root to survive the remount) were all symptoms of this.Fix
Hoist the chrome into a single persistent
AppShell, mounted as a Dioxus#[layout]insideAuthGuard. It renders the top bar, sidebar, banners, toast and account-deleted overlays once and swaps only the routed subtree throughOutlet, so the shell stays mounted across navigation and nothing blanks.use_page_title(title)hook, backed by a sharedPageTitlesignal provided at the App root (use_page_title_providerinmain.rs).TopBarreads that signal itself and syncsdocument.title, so a title change re-renders only the bar, never the page. This is what makes it loop-safe: a page and itsContentUnavailable/PermissionRequiredbranch can both calluse_page_titlewithout fighting over the signal./onboarding/profile,/dashboard/tv,/big/*) are hoisted above the#[layout(AppShell)]boundary so they keep rendering full-screen with no chrome.AppLayoutcomponent is removed; all 91AppLayout { title, ... }call sites across the authenticated pages are converted.use_page_titleis placed before every early return (rules of hooks); permission-gated and detail pages were checked individually.Scope
Core:
components/layout.rs,main.rs,lib.rs(route restructure),content_unavailable.rs,permission_state.rs. Plus the 24 authenticated page modules (mechanical wrapper removal). Chromeless (big_view,dashboard::DashboardTvPage) and portal pages are untouched.Verification
just check-docker(full wasm release build) andjust pre-commit(cargo fmt --check+cargo clippy --all-targets -- -D warnings+cargo check --target wasm32-unknown-unknown+cargo test --lib, 223 passing) are both green.A render test (
layout.rs) asserts the newuse_page_titleplumbing carries a page's title through the sharedPageTitlesignal to theTopBar-style reader. The complementary "the shell does not re-mount across navigation" property is a structural guarantee of the#[layout(AppShell)]router construct (a Dioxus#[layout]is one scope the router keeps mounted across its child routes), enforced by the route wiring inlib.rsrather than asserted at runtime.#MAPPS-366