> Markdown version of [Creating a Main View](https://vaadin.com/docs/v24/flow/application/main-view). Section index: [llms.txt](https://vaadin.com/docs/v24/flow/llms.txt)

# <a id="flow.application.main-view"></a>Creating a Main View

Applications often have a main view with a menu bar that shows a selection of sub-views. When the user clicks on a menu item, the sub-view is displayed.

The `AppLayout` component allows you to create typical main views that have a header, a menu, and a content area.

It works with full routing and navigation, making it easier to set these up than wiring them yourself. It’s responsive to changes in the screen size and orientation and adapts to both desktop and mobile browsers.

[Image: starter main view]

An example of an application layout

`AppLayout` is highly flexible and enables a range of main view layouts that can have either horizontal or vertical menus. These can be displayed statically or opened by clicking, and have many customizable elements. See [the Design System documentation](https://vaadin.com/docs/v24/components/app-layout.md) for a showcase of the features.

By default, the starter applications created with [Vaadin Start](https://start.vaadin.com) use `AppLayout` to create the main view.

## <a id="flow.application.main-view.main-view"></a>The Main View

A main view uses `AppLayout` by extending it and setting up the elements in the constructor. You need to set the content for the header and the drawer. You can have an application menu either horizontally in the header (navigation bar) or vertically in the drawer.

The following example shows how to create a main view with a vertical menu in the drawer, and a button to open and close it in the navigation bar:

`MainView.java`

```java
@CssImport("./styles/views/main/main-view.css")
@JsModule("./styles/shared-styles.js")
public class MainView extends AppLayout {
    private final Tabs menu;
    private H1 viewTitle;

    public MainView() {
        // Use the drawer for the menu
        setPrimarySection(Section.DRAWER);

        // Make the nav bar a header
        addToNavbar(true, createHeaderContent());

        // Put the menu in the drawer
        menu = createMenu();
        addToDrawer(createDrawerContent(menu));
    }
```

You can customize the styling by specifying the path to the CSS files with the `@CssImport` annotation. The style sheets should be placed inside the `frontend` folder in the project. In a similar way, you can include JavaScript code with the `JsModule` annotation. In the example, an included JavaScript file sets shared custom styles. See [Loading Resources](https://vaadin.com/docs/v24/flow/advanced/loading-resources.md) for more details on importing the CSS and JavaScript resources.

The main view itself doesn’t have a route, as it’s only a frame for the actual content views.

## <a id="flow.application.main-view.header"></a>Creating a Header

The navigation bar of `AppLayout` is a horizontal element that can contain any component, such as a header or a horizontal menu. Applications created with the project builder use it to produce a header containing a menu toggle, a view title, and a user image.

[Image: starter main view header]

A header with drawer (menu) toggle, view title, and a user avatar.

You can use a `DrawerToggle` component to toggle displaying the drawer.

The following example creates such a header, using the `viewTitle` member in the main view class:

`MainView.java`

```java
private Component createHeaderContent() {
    HorizontalLayout layout = new HorizontalLayout();

    // Configure styling for the header
    layout.setId("header");
    layout.getThemeList().set("dark", true);
    layout.setWidthFull();
    layout.setSpacing(false);
    layout.setAlignItems(FlexComponent.Alignment.CENTER);

    // Have the drawer toggle button on the left
    layout.add(new DrawerToggle());

    // Placeholder for the title of the current view.
    // The title will be set after navigation.
    viewTitle = new H1();
    layout.add(viewTitle);

    // A user icon
    layout.add(new Image("images/user.svg", "Avatar"));

    return layout;
}
```

## <a id="flow.application.main-view.menu"></a>Creating a Menu

A menu can be displayed either in the navigation bar or in the drawer. In an application created by the project builder, it’s displayed in the drawer, as described here.

`MainView.java`

```java
private Component createDrawerContent(Tabs menu) {
    VerticalLayout layout = new VerticalLayout();

    // Configure styling for the drawer
    layout.setSizeFull();
    layout.setPadding(false);
    layout.setSpacing(false);
    layout.getThemeList().set("spacing-s", true);
    layout.setAlignItems(FlexComponent.Alignment.STRETCH);

    // Have a drawer header with an application logo
    HorizontalLayout logoLayout = new HorizontalLayout();
    logoLayout.setId("logo");
    logoLayout.setAlignItems(FlexComponent.Alignment.CENTER);
    logoLayout.add(new Image("images/logo.png", "My Project logo"));
    logoLayout.add(new H1("My Project"));

    // Display the logo and the menu in the drawer
    layout.add(logoLayout, menu);
    return layout;
}
```

The actual menu is a vertical `Tabs` component. It’s filled from a list of `Tab` components. Each tab contains a `RouterLink` to the corresponding view.

`MainView.java`

```java
private Tabs createMenu() {
    final Tabs tabs = new Tabs();
    tabs.setOrientation(Tabs.Orientation.VERTICAL);
    tabs.addThemeVariants(TabsVariant.LUMO_MINIMAL);
    tabs.setId("tabs");
    tabs.add(createMenuItems());
    return tabs;
}

private Component[] createMenuItems() {
    return new Tab[] { createTab("Hello World", HelloWorldView.class),
            createTab("Card List", CardListView.class),
            createTab("About", AboutView.class) };
}

private static Tab createTab(String text,
        Class<? extends Component> navigationTarget) {
    final Tab tab = new Tab();
    tab.add(new RouterLink(text, navigationTarget));
    ComponentUtil.setData(tab, Class.class, navigationTarget);
    return tab;
}
```

## <a id="flow.application.main-view.navigation"></a>Handling Navigation

When the user navigates to a view, the tab for the view should be highlighted by setting it as selected. You can also set the view title in header.

You can do both these things by overriding `afterNavigation()` in `AppLayout`, as follows:

`MainView.java`

```java
@Override
protected void afterNavigation() {
    super.afterNavigation();

    // Select the tab corresponding to currently shown view
    getTabForComponent(getContent()).ifPresent(menu::setSelectedTab);

    // Set the view title in the header
    viewTitle.setText(getCurrentPageTitle());
}
```

<!-- vale Vaadin.Weasel = NO -->The selected tab should correspond to the displayed content (the view).<!-- vale Vaadin.Weasel = YES -->

You can retrieve it as follows:

`MainView.java`

```java
private Optional<Tab> getTabForComponent(Component component) {
    return menu.getChildren()
            .filter(tab -> ComponentUtil.getData(tab, Class.class)
                    .equals(component.getClass()))
            .findFirst().map(Tab.class::cast);
}
```

You can get the view title from the `PageTitle` annotation given to the view (see [Creating a View](#flow.application.main-view.view)).

`MainView.java`

```java
private String getCurrentPageTitle() {
    return getContent().getClass().getAnnotation(PageTitle.class).value();
}
```

The same title is automatically set as the page title in the browser, so you don’t need to handle that.

## <a id="flow.application.main-view.view"></a>Creating a View

Like any view, a view displayed in an `AppLayout` needs a route defined with the `@Route` annotation. The route needs to be linked to the main view by using the `layout` parameter to pass the class object of the main view.

`HelloWorldView.java`

```java
@Route(value = "hello", layout = MainView.class)
```

The main view itself didn’t have a route. To have an entry point to the main view, and often to the entire application, you need to define a default view. You do this using a route alias, as described in [Default View](#flow.application.main-view.view.default).

### <a id="page-title"></a>Page Title

You can set the page title shown in the browser window or tab using the `@PageTitle` annotation.

`HelloWorldView.java`

```java
@PageTitle("Hello World")
```

You can use the page title in a view header or breadcrumbs, as shown in [Handling Navigation](#flow.application.main-view.navigation).

### <a id="styling-a-view"></a>Styling a View

You can define custom styling for the view with the `@CssImport` annotation.

`HelloWorldView.java`

```java
@CssImport("./styles/views/helloworld/hello-world-view.css")
```

### <a id="flow.application.main-view.view.default"></a>Default View

Most applications need an entry point. You can define a view as the default view by defining the route of the main view with `@RouteAlias`. The `value` defining the route needs to be empty for the root route.

You also need to define the enclosing main view with the `layout` parameter, as for the earlier route.

`HelloWorldView.java`

```java
@RouteAlias(value = "", layout = MainView.class)
```

You could also have `/main` for the main view and then `/main/hello` for the sub-view.

### <a id="finishing-the-view"></a>Finishing the View

Otherwise a view displayed in `AppLayout` is like any other view or a composite component.

`HelloWorldView.java`

```java
public class HelloWorldView extends HorizontalLayout {
    private TextField name;
    private Button sayHello;

    public HelloWorldView() {
        setId("hello-world-view");
        name = new TextField("Your name");
        sayHello = new Button("Say hello");
        add(name, sayHello);
        setVerticalComponentAlignment(Alignment.END, name, sayHello);

        // Handle clicks
        sayHello.addClickListener(e -> {
            Notification.show("Hello " + name.getValue());
        });
    }

}
```

`7CAF8324-78D4-46E3-8825-FD4A6E45DB62`
