Navigation bar
A navigation bar holds destinations in a row along the bottom of the window. Each destination is a button, or a link when it has an href.
Usage
Each destination has an id, a label and an icon. active marks the current one. A badge is a count, a short text, or true for a dot with no text. badgeLabel names the badge; a dot with none is announced as "New activity".
import { createNavigationBar } from 'material';
const navigationBar = createNavigationBar({
ariaLabel: 'Mail navigation',
items: [
{
id: 'inbox',
label: 'Inbox',
icon: inboxIcon,
badge: 8,
active: true,
},
{
id: 'favorites',
label: 'Favorites',
icon: heartOutlineIcon,
badge: true,
},
{ id: 'sent', label: 'Sent', icon: outboxIcon },
],
});
document.body.append(navigationBar.element);
<m-navigation-bar value="inbox" aria-label="Mail navigation">
<m-navigation-bar-item value="inbox" badge="8">Inbox</m-navigation-bar-item>
<m-navigation-bar-item value="favorites" badge="">Favorites</m-navigation-bar-item>
<m-navigation-bar-item value="sent">Sent</m-navigation-bar-item>
</m-navigation-bar>
<script type="module">
const navigationBar = document.querySelector('m-navigation-bar');
navigationBar.querySelector('m-navigation-bar-item[value="inbox"]').setAttribute('icon', inboxIcon);
navigationBar.querySelector('m-navigation-bar-item[value="favorites"]').setAttribute('icon', heartOutlineIcon);
navigationBar.querySelector('m-navigation-bar-item[value="sent"]').setAttribute('icon', outboxIcon);
</script>
import { useState } from 'react';
import { NavigationBar, NavigationBarItem } from 'material/react';
import { inboxIcon, heartOutlineIcon, outboxIcon } from './app';
export function Example() {
const [value, setValue] = useState("inbox");
return (
<NavigationBar value={value} onChange={(event) => setValue(event.detail.value)} ariaLabel="Mail navigation">
<NavigationBarItem value="inbox" icon={inboxIcon} badge="8">Inbox</NavigationBarItem>
<NavigationBarItem value="favorites" icon={heartOutlineIcon} badge="">Favorites</NavigationBarItem>
<NavigationBarItem value="sent" icon={outboxIcon}>Sent</NavigationBarItem>
</NavigationBar>
);
}
<script setup lang="ts">
import { ref } from 'vue';
import { MNavigationBar, MNavigationBarItem } from 'material/vue';
import { inboxIcon, heartOutlineIcon, outboxIcon } from './app';
const value = ref("inbox");
</script>
<template>
<MNavigationBar v-model="value" aria-label="Mail navigation">
<MNavigationBarItem value="inbox" :icon="inboxIcon" badge="8">Inbox</MNavigationBarItem>
<MNavigationBarItem value="favorites" :icon="heartOutlineIcon" badge="">Favorites</MNavigationBarItem>
<MNavigationBarItem value="sent" :icon="outboxIcon">Sent</MNavigationBarItem>
</MNavigationBar>
</template>
<script lang="ts">
import { NavigationBar, NavigationBarItem } from 'material/svelte';
import { inboxIcon, heartOutlineIcon, outboxIcon } from './app';
let value = $state("inbox");
</script>
<NavigationBar bind:value ariaLabel="Mail navigation">
<NavigationBarItem value="inbox" icon={inboxIcon} badge="8">Inbox</NavigationBarItem>
<NavigationBarItem value="favorites" icon={heartOutlineIcon} badge="">Favorites</NavigationBarItem>
<NavigationBarItem value="sent" icon={outboxIcon}>Sent</NavigationBarItem>
</NavigationBar>
import { createSignal } from 'solid-js';
import { NavigationBar, NavigationBarItem } from 'material/solid';
import { inboxIcon, heartOutlineIcon, outboxIcon } from './app';
export function Example() {
const [value, setValue] = createSignal("inbox");
return (
<NavigationBar value={value()} onChange={(event) => setValue(event.detail.value)} ariaLabel="Mail navigation">
<NavigationBarItem value="inbox" icon={inboxIcon} badge="8">Inbox</NavigationBarItem>
<NavigationBarItem value="favorites" icon={heartOutlineIcon} badge="">Favorites</NavigationBarItem>
<NavigationBarItem value="sent" icon={outboxIcon}>Sent</NavigationBarItem>
</NavigationBar>
);
}
Examples
Icon beside the label
itemLayout is vertical (the icon above the label), horizontal (the icon beside it), or auto. auto is vertical, and horizontal while the bar itself is at least 600px wide.
activeIcon is the icon shown while that destination is selected. The web component takes it as selected-icon.
import { createNavigationBar } from 'material';
const navigationBar = createNavigationBar({
itemLayout: 'horizontal',
items: [
{
id: 'home',
label: 'Home',
icon: heartOutlineIcon,
activeIcon: heartFilledIcon,
active: true,
},
{ id: 'search', label: 'Search', icon: searchIcon },
],
});
document.body.append(navigationBar.element);
<m-navigation-bar value="home" item-layout="horizontal">
<m-navigation-bar-item value="home">Home</m-navigation-bar-item>
<m-navigation-bar-item value="search">Search</m-navigation-bar-item>
</m-navigation-bar>
<script type="module">
const navigationBar = document.querySelector('m-navigation-bar');
navigationBar.querySelector('m-navigation-bar-item[value="home"]').setAttribute('icon', heartOutlineIcon);
navigationBar.querySelector('m-navigation-bar-item[value="home"]').setAttribute('selected-icon', heartFilledIcon);
navigationBar.querySelector('m-navigation-bar-item[value="search"]').setAttribute('icon', searchIcon);
</script>
import { useState } from 'react';
import { NavigationBar, NavigationBarItem } from 'material/react';
import { heartOutlineIcon, heartFilledIcon, searchIcon } from './app';
export function Example() {
const [value, setValue] = useState("home");
return (
<NavigationBar value={value} onChange={(event) => setValue(event.detail.value)} itemLayout="horizontal">
<NavigationBarItem value="home" icon={heartOutlineIcon} selectedIcon={heartFilledIcon}>Home</NavigationBarItem>
<NavigationBarItem value="search" icon={searchIcon}>Search</NavigationBarItem>
</NavigationBar>
);
}
<script setup lang="ts">
import { ref } from 'vue';
import { MNavigationBar, MNavigationBarItem } from 'material/vue';
import { heartOutlineIcon, heartFilledIcon, searchIcon } from './app';
const value = ref("home");
</script>
<template>
<MNavigationBar v-model="value" item-layout="horizontal">
<MNavigationBarItem value="home" :icon="heartOutlineIcon" :selected-icon="heartFilledIcon">Home</MNavigationBarItem>
<MNavigationBarItem value="search" :icon="searchIcon">Search</MNavigationBarItem>
</MNavigationBar>
</template>
<script lang="ts">
import { NavigationBar, NavigationBarItem } from 'material/svelte';
import { heartOutlineIcon, heartFilledIcon, searchIcon } from './app';
let value = $state("home");
</script>
<NavigationBar bind:value itemLayout="horizontal">
<NavigationBarItem value="home" icon={heartOutlineIcon} selectedIcon={heartFilledIcon}>Home</NavigationBarItem>
<NavigationBarItem value="search" icon={searchIcon}>Search</NavigationBarItem>
</NavigationBar>
import { createSignal } from 'solid-js';
import { NavigationBar, NavigationBarItem } from 'material/solid';
import { heartOutlineIcon, heartFilledIcon, searchIcon } from './app';
export function Example() {
const [value, setValue] = createSignal("home");
return (
<NavigationBar value={value()} onChange={(event) => setValue(event.detail.value)} itemLayout="horizontal">
<NavigationBarItem value="home" icon={heartOutlineIcon} selectedIcon={heartFilledIcon}>Home</NavigationBarItem>
<NavigationBarItem value="search" icon={searchIcon}>Search</NavigationBarItem>
</NavigationBar>
);
}
Hide on scroll
hideOnScroll slides the bar out of view after the page scrolls down by 10 pixels, and back when it scrolls up. true follows the window; an object { target } follows that element's scroll instead. Focus inside the bar shows it again. hide() and show() do the same without a scroll.
import { createNavigationBar } from 'material';
const navigationBar = createNavigationBar({
hideOnScroll: true,
items: [
{ id: 'home', label: 'Home', icon: homeIcon, active: true },
{ id: 'search', label: 'Search', icon: searchIcon },
],
});
document.body.append(navigationBar.element);
<m-navigation-bar value="home" hide-on-scroll>
<m-navigation-bar-item value="home">Home</m-navigation-bar-item>
<m-navigation-bar-item value="search">Search</m-navigation-bar-item>
</m-navigation-bar>
<script type="module">
const navigationBar = document.querySelector('m-navigation-bar');
navigationBar.querySelector('m-navigation-bar-item[value="home"]').setAttribute('icon', homeIcon);
navigationBar.querySelector('m-navigation-bar-item[value="search"]').setAttribute('icon', searchIcon);
</script>
import { useState } from 'react';
import { NavigationBar, NavigationBarItem } from 'material/react';
import { homeIcon, searchIcon } from './app';
export function Example() {
const [value, setValue] = useState("home");
return (
<NavigationBar value={value} onChange={(event) => setValue(event.detail.value)} hideOnScroll>
<NavigationBarItem value="home" icon={homeIcon}>Home</NavigationBarItem>
<NavigationBarItem value="search" icon={searchIcon}>Search</NavigationBarItem>
</NavigationBar>
);
}
<script setup lang="ts">
import { ref } from 'vue';
import { MNavigationBar, MNavigationBarItem } from 'material/vue';
import { homeIcon, searchIcon } from './app';
const value = ref("home");
</script>
<template>
<MNavigationBar v-model="value" hide-on-scroll>
<MNavigationBarItem value="home" :icon="homeIcon">Home</MNavigationBarItem>
<MNavigationBarItem value="search" :icon="searchIcon">Search</MNavigationBarItem>
</MNavigationBar>
</template>
<script lang="ts">
import { NavigationBar, NavigationBarItem } from 'material/svelte';
import { homeIcon, searchIcon } from './app';
let value = $state("home");
</script>
<NavigationBar bind:value hideOnScroll>
<NavigationBarItem value="home" icon={homeIcon}>Home</NavigationBarItem>
<NavigationBarItem value="search" icon={searchIcon}>Search</NavigationBarItem>
</NavigationBar>
import { createSignal } from 'solid-js';
import { NavigationBar, NavigationBarItem } from 'material/solid';
import { homeIcon, searchIcon } from './app';
export function Example() {
const [value, setValue] = createSignal("home");
return (
<NavigationBar value={value()} onChange={(event) => setValue(event.detail.value)} hideOnScroll>
<NavigationBarItem value="home" icon={homeIcon}>Home</NavigationBarItem>
<NavigationBarItem value="search" icon={searchIcon}>Search</NavigationBarItem>
</NavigationBar>
);
}
A selection emits select with { id, value, index, originalEvent }. value is the destination's id, the same field the web component's change event carries. Arrow keys move between destinations along the row; Home and End move to the ends.
API
Options
| Option | Type | Default | Description |
|---|---|---|---|
items |
NavigationBarItemConfig[] |
[] |
Destinations; each needs a unique id, a label and an icon |
itemLayout |
'auto' | 'vertical' | 'horizontal' |
'auto' |
Icon above the label, beside it, or above until the bar is 600px wide |
hideOnScroll |
boolean | { target?: HTMLElement | Window } |
off | Hide on scroll down, show on scroll up; true follows the window |
ariaLabel |
string |
'Primary navigation' |
The landmark's accessible name |
ripple |
boolean |
true |
false is the element's no-ripple attribute |
onSelect |
(event: NavigationBarSelectEvent) => void |
select listener registered at creation |
Items
| Option | Type | Description |
|---|---|---|
id |
string |
Unique among the bar's destinations |
label |
string |
The text under or beside the icon |
icon |
string |
SVG markup. The element takes it as icon |
activeIcon |
string |
SVG markup shown while this destination is active. The element takes it as selected-icon |
href |
string |
Renders the destination as a link and keeps the browser's navigation |
badge |
string | number | boolean |
A count, a short text, or true for the dot |
badgeLabel |
string |
The accessible name of the badge |
active |
boolean |
Whether this destination starts selected |
disabled |
boolean |
Whether the destination is inert |
Methods
| Method | Returns | Description |
|---|---|---|
getActive() |
string | null |
The selected destination's id |
setActive(id) |
this |
Selects a destination without emitting select; null clears it |
getItems() |
NavigationBarItemConfig[] |
The destinations |
setItems(items) |
this |
Replaces the destinations |
setBadge(id, badge, label?) |
this |
Sets or clears one destination's badge |
hide() |
this |
Slides the bar out of view |
show() |
this |
Slides the bar back |
isHidden() |
boolean |
Whether hide() or a scroll has hidden it |
on(event, handler) |
this |
Listens for select or visibility |
off(event, handler) |
this |
Removes that listener |
destroy() |
void |
Removes the bar and its listeners |
Element
<m-navigation-bar> takes value (the selected destination's id), item-layout, hide-on-scroll, no-ripple and aria-label. value is also the live property. It dispatches change with { value } and visibility with { hidden }. hide() and show() are methods.
<m-navigation-bar-item> takes value, icon, selected-icon, href, badge, badge-label and disabled. Its text is the label. An empty badge attribute is the dot.