Menu panel with header links
A guide with site links in the header and chapters in the sidebar. At phone width the sidebar opens as a panel under the header, with the header's links at its top so there is one menu, and the menu button becomes its close button.
NavigationManager Navigation
@* A guide with site links in the header and chapters in the sidebar. On phones the sidebar opens
as a panel under the header (SmallScreen.Panel) with the header's links at its top, so there is
one menu, and the menu button turns into its close button. *@
<AppShell>
<AppHeader>
<SidebarToggle />
<AppBrand Href="To(null)" Icon="Lucide.Zap" Label="Acme" />
<Box Grow />
<SiteNav>
<NavItem Href="Site(null)">Guide</NavItem>
<NavItem Href='Site("blog")'>Blog</NavItem>
<NavItem Href='Site("videos")'>Videos</NavItem>
</SiteNav>
</AppHeader>
<AppSidebar SmallScreen="SidebarSmallScreen.Panel" Label="Guide">
<NavMenu>
<NavLabel>Basics</NavLabel>
<NavItem Href="To(null)" Icon="Lucide.BookOpen">Writing your first rule</NavItem>
<NavItem Href='To("guide/outcomes")' Icon="Lucide.ListChecks">Outcomes</NavItem>
<NavItem Href='To("guide/dry-runs")' Icon="Lucide.Play">Dry runs</NavItem>
<NavLabel>Going live</NavLabel>
<NavItem Href='To("guide/reviews")' Icon="Lucide.Users">Reviews</NavItem>
<NavItem Href='To("guide/shadow-mode")' Icon="Lucide.ShieldCheck">Shadow mode</NavItem>
</NavMenu>
</AppSidebar>
<AppMain>
<Stack Gap="5" Padding="new() { Base = 4, Md = 10 }" MaxWidth="Length.Prose">
<Heading Level="1" Size="TextSize.Xl2">Writing your first rule</Heading>
<TextBlock Color="Color.Muted">A rule reads a decision's inputs and returns an outcome. Start small: one condition, one outcome, and a dry run before it goes live.</TextBlock>
<Heading Level="2" Size="TextSize.Lg">Conditions</Heading>
<TextBlock>Each condition compares an input to a value. Conditions in a group must all match; groups are tried in order, and the first group that matches decides the outcome.</TextBlock>
<Code Block Language="text">Sample</Code>
<Alert Title="Run it dry first">A dry run replays last week's decisions through the new rule and shows what would change, without changing anything.</Alert>
</Stack>
</AppMain>
</AppShell>
{
// Links within this example, in its own address so they stay here: ?site= for the site's
// sections, ?view= for the guide's chapters, so each list marks its own current page.
private string Site(string? section) => Navigation.GetUriWithQueryParameter("site", section);
private string To(string? page) => Navigation.GetUriWithQueryParameter("view", page);
}Off: At phone width the menu button and its close button are links, so the panel opens and closes, but focus doesn't move and Escape does nothing.