> Markdown version of [Add a Navigation Menu](https://vaadin.com/docs/next/building-apps/views/add-navi-menu). Section index: [llms.txt](https://vaadin.com/docs/next/building-apps/llms.txt)

# Add a Navigation Menu

This guide teaches you how to add a navigation menu to a router layout in Vaadin. It is a continuation of the [Add a Router Layout](https://vaadin.com/docs/next/building-apps/views/add-router-layout.md) guide.

## <a id="copy-paste-into-your-project"></a>Copy-Paste into Your Project

If you want to quickly try out a navigation menu, you can copy-paste the following code into your router layout:

`MainLayout.java`

```java
private SideNav createSideNav() {
    var nav = new SideNav();
    MenuConfiguration.getMenuEntries()
            .forEach(entry -> nav.addItem(createSideNavItem(entry)));
    return nav;
}

private SideNavItem createSideNavItem(MenuEntry menuEntry) {
    var item = new SideNavItem(menuEntry.title(), menuEntry.menuClass());
    item.setMatchNested(true);
    if (menuEntry.icon() != null) {
        item.setPrefixComponent(new Icon(menuEntry.icon()));
    }
    return item;
}
```

Expand the code for a complete implementation of a router layout with a navigation menu. For more detailed instructions on how to use build a navigation menu, continue reading below.

## <a id="creating-a-navigation-menu"></a>Creating a Navigation Menu

You typically build a navigation menu in Vaadin using the Side Navigation components, which provide a vertical list of navigation links with support for collapsible, nested sections. This guide only covers the very basics of building a navigation menu. For more detailed information, see the [Side Navigation](https://vaadin.com/docs/next/components/side-nav.md) documentation.

Start by creating an instance of `SideNav` to act as the container for the navigation items:

```java
private SideNav createSideNav() {
    SideNav sideNav = new SideNav();
    // Add navigation items here
    return sideNav;
}
```

For every item in the navigation menu, create an instance of `SideNavItem`, and add it to the `SideNav` instance. Each item represents a link to a view in your application. You can create a simple navigation item like this:

```java
SideNavItem homeItem = new SideNavItem("Home", HomeView.class);
sideNav.addItem(homeItem);
```

Now, whenever the user clicks on the item, the router navigates to the specified view. Furthermore, the item is highlighted when the user is on that view.

### <a id="highlighting-nested-views"></a>Highlighting Nested Views

By default, a `SideNavItem` is highlighted only when the user is on the exact path of the view. That means that if the view has e.g. a URL parameter, or acts as a parent layout for another view, the item is not highlighted.

For example, an item with the path `/customers` has the following behavior:

- `/customers` — item is highlighted

- `/customers/123` — item is **not** highlighted

- `/customers/123/edit` — item is **not** highlighted

To highlight the item for all paths that start with the view’s path, use the `SideNavItem.setMatchNested()` method:

```java
SideNavItem customersItem = new SideNavItem("Customers", CustomersView.class);
customersItem.setMatchNested(true);
// Now matches /customers, /customers/123, /customers/123/edit, etc.
sideNav.addItem(customersItem);
```

## <a id="getting-the-menu-items-dynamically"></a>Getting the Menu Items Dynamically

If your views have [navigation menu items](https://vaadin.com/docs/next/building-apps/views/add-view.md#navigation-menu-item) defined using the `@Menu` annotation, you can build the menu dynamically.

The `MenuConfiguration.getMenuEntries()` method returns a list of all menu entries defined in the application. You can iterate over these entries and create corresponding `SideNavItem` instances for each entry:

```java
private SideNav createSideNav() {
    var nav = new SideNav();
    MenuConfiguration.getMenuEntries()
            .forEach(entry -> nav.addItem(
                new SideNavItem(
                    entry.title(),
                    entry.menuClass()
                )
            ));
    return nav;
}
```

For technical details, see the [Menu Configuration](https://vaadin.com/docs/next/flow/routing/menu-configuration.md) reference guide.

### <a id="showing-only-accessible-views"></a>Showing Only Accessible Views

`MenuConfiguration.getMenuEntries()` leaves out the views that the current user can’t open. It checks each view against the same [access rules](https://vaadin.com/docs/next/building-apps/security/protect-views.md) that protect the view itself. For example, a user without the `ADMIN` role doesn’t get a menu item for a view annotated with `@RolesAllowed("ADMIN")`. It also leaves out views whose routes have required parameters, because a menu item has no values to give them.

Menu items that you create yourself are shown to every user. To hide one, check the roles of the user with `AuthenticationContext`, as described in [Checking the Roles of the Current User](https://vaadin.com/docs/next/building-apps/security/protect-views.md#checking-the-roles-of-the-current-user).

A hidden menu item doesn’t protect its view: a user can still type the URL in the address bar. Every view needs access rules of its own.

## <a id="icons-in-the-menu"></a>Icons in the Menu

You often want to have icons in your navigation menu to improve usability and visual appeal. The `@Menu` annotation has an `icon` attribute, but it’s an ordinary string. Therefore, you need to decide how to interpret that string in your menu implementation.

For example, if you use [Vaadin Icons](https://vaadin.com/docs/next/components/icons.md), you can create an icon for a menu item like this:

```java
// Annotation on view:
@Menu(title = "Dashboard", icon = "vaadin:dashboard")

// In the menu building code:
item.setPrefixComponent(new Icon(menuEntry.icon()));
```

If you’re using SVG icons, you can do this instead:

```java
// Annotation on view:
@Menu(title = "Dashboard", icon = "icons/dashboard.svg")

// In the menu building code:
item.setPrefixComponent(new SvgIcon(menuEntry.icon()));
```

## <a id="displaying-the-current-view-title"></a>Displaying the Current View Title

A common pattern is to display the title of the current view in the layout header. To do this, implement `AfterNavigationObserver` in your layout and read the `@PageTitle` annotation from the current view.

```java
public class MainLayout extends AppLayout implements AfterNavigationObserver {
    private final H1 viewTitle = new H1();

    public MainLayout() {
        addToNavbar(new DrawerToggle(), viewTitle);
        // ... rest of setup
    }

    @Override
    public void afterNavigation(AfterNavigationEvent event) {
        viewTitle.setText(getCurrentPageTitle());
    }

    private String getCurrentPageTitle() {
        PageTitle title = getContent().getClass().getAnnotation(PageTitle.class);
        return title == null ? "" : title.value();
    }
}
```

For this to work, views need to declare their titles using the `@PageTitle` annotation. See [Page Title](https://vaadin.com/docs/next/building-apps/views/add-view.md#page-title) for more details on setting page titles.

## <a id="translating-titles-and-menu-items"></a>Translating Titles and Menu Items (since V25.2)

If your application supports several languages, use translation keys as the `@PageTitle` values, and translate them with an application-wide page title generator:

```java
@Bean
PageTitleGenerator pageTitleGenerator() {
    return context -> I18NProvider.translate(context.value()); // (1)
}
```

1. `context.value()` is the `@PageTitle` value of the view, such as `orders.title`.

The generator applies to every view, so give every view a `@PageTitle` key. For a view without one, `context.value()` is empty.

The generator gives the browser tab its title. `MenuConfiguration.getMenuEntries()` also uses it for every view whose `@Menu` annotation has no `title`, so the menu items are translated as well. `MenuConfiguration.getPageHeader(getContent())` returns the translated title, too. Call it in the layout instead of reading the `@PageTitle` annotation as in [Displaying the Current View Title](#displaying-the-current-view-title).

The layout builds the menu when it’s created. If users can change the language while the application is open, rebuild the menu when the locale changes. See [Generating Page Titles](https://vaadin.com/docs/next/flow/routing/page-titles.md#generating-page-titles) for the generator, and the [Localization](https://vaadin.com/docs/next/flow/i18n.md) reference for translation files, language selection, and reacting to locale changes.
