Navigation rail

A navigation rail is the top level navigation for medium sized screens: a narrow vertical strip of destinations that stays visible next to the content. Use it for three to seven destinations. Below that a tab bar reads better, above it a navigation drawer has room for labels and grouping.

Each item needs an icon and a label. Mark the destination the user is on with selected, which fills the icon, moves the label to the stronger colour and draws the pill behind the icon.

Usage

<NavigationRail>
	<NavigationRailItem
		selected={selection === 1}
		onclick={() => {
			selection = 1
		}}
		label="Videos"
	>
		{#snippet icon()}<Icon>videocam</Icon>{/snippet}
	</NavigationRailItem>
	<NavigationRailItem
		selected={selection === 2}
		onclick={() => {
			selection = 2
		}}
		label="Styles"
	>
		{#snippet icon()}<Icon>palette</Icon>{/snippet}
	</NavigationRailItem>
	<NavigationRailItem
		selected={selection === 3}
		onclick={() => {
			selection = 3
		}}
		label="Settings"
	>
		{#snippet icon()}<Icon>settings</Icon>{/snippet}
	</NavigationRailItem>
</NavigationRail>

Pass an href and the item renders as an <a> instead of a <button>. That is the right choice for real navigation: it gives the user a URL to open in a new tab and it lets the browser do its job.

<NavigationRail>
	<NavigationRailItem href="/videos" selected={page.url.pathname === '/videos'} label="Videos">
		{#snippet icon()}<Icon>videocam</Icon>{/snippet}
	</NavigationRailItem>
	<NavigationRailItem href="/styles" selected={page.url.pathname === '/styles'} label="Styles">
		{#snippet icon()}<Icon>palette</Icon>{/snippet}
	</NavigationRailItem>
</NavigationRail>

Accessibility

The rail renders a <nav>, and the selected item gets aria-current="page", so assistive technology announces which destination is the current one.

The items share a single tab stop. Tab moves into and out of the rail as a whole, while and move between the destinations and wrap around at the ends, and Home and End jump to the first and the last one. When several rails or navigations are on the page, give each <nav> an aria-label so they can be told apart.

Theming

TokenDefault value
--np-navigation-rail-item-font-weight500
--np-navigation-rail-item-selected-font-weight500

The colours follow the theme: surface for the rail, on-surface-variant for an idle icon and label, and secondary-container with on-secondary-container for the pill behind the selected icon. Raise --np-navigation-rail-item-selected-font-weight when you want the current destination to stand out more than the colour alone does.

Example

<NavigationRail --np-navigation-rail-item-selected-font-weight="700">
	<NavigationRailItem selected label="Videos">
		{#snippet icon()}<Icon>videocam</Icon>{/snippet}
	</NavigationRailItem>
</NavigationRail>

API

NavigationRail takes no attributes of its own. Everything you pass is forwarded to the <nav> element, so aria-label, class and style work as expected.

Everything else you pass is forwarded to the underlying <button> or <a>, including onclick and href.

AttributeTypeDefaultDescription
iconSnippetRequired. The destination's icon.
labelstringRequired. Text below the icon.
selectedboolean | undefinedundefinedMarks the current destination and sets aria-current="page".
hrefstring | undefinedundefinedRenders the item as a link instead of a button.
type'submit' | 'reset' | 'button' | nullundefinedButton type, for the cases where the item lives inside a form.