Docs

Documentation versions (currently viewingVaadin 24)

Side Navigation

Side Navigation provides a vertical list of navigation links with support for collapsible, nested sections.

Side Navigation provides a vertical list of navigation links with support for collapsible, nested sections.

Note
Navigation Disabled in Examples

For technical reasons, actual navigation is disabled in the examples on this page.

Open in a
new tab
<vaadin-side-nav style="width:100%" id="sideNav">
  <vaadin-side-nav-item path="/dashboard">
    <vaadin-icon icon="vaadin:dashboard" slot="prefix"></vaadin-icon>
    Dashboard
  </vaadin-side-nav-item>
  <vaadin-side-nav-item path="/inbox">
    <vaadin-icon icon="vaadin:envelope" slot="prefix"></vaadin-icon>
    Inbox
  </vaadin-side-nav-item>
  <vaadin-side-nav-item path="/calendar">
    <vaadin-icon icon="vaadin:calendar" slot="prefix"></vaadin-icon>
    Calendar
  </vaadin-side-nav-item>
  <vaadin-side-nav-item path="/settings">
    <vaadin-icon icon="vaadin:cog" slot="prefix"></vaadin-icon>
    Settings
  </vaadin-side-nav-item>
  <vaadin-side-nav-item path="https://vaadin.com">
    <vaadin-icon icon="vaadin:vaadin-h" slot="prefix"></vaadin-icon>
    Vaadin website
  </vaadin-side-nav-item>
</vaadin-side-nav>

The Side Navigation component can be used, for example, in a drawer of an App Layout.

Automatic Highlighting of Current Item

The navigation item matching the current URL is highlighted automatically to indicate it’s active.

Nested Matching

By default, items only match the exact path of the current URL. To enable matching of nested paths or routes, set the matchNested property to true. With nested matching, an item with the path /parent not only matches /parent, but also /parent/child, /parent/child/grandchild, etc.

<vaadin-side-nav-item path="/users" match-nested>
  Users
</vaadin-side-nav-item>

Query Parameters

If an item’s path contains query parameters, only URLs containing those parameters are considered a match. Additional parameters in the URL not specified in the item path are ignored — the URL is considered a match.

Prefix & Suffix Elements

Navigation items have slots for prefix and suffix elements. The prefix slot is intended primarily for icons, while the suffix slot can be used, for example, for notification badges.

Interactive prefix and suffix elements aren’t recommended since the entire item row acts as a link.

Open in a
new tab
<vaadin-side-nav style="width:100%">
  <vaadin-side-nav-item path="/inbox">
    <vaadin-icon icon="vaadin:envelope" slot="prefix"></vaadin-icon>
    Inbox
    <span theme="badge contrast pill" aria-label="12 unread messages" slot="suffix"
      >12</span
    >
  </vaadin-side-nav-item>
  <vaadin-side-nav-item path="/calendar">
    <vaadin-icon icon="vaadin:calendar" slot="prefix"></vaadin-icon>
    Calendar
    <vaadin-icon
      icon="vaadin:bell"
      theme="badge error pill"
      style="padding:var(--lumo-space-xs)"
      aria-label="Upcoming appointment"
      slot="suffix"
    ></vaadin-icon>
  </vaadin-side-nav-item>
</vaadin-side-nav>

Hierarchy

Navigation items can contain sub-items, which are collapsed by default. There’s no technical limitation on the number of nesting levels. However, a maximum of three levels is recommended for better usability.

Parent items can be links. Clicking them expands their sub-items in addition to navigating. Non-link parent items can be achieved by omitting the target path.

Open in a
new tab
<vaadin-side-nav style="width:100%">
  <vaadin-side-nav-item path="/messages">
    <vaadin-icon icon="vaadin:envelope" slot="prefix"></vaadin-icon>
    Messages
    <vaadin-side-nav-item path="/inbox" slot="children">
      <vaadin-icon icon="vaadin:inbox" slot="prefix"></vaadin-icon>
      Inbox
    </vaadin-side-nav-item>
    <vaadin-side-nav-item path="/sent" slot="children">
      <vaadin-icon icon="vaadin:paperplane" slot="prefix"></vaadin-icon>
      Sent
    </vaadin-side-nav-item>
    <vaadin-side-nav-item path="/trash" slot="children">
      <vaadin-icon icon="vaadin:trash" slot="prefix"></vaadin-icon>
      Trash
    </vaadin-side-nav-item>
  </vaadin-side-nav-item>
  <vaadin-side-nav-item>
    <vaadin-icon icon="vaadin:cog" slot="prefix"></vaadin-icon>
    Admin
    <vaadin-side-nav-item path="/users" slot="children">
      <vaadin-icon icon="vaadin:group" slot="prefix"></vaadin-icon>
      Users
    </vaadin-side-nav-item>
    <vaadin-side-nav-item path="/permissions" slot="children">
      <vaadin-icon icon="vaadin:key" slot="prefix"></vaadin-icon>
      Permissions
    </vaadin-side-nav-item>
  </vaadin-side-nav-item>
</vaadin-side-nav>

Labeled Collapsible List

A label can be applied to the top of the navigation list. This can be useful for cases with multiple adjacent Side Navigation lists. A labeled Side Navigation list can be made collapsible.

Open in a
new tab
<vaadin-vertical-layout theme="spacing">
  <vaadin-side-nav style="width:100%">
    <span slot="label">Messages</span>
    <vaadin-side-nav-item path="/inbox">
      <vaadin-icon icon="vaadin:inbox" slot="prefix"></vaadin-icon>
      Inbox
    </vaadin-side-nav-item>
    <vaadin-side-nav-item path="/sent">
      <vaadin-icon icon="vaadin:paperplane" slot="prefix"></vaadin-icon>
      Sent
    </vaadin-side-nav-item>
    <vaadin-side-nav-item path="/trash">
      <vaadin-icon icon="vaadin:trash" slot="prefix"></vaadin-icon>
      Trash
    </vaadin-side-nav-item>
  </vaadin-side-nav>

  <vaadin-side-nav collapsible style="width:100%">
    <span slot="label">Admin</span>
    <vaadin-side-nav-item path="/users">
      <vaadin-icon icon="vaadin:group" slot="prefix"></vaadin-icon>
      Users
    </vaadin-side-nav-item>
    <vaadin-side-nav-item path="/permissions">
      <vaadin-icon icon="vaadin:key" slot="prefix"></vaadin-icon>
      Permissions
    </vaadin-side-nav-item>
  </vaadin-side-nav>
</vaadin-vertical-layout>

Another Browser Tab or Window

A navigation link can be opened in another browser tab or window — depending on the browser’s configuration — by specifying the name of the tab or window as the link’s target. A new, unnamed tab or window can be set as the target by providing the name _blank, for which the Flow API provides the shorthand method setOpenInNewBrowserTab().

SideNavItem item = new SideNavItem("Example", "https://example.com");
item.setOpenInNewBrowserTab(true);

Scrolling

The Side Navigation component doesn’t contain a scroll area. Instead, it can be made scrollable by wrapping it inside a Scroller.

Keyboard Usage

Shortcut Function

Tab

Navigation between list items.

Tab

Navigation between link and expand and collapse button.

Enter / Space

Toggles expand and collapse.

Enter

Trigger link.

Styling Individual Items

Individual navigation items can be styled by applying a CSS class name to them.

Open in a
new tab
<vaadin-side-nav style="width:100%">
  <vaadin-side-nav-item path="/dashboard">
    <vaadin-icon icon="vaadin:dashboard" slot="prefix"></vaadin-icon>
    Dashboard
  </vaadin-side-nav-item>
  <vaadin-side-nav-item path="/inbox">
    <vaadin-icon icon="vaadin:envelope" slot="prefix"></vaadin-icon>
    Inbox
  </vaadin-side-nav-item>
  <vaadin-side-nav-item path="https://vaadin.com" class="external">
    <vaadin-icon icon="vaadin:vaadin-h" slot="prefix"></vaadin-icon>
    Vaadin website
  </vaadin-side-nav-item>
</vaadin-side-nav>

Client-Side Router Integration

By default, clicking a navigation link in a client-side application triggers a full page reload. When using a client-side router (e.g., React Router), this might be undesirable as it disrupts the single-page application experience.

To prevent this behavior, you can assign a callback function to the Side Navigation component’s onNavigate property. That would cancel the default action on a link click and delegate the responsibility of navigation to the provided function. The function receives an object with properties of the clicked navigation item, including path, which can be used to navigate to the desired route.

Additionally, the Side Navigation component needs to be notified of route changes to have it automatically highlight the currently active item. This can be achieved by updating the Side Navigation component’s location property whenever the route changes.

The following example demonstrates how to integrate the <SideNav> component with React Router:

const navigate = useNavigate();
const location = useLocation();

return (
  <SideNav
    location={location}
    onNavigate={({ path }) => {
      if (path) {
        navigate(path);
      }
    }}
  >
    <SideNavItem path="/inbox">Inbox</SideNavItem>
    <SideNavItem path="/calendar">Calendar</SideNavItem>
  </SideNav>
);

10387B24-0DDF-4FC8-B5F9-B6319633D354