Lumeo
Package LumeoA11ynavigationDepends onbuttonTested Tier 3 · 52 testsView source ↗

Bottom Nav

Mobile-first bottom tab bar with icons, labels, badges, safe-area padding, and an optional floating action button. Pair with Sidebar for responsive app layouts.

Installation

dotnet add package Lumeo

One-time app setup (AddLumeo(), CSS & JS) is covered in the installation guide.

Usage

@using Lumeo

<BottomNav />
Tested Tier 3 · A11y + behavior
all components →
Render Behavior A11y Keyboard Scale E2E

52 tests across 8 files. Auto-generated from the test suite.

When to Use

  • Mobile or touch-first apps that need 3–5 top-level destinations always reachable
  • As the small-screen half of a responsive pair: Sidebar on desktop, BottomNav on mobile
  • Thumb-zone primary actions (center FAB for "Create", "Compose", "Scan")

Not for: deep navigation hierarchies, admin panels, or more than ~5 items. Use Sidebar, Tabs, or Navigation Menu for those.

App content area
Unread indicators
Primary action in the thumb zone
Click a tab — active highlight glides in.

Pick a value to see it applied live. Default anchors full-width to the bottom; Pill floats as a centered rounded bar.

App content area
Elevated centered pill variant
Tap a tab — it scales for a tactile feel.

Responsive: Sidebar ↔ BottomNav

The standard mobile pattern: show the full <Sidebar> on md and up, and a 4-item <BottomNav> below it. Pick the 4 most-used items — do not mirror the full sidebar tree; bury the rest behind a "More" item or a Sheet.

<!-- MainLayout.razor --> <div class="min-h-screen flex"> <!-- Sidebar: visible on md and up --> <SidebarProvider Class="hidden md:flex"> <SidebarComponent> <SidebarHeader>Acme Inc</SidebarHeader> <SidebarContent> <SidebarMenu> <SidebarMenuItem> <SidebarMenuButton Href="/" IsActive="@true"> <IconContent><Icon Name="House" Size="Lumeo.Size.Sm" /></IconContent> <LabelContent>Home</LabelContent> </SidebarMenuButton> </SidebarMenuItem> <!-- …full sidebar tree… --> </SidebarMenu> </SidebarContent> </SidebarComponent> </SidebarProvider> <!-- Main content: reserve space at the bottom on mobile --> <main class="flex-1 pb-16 md:pb-0"> @Body </main> </div> <!-- BottomNav: visible below md. Pick the 4 most-used items only. --> <BottomNav Class="md:hidden"> <BottomNavItem Href="/" Label="Home"> <IconContent><Icon Name="House" Size="Lumeo.Size.Sm" /></IconContent> </BottomNavItem> <BottomNavItem Href="/search" Label="Search"> <IconContent><Icon Name="Search" Size="Lumeo.Size.Sm" /></IconContent> </BottomNavItem> <BottomNavItem Href="/inbox" Label="Inbox"> <IconContent><Icon Name="Inbox" Size="Lumeo.Size.Sm" /></IconContent> <Badge>3</Badge> </BottomNavItem> <BottomNavItem Href="/profile" Label="Profile"> <IconContent><Icon Name="User" Size="Lumeo.Size.Sm" /></IconContent> </BottomNavItem> </BottomNav>

Two simple rules: the Sidebar is hidden md:flex, the BottomNav is md:hidden. Add pb-16 md:pb-0 to your scroll container so content isn't hidden behind the fixed bar on mobile.

API Reference

BottomNav

Prop Type Default Description
ChildContent RenderFragment? — The BottomNavItem (and optionally BottomNavFab) elements rendered inside the nav bar.
AriaLabel string? — Accessible label for the nav landmark. Defaults to "Bottom navigation".
Fixed bool true When true (default), pins to the bottom of the viewport with position: fixed. Set false to render inline.
ReserveSpace bool false When true (and Fixed is on), also renders an in-flow, aria-hidden spacer equal to the nav's height plus the bottom safe-area inset, so the fixed bar never overlaps the end of the page content — no consumer padding-bottom hack needed. The height is driven by the --lumeo-bottom-nav-height CSS variable (default 3.5rem); override it if your nav is taller (e.g. the Pill variant or two-line labels). Place BottomNav at the end of the scrolling content so the spacer reserves room there. Default false.
Variant BottomNavVariant BottomNavVariant.Default Visual variant. Default is a solid bar with a top border; Pill is a floating centered pill.
AnimatedIndicator bool false When true, each BottomNavItem gets smooth background-color and color transitions, and the small active pill transitions its transform with a spring easing. Default is false.
Class string? — Additional CSS classes merged onto the root nav element.
AdditionalAttributes Dictionary<string, object>? — Unmatched attributes are splatted onto the root nav element.

BottomNavItem

Prop Type Default Description
Href string? — Destination URL. When set, item renders as an <a>; otherwise as a <button>.
Label string? — Text label shown under the icon. Also used as the accessible name.
IconContent RenderFragment? — Icon slot (use Icon or <SvgGlyph>). The Content suffix avoids colliding with the <Icon> component.
Badge RenderFragment? — Optional badge (count, dot, or any content) shown on the icon. Int, string, or RenderFragment.
IconSize string "h-5 w-5" Size class applied to the icon container. Defaults to h-5 w-5 to match the original visual. Override to fit larger content like avatars (e.g. "h-7 w-7").
IsActive bool? — Manual active-state override. When null, active is inferred from the current route matching Href.
PressEffect Button.ButtonPressEffect Button.ButtonPressEffect.None Visual feedback when the item is pressed. Default is None. Scale is recommended for a tactile feel on mobile.
Class string? — Additional CSS classes merged onto the root button/anchor element.
AdditionalAttributes Dictionary<string, object>? — Unmatched attributes are splatted onto the root button/anchor element.

Events

OnClick EventCallback Click handler — fires for both <a> and <button> renderings (link navigation still proceeds).

BottomNavFab

Prop Type Default Description
Href string? — Optional destination URL. When set, renders as an anchor; otherwise a button.
AriaLabel* string? — Accessible label. Required because FABs are usually icon-only. Defaults to "Primary action".
ChildContent RenderFragment? — The icon (or other content) rendered inside the floating action button.
Class string? — Additional CSS classes merged onto the root button/anchor element.
AdditionalAttributes Dictionary<string, object>? — Unmatched attributes are splatted onto the root button/anchor element.

Events

OnClick EventCallback Invoked when the FAB is activated. Ignored when Href is set (the anchor navigates instead).
  • Sidebar — Use on desktop in the responsive pair
  • Tabs — For switching views within a page (not top-level nav)
  • Speed Dial — Alternative quick-action surface
  • Sheet — Bottom sheet for "More" destinations that don't fit in 4 tabs