App Layout
- Usage
- Styling
- Usage as Root Layout
- Content Area
- Navbar
- Drawer
- Scrolling Behavior
- Bottom Navbar on Small Touchscreens
- Best Practices
App Layout is a component for the root layout of a Vaadin application. It provides predefined areas for the navigation drawer, the header, and the view’s content.
Important
|
Scaled down examples
The examples on this page are scaled down so that their viewport-size-dependent behavior can be demonstrated.
Some examples also change their behavior based on your browser viewport size.
|
new tab
public class AppLayoutBasic extends AppLayout {
public AppLayoutBasic() {
DrawerToggle toggle = new DrawerToggle();
H1 title = new H1("MyApp");
title.getStyle().set("font-size", "var(--lumo-font-size-l)")
.set("margin", "0");
SideNav nav = getSideNav();
Scroller scroller = new Scroller(nav);
scroller.setClassName(LumoUtility.Padding.SMALL);
addToDrawer(scroller);
addToNavbar(toggle, title);
}
}
The layout consists of three sections:
-
Content area, a view content area;
-
Navbar, a horizontal navigation bar; and
-
Drawer, a collapsible navigation drawer-
An application’s main navigation blocks should be positioned in the navbar
or the drawer
or both, whereas views are rendered in the content area. App Layout is responsive and adjusts automatically to fit desktop, tablet, and mobile screen sizes.
Usage as Root Layout
App Layout is designed to be the application’s root layout, within which most or all views are rendered. It’s not intended to be nested inside other elements.
Flow
With Flow, the root layout can be defined using the @Layout
annotation, which tells the router to render all routes or views inside of it.
@Layout
public class MainLayout extends AppLayout implements RouterLayout {
}
Hilla
Files named @layout.tsx
define the root layout for the other views defined in the same directory or its subdirectories. A @layout.tsx
in the root of the views
directory acts as the default root layout for all views in the application. An <Outlet/>
element is used to tell the router where to render the contents of routes or views.
export default function MainLayout() {
return (
<AppLayout>
<Outlet />
</AppLayout>
);
}
See Hilla routing documentation for details.
Content Area
The content area is where individual views are rendered. The route layout mechanisms in Flow and Hilla can automatically render the contents of routes and views there, but it can be invoked manually:
public class MainLayout extends AppLayout {
public MainLayout() {
MyView view = new MyView();
setContent(view);
}
}
Navbar
The navbar
is a header above the content area. It can contain primary or secondary navigation elements, the application’s title, or view-specific content such as the title of the current view.
@Layout
public class MainLayout extends AppLayout implements RouterLayout {
public MainLayout() {
H1 title = new H1("My App");
addToNavbar(title);
}
}
Navbar Placement
The navbar
can be located on top, or to the side of the drawer
. When put it on top, the navbar
is typically used as an application header. Application headers contain, for example, the application’s name and branding, as well as actions that apply to the entire application (e.g., notifications, settings, etc.).
new tab
public class AppLayoutNavbarPlacement extends AppLayout {
public AppLayoutNavbarPlacement() {
DrawerToggle toggle = new DrawerToggle();
H1 title = new H1("MyApp");
title.getStyle().set("font-size", "var(--lumo-font-size-l)")
.set("margin", "0");
SideNav nav = getSideNav();
Scroller scroller = new Scroller(nav);
scroller.setClassName(LumoUtility.Padding.SMALL);
addToDrawer(scroller);
addToNavbar(toggle, title);
}
}
When placed to the side, the navbar
is often seen as a view header, containing the view’s title, as well as actions and secondary navigation that relate only to the current view.
new tab
public class AppLayoutNavbarPlacementSide extends AppLayout {
public AppLayoutNavbarPlacementSide() {
DrawerToggle toggle = new DrawerToggle();
H1 title = new H1("Dashboard");
title.getStyle().set("font-size", "var(--lumo-font-size-l)")
.set("margin", "0");
SideNav nav = getSideNav();
Scroller scroller = new Scroller(nav);
scroller.setClassName(LumoUtility.Padding.SMALL);
addToDrawer(scroller);
addToNavbar(toggle, title);
setPrimarySection(Section.DRAWER);
}
}
Drawer
The drawer
can switch between a fixed area next to the view’s content and an expandable panel, toggled via the drawer toggle. It typically contains the application’s primary navigation, such as a Side Navigation component.
@Layout
public class MainLayout extends AppLayout implements RouterLayout {
public MainLayout() {
SideNav nav = new SideNav();
addToDrawer(nav);
}
}
Scrolling Behavior
Depending on whether App Layout has a defined height, the way the content inside the layout scrolls can differ.
Auto Height
When the App Layout has an undefined or auto height set, which is the default, the <body>
element is the scrolling container for the content inside the layout.
new tab
public class AppLayoutHeightAuto extends AppLayout {
public AppLayoutHeightAuto() {
H1 title = new H1("MyApp");
title.getStyle().set("font-size", "var(--lumo-font-size-l)")
.set("margin", "var(--lumo-space-m)");
addToNavbar(title);
Grid<Person> grid = new Grid<>(Person.class, false);
grid.addColumn(Person::getFirstName).setHeader("First name");
grid.addColumn(Person::getLastName).setHeader("Last name");
grid.addColumn(Person::getEmail).setHeader("Email");
grid.addColumn(Person::getProfession).setHeader("Profession");
List<Person> people = DataService.getPeople(20);
grid.setItems(people);
grid.setAllRowsVisible(true);
setContent(grid);
}
}
The vertical scrollbar crosses the App Layout navbar
and the content flows under it, allowing for translucent visual styles. Mobile browsers collapse and expand their toolbars when the user scrolls down and up, respectively. On iOS, you can tap the status bar (i.e., where signal strength, battery, and clock are indicated) to scroll back to the top of the page or view.
This behavior isn’t compatible with vertically scrollable Grids, or other scrolling containers within the content area that’s height is 100%. To support those, define 100% height for the App Layout.
Full Height (100%)
To allow a nested component to take all of the available vertical space inside the App Layout, you need to set an explicit height for the layout, typically 100%. A common use case is to let a data grid fill the entire content area.
Note
|
Make sure all parent components and elements have 100% height. The full hierarchy of components from the App Layout to the <body> element need to have 100% height.
|
new tab
public class AppLayoutHeightFull extends AppLayout {
public AppLayoutHeightFull() {
H1 title = new H1("MyApp");
title.getStyle().set("font-size", "var(--lumo-font-size-l)")
.set("margin", "var(--lumo-space-m)");
addToNavbar(title);
Grid<Person> grid = new Grid<>(Person.class, false);
grid.addColumn(Person::getFirstName).setHeader("First name");
grid.addColumn(Person::getLastName).setHeader("Last name");
grid.addColumn(Person::getEmail).setHeader("Email");
grid.addColumn(