> Markdown version of [Side Navigation](https://vaadin.com/docs/next/components/side-nav). Section index: [llms.txt](https://vaadin.com/docs/next/components/llms.txt)

# Side Navigation

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.

**Lit** — `side-nav-basic.ts`

```html
<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>
```

**Flow** — `SideNavBasic.java`

```java
SideNav nav = new SideNav();

SideNavItem dashboardLink = new SideNavItem("Dashboard",
        DashboardView.class, VaadinIcon.DASHBOARD.create());
SideNavItem inboxLink = new SideNavItem("Inbox", InboxView.class,
        VaadinIcon.ENVELOPE.create());
SideNavItem calendarLink = new SideNavItem("Calendar",
        CalendarView.class, VaadinIcon.CALENDAR.create());
SideNavItem settingsLink = new SideNavItem("Settings",
        SettingsView.class, VaadinIcon.COG.create());
SideNavItem vaadinLink = new SideNavItem("Vaadin website",
        "https://vaadin.com", VaadinIcon.VAADIN_H.create());

nav.addItem(dashboardLink, inboxLink, calendarLink, settingsLink,
        vaadinLink);
```

**React** — `side-nav-basic.tsx`

```tsx
<SideNav style={{ width: '100%' }} id="sideNav" ref={sideNavRef}>
  <SideNavItem path="/dashboard">
    <Icon icon="vaadin:dashboard" slot="prefix" />
    Dashboard
  </SideNavItem>
  <SideNavItem path="/inbox">
    <Icon icon="vaadin:envelope" slot="prefix" />
    Inbox
  </SideNavItem>
  <SideNavItem path="/calendar">
    <Icon icon="vaadin:calendar" slot="prefix" />
    Calendar
  </SideNavItem>
  <SideNavItem path="/settings">
    <Icon icon="vaadin:cog" slot="prefix" />
    Settings
  </SideNavItem>
  <SideNavItem path="https://vaadin.com">
    <Icon icon="vaadin:vaadin-h" slot="prefix" />
    Vaadin website
  </SideNavItem>
</SideNav>
```

The Side Navigation component can be used, for example, in a drawer of an [App Layout](https://vaadin.com/docs/next/components/app-layout.md).

## <a id="automatic-highlighting-of-current-item"></a>Automatic Highlighting of Current Item

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

### <a id="nested-matching"></a>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.

**Lit**

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

**Flow**

```java
SideNavItem item = new SideNavItem("Users", "/users");
item.setMatchNested(true);
```

**React**

```tsx
<SideNavItem path="/users" matchNested>
  Users
</SideNavItem>
```

### <a id="query-parameters"></a>Query Parameters

If an item’s path contains [query parameters](https://vaadin.com/docs/next/flow/routing/additional-guides/query-parameters.md), 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.

### <a id="automatic-expansion-of-parent-items"></a>Automatic Expansion of Parent Items (since V25.0)

When the current URL matches a nested item, all its parent items are automatically expanded to reveal the active item. This behavior can be disabled for the whole side navigation if desired.

**Lit**

```html
<vaadin-side-nav no-auto-expand>
  ...
</vaadin-side-nav>
```

**Flow**

```java
sideNav.setAutoExpand(false);
```

**React**

```tsx
<SideNav noAutoExpand>
  ...
</SideNav>
```

## <a id="prefix-suffix-elements"></a>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.

**Lit** — `side-nav-suffix.ts`

```html
<vaadin-side-nav style="width:100%">
  <vaadin-side-nav-item path="/inbox">
    <vaadin-icon icon="vaadin:envelope" slot="prefix"></vaadin-icon>
    Inbox
    <vaadin-badge number="12" theme="filled number-only" slot="suffix">
      unread messages
    </vaadin-badge>
  </vaadin-side-nav-item>
  <vaadin-side-nav-item path="/calendar">
    <vaadin-icon icon="vaadin:calendar" slot="prefix"></vaadin-icon>
    Calendar
    <vaadin-badge theme="error icon-only" slot="suffix">
      <vaadin-icon icon="vaadin:bell" slot="icon"></vaadin-icon>
      Upcoming appointment
    </vaadin-badge>
  </vaadin-side-nav-item>
</vaadin-side-nav>
```

**Flow** — `SideNavSuffix.java`

```java
SideNav nav = new SideNav();

SideNavItem inboxLink = new SideNavItem("Inbox", InboxView.class,
        VaadinIcon.ENVELOPE.create());
Badge inboxCounter = new Badge("unread messages", 12);
inboxCounter.addThemeVariants(BadgeVariant.FILLED,
        BadgeVariant.NUMBER_ONLY);
inboxLink.setSuffixComponent(inboxCounter);

SideNavItem calendarLink = new SideNavItem("Calendar",
        CalendarView.class, VaadinIcon.CALENDAR.create());
Badge calendarNotification = new Badge("Upcoming appointment");
calendarNotification.setIcon(VaadinIcon.BELL.create());
calendarNotification.addThemeVariants(BadgeVariant.ERROR,
        BadgeVariant.ICON_ONLY);
calendarLink.setSuffixComponent(calendarNotification);

nav.addItem(inboxLink, calendarLink);
```

**React** — `side-nav-suffix.tsx`

```tsx
<SideNav style={{ width: '100%' }} ref={sideNavRef}>
  <SideNavItem path="/inbox">
    <Icon icon="vaadin:envelope" slot="prefix" />
    Inbox
    <Badge number={12} theme="filled number-only" slot="suffix">
      unread messages
    </Badge>
  </SideNavItem>
  <SideNavItem path="/calendar">
    <Icon icon="vaadin:calendar" slot="prefix" />
    Calendar
    <Badge theme="error icon-only" slot="suffix">
      <Icon icon="vaadin:bell" slot="icon" />
      Upcoming appointment
    </Badge>
  </SideNavItem>
</SideNav>
```

## <a id="hierarchy"></a>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.

**Lit** — `side-nav-hierarchy.ts`

```html
<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>
```

**Flow** — `SideNavHierarchy.java`

```java
SideNav nav = new SideNav();

SideNavItem messagesLink = new SideNavItem("Messages",
        MessagesView.class, VaadinIcon.ENVELOPE.create());
messagesLink.addItem(new SideNavItem("Inbox", InboxView.class,
        VaadinIcon.INBOX.create()));
messagesLink.addItem(new SideNavItem("Sent", SentView.class,
        VaadinIcon.PAPERPLANE.create()));
messagesLink.addItem(new SideNavItem("Trash", TrashView.class,
        VaadinIcon.TRASH.create()));

SideNavItem adminSection = new SideNavItem("Admin");
adminSection.setPrefixComponent(VaadinIcon.COG.create());
adminSection.addItem(new SideNavItem("Users", UsersView.class,
        VaadinIcon.GROUP.create()));
adminSection.addItem(new SideNavItem("Permissions",
        PermissionsView.class, VaadinIcon.KEY.create()));

nav.addItem(messagesLink, adminSection);
```

**React** — `side-nav-hierarchy.tsx`

```tsx
<SideNav style={{ width: '100%' }} id="sideNav" ref={sideNavRef}>
  <SideNavItem path="/messages">
    <Icon icon="vaadin:envelope" slot="prefix" />
    Messages
    <SideNavItem path="/inbox" slot="children">
      <Icon icon="vaadin:inbox" slot="prefix" />
      Inbox
    </SideNavItem>
    <SideNavItem path="/sent" slot="children">
      <Icon icon="vaadin:paperplane" slot="prefix" />
      Sent
    </SideNavItem>
    <SideNavItem path="/trash" slot="children">
      <Icon icon="vaadin:trash" slot="prefix" />
      Trash
    </SideNavItem>
  </SideNavItem>
  <SideNavItem>
    <Icon icon="vaadin:cog" slot="prefix" />
    Admin
    <SideNavItem path="/users" slot="children">
      <Icon icon="vaadin:group" slot="prefix" />
      Users
    </SideNavItem>
    <SideNavItem path="/permissions" slot="children">
      <Icon icon="vaadin:key" slot="prefix" />
      Permissions
    </SideNavItem>
  </SideNavItem>
</SideNav>
```

## <a id="labeled-collapsible-list"></a>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.

**Lit** — `side-nav-labelled.ts`

```html
<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>
```

**Flow** — `SideNavLabelled.java`

```java
SideNav messagesNav = new SideNav();
messagesNav.setLabel("Messages");
messagesNav.addItem(new SideNavItem("Inbox", InboxView.class,
        VaadinIcon.INBOX.create()));
messagesNav.addItem(new SideNavItem("Sent", SentView.class,
        VaadinIcon.PAPERPLANE.create()));
messagesNav.addItem(new SideNavItem("Trash", TrashView.class,
        VaadinIcon.TRASH.create()));

SideNav adminNav = new SideNav();
adminNav.setLabel("Admin");
adminNav.setCollapsible(true);
adminNav.addItem(new SideNavItem("Users", UsersView.class,
        VaadinIcon.GROUP.create()));
adminNav.addItem(new SideNavItem("Permissions", PermissionsView.class,
        VaadinIcon.KEY.create()));
```

**React** — `side-nav-labelled.tsx`

```tsx
<VerticalLayout theme="spacing">
  <SideNav style={{ width: '100%' }} ref={sideNavRef}>
    <span slot="label">Messages</span>
    <SideNavItem path="/inbox">
      <Icon icon="vaadin:inbox" slot="prefix" />
      Inbox
    </SideNavItem>
    <SideNavItem path="/sent">
      <Icon icon="vaadin:paperplane" slot="prefix" />
      Sent
    </SideNavItem>
    <SideNavItem path="/trash">
      <Icon icon="vaadin:trash" slot="prefix" />
      Trash
    </SideNavItem>
  </SideNav>
  <SideNav style={{ width: '100%' }} collapsible ref={secondSideNavRef}>
    <span slot="label">Admin</span>
    <SideNavItem path="/users">
      <Icon icon="vaadin:group" slot="prefix" />
      Users
    </SideNavItem>
    <SideNavItem path="/permissions">
      <Icon icon="vaadin:key" slot="prefix" />
      Permissions
    </SideNavItem>
  </SideNav>
</VerticalLayout>
```

## <a id="another-browser-tab-or-window"></a>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()`.

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

```html
<vaadin-side-nav-item path="https://example.com" target="_blank">
  Example
</vaadin-side-nav-item>
```

```tsx
<SideNavItem path="https://example.com" target="_blank">Example</SideNavItem>
```

## <a id="scrolling"></a>Scrolling

The Side Navigation component doesn’t contain a scroll area. Instead, it can be made scrollable by wrapping it inside a [Scroller](https://vaadin.com/docs/next/components/scroller.md).

## <a id="keyboard-usage"></a>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.                                           |

## <a id="client-side-router-integration"></a>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:

**React** — `side-nav-router.tsx`

```tsx
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`
