navigation · conformant
NavigationBar
NavigationBarNavigationBarPropsNavigationItem
import { Icon, NavigationBar, Surface, Text } from '@language-lit/material3-expressive'
export function NavigationBarExample() {
return (
<Surface
as="section"
aria-labelledby="navigation-bar-example-title"
color="surface-container-low"
shape="extra-large"
className="navigation-bar-example"
>
<Text as="h2" id="navigation-bar-example-title" variant="titleLarge" emphasis="emphasized">
Navigation bar
</Text>
<Text as="p" variant="bodyMedium">
Web-native `nav`/`aria-current` navigation with a sliding pill
highlight per item.
</Text>
<NavigationBar
aria-label="Example sections"
className="navigation-bar-example__bar"
defaultValue="profile"
items={[
{
value: 'home',
label: 'Home',
icon: <Icon source="home" />,
selectedIcon: <Icon source="home" fill={1} />,
},
{
value: 'favorites',
label: 'Favorites',
icon: <Icon source="favorite" />,
selectedIcon: <Icon source="favorite" fill={1} />,
},
{ value: 'trash', label: 'Trash', icon: <Icon source="delete" />, disabled: true },
// No `selectedIcon` — selected by default here to visually confirm
// the fallback-to-`icon`-while-selected behavior.
{ value: 'profile', label: 'Profile', icon: <Icon source="person" /> },
{ value: 'docs', label: 'Docs', icon: <Icon source="description" />, href: '#' },
]}
/>
</Surface>
)
}NavigationBar renders a bottom navigation bar with a width-expanding pill
highlight behind the selected item's icon. It uses web-native <nav>/
aria-current navigation semantics rather than the pinned Material
source's ported tab role — it is a persistent app-navigation region, not
an in-page tab switcher (see Tabs for that).
import { Icon, NavigationBar } from '@language-lit/material3-expressive'
import '@language-lit/material3-expressive/styles.css'
<NavigationBar
aria-label="Primary sections"
items={[
{ value: 'home', label: 'Home', icon: <Icon source="home" /> },
{ value: 'favorites', label: 'Favorites', icon: <Icon source="favorite" /> },
]}
/>Contract
items: readonly NavigationItem[]describes the bar's content:{ value, label, icon, selectedIcon?, disabled?, href? }. This is the sameNavigationItemtypeNavigationRail,NavigationDrawer, andNavigationSuiteall reuse.value/defaultValue/onValueChangefollow the same controlled/ uncontrolled shape as every other stateful component.defaultValuefalls back to the first item's value when omitted.- An item with
hrefrenders a real<a href>instead of<button>, the same link-safe patternTabsalready uses — useful for router-driven navigation. A disabledhrefitem omitshref(anchors have no native disabled state) but keepsrole="link"so it stays identifiable to assistive technology. selectedIcon, when supplied, replacesiconwhile that item is selected (a common outlined-to-filled icon swap); omit it to reuseiconfor both states. Both artworks stay inside the same 24×24px box: selection animates only the centered indicator background from zero width to its 56×32px pill, never the icon or item footprint.
Tokens and boundaries
All color, geometry, and motion values live in one
--m3e-comp-navigation-bar-* registration. Theme overrides remain scoped
to Material3Provider; NavigationBar injects no runtime styles. It
imports no Next.js, Vite, router, animation library, or
private application code.