Shell
The app frame: an app bar, a drawer, a content region and a footer. This page is inside one.
Putting it together
The pieces go inside VetoLayout in any order - the frame positions them, so
the markup reads top to bottom instead of being nested to match the picture. They
coordinate through shared state, which is how the content region knows to move when a
drawer opens without either component knowing about the other.
@inherits LayoutComponentBase
<VetoThemeProvider />
<VetoLayout>
<VetoAppBar>
<VetoIconButton Icon="@VetoIcons.Menu"
Label="Toggle navigation"
OnClick="() => _open = !_open" />
Veto
<VetoSpacer />
<VetoThemeToggle />
</VetoAppBar>
<VetoDrawer @bind-Open="_open">
<VetoNavMenu Items="Nav" />
</VetoDrawer>
<VetoMainContent>
@Body
</VetoMainContent>
</VetoLayout>Drawer behaviour
Every behaviour ships; pick one with Variant. Nothing is forced on you, and
the default responds to the viewport.
Variants
| Parameter | Type | Default | Description |
|---|---|---|---|
Persistent |
— |
— |
Always visible, pushing content aside. |
Temporary |
— |
— |
Hidden until opened, then overlaid with a scrim. Escape closes it and the page behind stops scrolling. |
Mini |
— |
— |
Collapsed to an icon rail, expanding on hover or toggle. |
Responsive |
— |
default |
Persistent above the breakpoint, temporary below. With MiniBreakpoint set it steps full, rail, overlay. |
The responsive behaviour is pure CSS. Only the open state is tracked in code, which means no viewport listener, no layout shift while WebAssembly boots, and a drawer that is already correct in prerendered HTML.
<!-- Full width, then a rail, then an overlay -->
<VetoDrawer @bind-Open="_open"
Variant="VetoDrawerVariant.Responsive"
Breakpoint="VetoBreakpoint.Medium"
MiniBreakpoint="VetoBreakpoint.Small" />
<!-- Always an overlay, wherever it is opened -->
<VetoDrawer @bind-Open="_open" Variant="VetoDrawerVariant.Temporary" Anchor="VetoAnchor.Right" />Navigation
VetoNavMenu takes its entries as data, so the same navigation can feed a
drawer, a dock and a footer without being written out three times. Active entries are
matched against the URL and marked with aria-current, and a group containing
the current page starts expanded.
public static readonly IReadOnlyList<VetoNavEntry> Items =
[
new VetoNavEntry { Label = "Overview", Href = "/", Icon = VetoIcons.Home, MatchExact = true },
new VetoNavEntry
{
Label = "Components",
Icon = VetoIcons.Grid,
Children =
[
new VetoNavEntry { Label = "Text box", Href = "/docs/components/text-box" },
new VetoNavEntry { Label = "Card", Href = "/docs/components/card" }
]
}
];VetoDrawer
| Parameter | Type | Default | Description |
|---|---|---|---|
Open |
bool |
true |
Whether the drawer is open. Supports @bind-Open. |
Variant |
VetoDrawerVariant |
Responsive |
Persistent, Temporary, Mini or Responsive. |
Anchor |
VetoAnchor |
Left |
Left, Right, Top or Bottom. |
Width |
string |
"16rem" |
Width when fully open. |
MiniWidth |
string |
"4rem" |
Width when collapsed to a rail. |
Breakpoint |
VetoBreakpoint |
Medium |
Where a responsive drawer switches between docked and overlay. |
MiniBreakpoint |
VetoBreakpoint? |
null |
Adds the rail step between the two. |
ClipMode |
VetoClipMode |
Clipped |
Whether the drawer starts below the app bar or runs full height. |
ExpandOnHover |
bool |
true |
Expands a mini drawer while the pointer is over it. Pointer devices only. |
VetoAppBar
| Parameter | Type | Default | Description |
|---|---|---|---|
Height |
string |
"3.5rem" |
The bar's height. The content region offsets itself by it. |
Dense |
bool |
false |
Reduces height and padding. |
Bordered |
bool |
true |
Draws a bottom border. |
Elevated |
bool |
false |
Casts a shadow instead of drawing a border. |
Translucent |
bool |
false |
Lets content scroll under a blurred bar, with a solid fallback. |