Nav rail
A vertical navigation bar that can collapse to icons.
import '@usezeno/tokens/css';
import '@usezeno/core/web-components';
Examples
Basic rail
Set items and activeItem as properties. The rail fires item-select when an item is chosen.
Nothing selected yet.
<zeno-nav-rail></zeno-nav-rail>
<p data-result>Nothing selected yet.</p>
const rail = document.querySelector('zeno-nav-rail');
rail.items = [
{ id: 'home', value: 'home', label: 'Home', icon: 'home' },
{ id: 'search', value: 'search', label: 'Search', icon: 'search' },
{ id: 'saved', value: 'saved', label: 'Saved', icon: 'heart' },
{ id: 'settings', value: 'settings', label: 'Settings', icon: 'settings' },
];
rail.activeItem = 'home';
rail.addEventListener('item-select', event => {
document.querySelector('[data-result]').textContent = 'Selected: ' + event.detail.value;
});
Expanded, with sections and a badge
With expanded the rail is wider and shows the labels. Items with the same section are listed under that title.
<zeno-nav-rail expanded></zeno-nav-rail>
const rail = document.querySelector('zeno-nav-rail');
rail.items = [
{ id: 'home', value: 'home', label: 'Home', icon: 'home', section: 'Workspace' },
{ id: 'saved', value: 'saved', label: 'Saved', icon: 'star', badge: 3, section: 'Workspace' },
{ id: 'profile', value: 'profile', label: 'Profile', icon: 'user', section: 'Account' },
{ id: 'settings', value: 'settings', label: 'Settings', icon: 'settings', section: 'Account' },
];
rail.activeItem = 'saved';
The toggle button
The button at the top switches expanded and fires toggle. Set the showToggle property to false to remove it.
The rail is collapsed.
<zeno-nav-rail></zeno-nav-rail>
<p data-result>The rail is collapsed.</p>
const rail = document.querySelector('zeno-nav-rail');
rail.items = [
{ id: 'home', value: 'home', label: 'Home', icon: 'home' },
{ id: 'profile', value: 'profile', label: 'Profile', icon: 'user' },
];
rail.activeItem = 'home';
rail.addEventListener('toggle', event => {
document.querySelector('[data-result]').textContent =
event.detail.expanded ? 'The rail is expanded.' : 'The rail is collapsed.';
});
Attributes and properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
items | items | NavRailItem[] | [] | |
activeItem | activeitem | string | '' | |
expanded | expandedreflects | boolean | false | |
showToggle | show-togglereflects | boolean | true | |
testId | string | Test ID for automated testing From ZenoElement. |
Methods
| Method | Description |
|---|---|
toggleExpanded(): void | Toggle expanded state |
selectItem(value: string): void | Select an item |
focus(): void | Focus the component or its first focusable element From ZenoElement. |
blur(): void | Blur the component or its focused element From ZenoElement. |
Events
| Event | Detail | Description |
|---|---|---|
toggle | { expanded: boolean } | The rail was expanded or collapsed. |
item-select | { value: string; item: NavRailItem } | An item was selected. |
Slots
| Slot | Description |
|---|---|
footer | Content below the items. |
header | Content above the items. |
CSS parts
| Part |
|---|
badge |
base |
footer |
header |
icon |
item |
items |
label |
link |
list |
section |
section-list |
section-title |
toggle |
tooltip |
CSS custom properties
This element documents no custom properties of its own. Style it through its parts and through the tokens it reads.
The element's own source reads no tokens.
Types
interface NavRailItem {
id: string;
value: string;
label: string;
icon?: string;
href?: string;
target?: string;
rel?: string;
section?: string;
disabled?: boolean;
badge?: string | number;
}
Accessibility
Keyboard
| Key | What it does |
|---|---|
| Tab | Moves focus to the toggle button, then to each item in turn. Every item is a Tab stop. |
| EnterSpace | On the toggle button, expands or collapses the rail. On an item, selects it. Enter on an item with href follows the link. |
| ArrowDownArrowUp | Selects the next or previous item and moves focus to it. Wraps at both ends. |
| HomeEnd | Selects the first or last item and moves focus to it. |
Forms
This element is not a form control. It adds nothing to a form's data.
Notes
- Renders a
<nav>landmark. It is named by thearia-labelof the element, or “Navigation rail” when there is none. - Items are native links when they have
hrefand native buttons when they do not, inside nested lists. - The active link has
aria-current="page"and the active button hasaria-current="true". - The toggle button has
aria-expandedand is named “Expand navigation” or “Collapse navigation”. - With reduced motion the rail has no transitions. The rail is hidden when the page is printed.
Tests and known gaps
- No tests of its own. The only check is that the element registers and renders (
smoke.test.ts). - Not checked with axe-core.
- Has no Storybook story.
19 of the 28 properties, methods, events, slots and parts above have no description in the source
- the property
items - the property
activeItem - the property
expanded - the property
showToggle - the part
badge - the part
base - the part
footer - the part
header - the part
icon - the part
item - the part
items - the part
label - the part
link - the part
list - the part
section - the part
section-list - the part
section-title - the part
toggle - the part
tooltip
Known gaps:
- Each link or button is rendered empty. The icon, label and badge are placed after it, not inside it. The control has no accessible name, a click on the icon or label does nothing, and the item looks like an empty box with its content under it.
- The tooltip of a collapsed rail never shows, because it is not inside the link that the hover style looks at.
- In a collapsed rail the labels are removed with
display: none. Together with the two gaps above, items have no name at all for assistive technology. - The arrow keys go to the wrong item when the rail has sections or disabled items. The handler mixes three different ways of counting the items.
- The arrow keys, Home and End select the item they move to. In a rail of links this changes
activeItemand firesitem-selectwithout loading the page of that link. - A disabled item is only dimmed and closed to the pointer. It is still a Tab stop and is not announced as disabled.
show-toggleis on by default and a Boolean attribute cannot turn it off. Only the propertyshowToggle = falseworks.- The
headerslot is removed together with the toggle button whenshowToggleisfalse. - The attribute for
activeItemisactiveitem, with no dash. The other attributes of the element use dashes. - Buttons that are not active carry
aria-current="false". The attribute should be left out. - Item icons only work for the names
zeno-iconhas built in or the page has registered. The sizes24and20that the rail asks for do not exist inzeno-icon. - “Navigation rail”, “Expand navigation” and “Collapse navigation” are English only. Only the first can be replaced, with
aria-label. - The width does not animate when the rail expands or collapses. The transition value is not valid CSS.
- The border, the active marker, the badge and the tooltip are placed with left and right. They do not follow a right-to-left page.