Skip to main content
Navigation controls help users move through different sections and views of your application. Flet provides both Material and Cupertino navigation controls to match your design system.

AppBar

Top application bar with title and actions

NavigationBar

Bottom navigation bar (Material)

NavigationRail

Side navigation panel

NavigationDrawer

Sliding drawer menu

Tabs

Tabbed content navigation

AppBar

The AppBar appears at the top of the screen and typically contains the app title, navigation icons, and action buttons.

Material AppBar

import flet as ft

def main(page: ft.Page):
    page.appbar = ft.AppBar(
        leading=ft.Icon(ft.Icons.MENU),
        leading_width=40,
        title=ft.Text("My Application"),
        center_title=True,
        bgcolor=ft.Colors.SURFACE_VARIANT,
        actions=[
            ft.IconButton(ft.Icons.SEARCH),
            ft.IconButton(ft.Icons.NOTIFICATIONS),
            ft.PopupMenuButton(
                items=[
                    ft.PopupMenuItem(text="Settings"),
                    ft.PopupMenuItem(text="About"),
                    ft.PopupMenuItem(text="Logout"),
                ]
            ),
        ],
    )
    
    page.add(ft.Text("App content here"))

ft.app(target=main)

Cupertino AppBar

import flet as ft
from flet import cupertino_icons

def main(page: ft.Page):
    page.appbar = ft.CupertinoAppBar(
        leading=ft.Icon(cupertino_icons.BACK),
        middle=ft.Text("My App"),
        trailing=ft.Icon(cupertino_icons.ELLIPSIS),
        bgcolor=ft.Colors.SURFACE_VARIANT,
    )
    
    page.add(ft.Text("App content here"))

ft.app(target=main)

Dynamic AppBar

import flet as ft

def main(page: ft.Page):
    def toggle_theme(e):
        page.theme_mode = (
            ft.ThemeMode.DARK
            if page.theme_mode == ft.ThemeMode.LIGHT
            else ft.ThemeMode.LIGHT
        )
        page.update()
    
    page.appbar = ft.AppBar(
        title=ft.Text("Dynamic AppBar"),
        actions=[
            ft.IconButton(
                ft.Icons.LIGHT_MODE,
                on_click=toggle_theme,
            ),
        ],
    )
    
    page.add(ft.Text("Toggle theme from AppBar"))

ft.app(target=main)
Bottom navigation bar for switching between primary destinations in the app.

Material NavigationBar

import flet as ft

def main(page: ft.Page):
    def on_navigation_change(e):
        selected_index = e.control.selected_index
        content_area.content = ft.Text(f"Showing view {selected_index}")
        page.update()
    
    content_area = ft.Container(
        content=ft.Text("Showing view 0"),
        expand=True,
    )
    
    page.navigation_bar = ft.NavigationBar(
        destinations=[
            ft.NavigationBarDestination(
                icon=ft.Icons.HOME,
                label="Home",
            ),
            ft.NavigationBarDestination(
                icon=ft.Icons.EXPLORE,
                label="Explore",
            ),
            ft.NavigationBarDestination(
                icon=ft.Icons.FAVORITE,
                label="Favorites",
            ),
            ft.NavigationBarDestination(
                icon=ft.Icons.PERSON,
                label="Profile",
            ),
        ],
        on_change=on_navigation_change,
    )
    
    page.add(content_area)

ft.app(target=main)

Cupertino NavigationBar

import flet as ft
from flet import cupertino_icons

def main(page: ft.Page):
    def on_tab_change(e):
        selected_index = e.control.selected_index
        content_area.content = ft.Text(f"Tab {selected_index}")
        page.update()
    
    content_area = ft.Container(
        content=ft.Text("Tab 0"),
        expand=True,
    )
    
    page.navigation_bar = ft.CupertinoNavigationBar(
        destinations=[
            ft.NavigationBarDestination(
                icon=cupertino_icons.HOME,
                label="Home",
            ),
            ft.NavigationBarDestination(
                icon=cupertino_icons.SEARCH,
                label="Search",
            ),
            ft.NavigationBarDestination(
                icon=cupertino_icons.HEART,
                label="Favorites",
            ),
            ft.NavigationBarDestination(
                icon=cupertino_icons.PERSON,
                label="Profile",
            ),
        ],
        on_change=on_tab_change,
    )
    
    page.add(content_area)

ft.app(target=main)
Side navigation for desktop and tablet layouts.
import flet as ft

def main(page: ft.Page):
    def on_rail_change(e):
        selected_index = e.control.selected_index
        content_area.content = ft.Text(
            f"Content for section {selected_index}",
            size=24,
        )
        page.update()
    
    rail = ft.NavigationRail(
        selected_index=0,
        label_type=ft.NavigationRailLabelType.ALL,
        min_width=100,
        min_extended_width=200,
        destinations=[
            ft.NavigationRailDestination(
                icon=ft.Icons.HOME_OUTLINED,
                selected_icon=ft.Icons.HOME,
                label="Home",
            ),
            ft.NavigationRailDestination(
                icon=ft.Icons.BOOKMARK_OUTLINED,
                selected_icon=ft.Icons.BOOKMARK,
                label="Bookmarks",
            ),
            ft.NavigationRailDestination(
                icon=ft.Icons.SETTINGS_OUTLINED,
                selected_icon=ft.Icons.SETTINGS,
                label="Settings",
            ),
        ],
        on_change=on_rail_change,
    )
    
    content_area = ft.Container(
        content=ft.Text("Content for section 0", size=24),
        expand=True,
        padding=20,
    )
    
    page.add(
        ft.Row(
            controls=[rail, ft.VerticalDivider(width=1), content_area],
            expand=True,
        )
    )

ft.app(target=main)
Sliding drawer menu, typically accessed from the AppBar.
import flet as ft

def main(page: ft.Page):
    def close_drawer(e):
        drawer.open = False
        page.update()
    
    def navigate(e, section):
        content_area.content = ft.Text(f"Viewing: {section}", size=24)
        drawer.open = False
        page.update()
    
    drawer = ft.NavigationDrawer(
        controls=[
            ft.Container(height=12),
            ft.NavigationDrawerDestination(
                icon=ft.Icons.HOME_OUTLINED,
                selected_icon=ft.Icons.HOME,
                label="Home",
            ),
            ft.Divider(thickness=2),
            ft.NavigationDrawerDestination(
                icon=ft.Icons.EMAIL_OUTLINED,
                selected_icon=ft.Icons.EMAIL,
                label="Messages",
            ),
            ft.NavigationDrawerDestination(
                icon=ft.Icons.CALENDAR_MONTH,
                selected_icon=ft.Icons.CALENDAR_MONTH,
                label="Calendar",
            ),
            ft.Divider(thickness=2),
            ft.NavigationDrawerDestination(
                icon=ft.Icons.SETTINGS_OUTLINED,
                selected_icon=ft.Icons.SETTINGS,
                label="Settings",
            ),
        ],
    )
    
    page.overlay.append(drawer)
    
    page.appbar = ft.AppBar(
        title=ft.Text("Navigation Drawer"),
        leading=ft.IconButton(
            ft.Icons.MENU,
            on_click=lambda e: (setattr(drawer, 'open', True), page.update()),
        ),
    )
    
    content_area = ft.Container(
        content=ft.Text("Select from drawer", size=24),
        expand=True,
    )
    
    page.add(content_area)

ft.app(target=main)

Tabs

Tabbed navigation for organizing related content.
import flet as ft

def main(page: ft.Page):
    tabs = ft.Tabs(
        selected_index=0,
        animation_duration=300,
        tabs=[
            ft.Tab(
                text="Overview",
                icon=ft.Icons.DASHBOARD,
                content=ft.Container(
                    content=ft.Text("Overview Tab Content"),
                    padding=20,
                ),
            ),
            ft.Tab(
                text="Analytics",
                icon=ft.Icons.BAR_CHART,
                content=ft.Container(
                    content=ft.Text("Analytics Tab Content"),
                    padding=20,
                ),
            ),
            ft.Tab(
                text="Settings",
                icon=ft.Icons.SETTINGS,
                content=ft.Container(
                    content=ft.Text("Settings Tab Content"),
                    padding=20,
                ),
            ),
        ],
        expand=1,
    )
    
    page.add(tabs)

ft.app(target=main)
Navigate between different pages/views using routing.

Route-based Navigation

import flet as ft

def main(page: ft.Page):
    def route_change(route):
        page.views.clear()
        
        # Home view
        page.views.append(
            ft.View(
                "/",
                [
                    ft.AppBar(title=ft.Text("Home")),
                    ft.ElevatedButton(
                        "Go to Details",
                        on_click=lambda _: page.go("/details"),
                    ),
                ],
            )
        )
        
        # Details view
        if page.route == "/details":
            page.views.append(
                ft.View(
                    "/details",
                    [
                        ft.AppBar(title=ft.Text("Details")),
                        ft.Text("This is the details page"),
                        ft.ElevatedButton(
                            "Back",
                            on_click=lambda _: page.go("/"),
                        ),
                    ],
                )
            )
        
        page.update()
    
    page.on_route_change = route_change
    page.go("/")

ft.app(target=main)

View Pop Handler

import flet as ft

def main(page: ft.Page):
    def view_pop(view):
        page.views.pop()
        top_view = page.views[-1]
        page.go(top_view.route)
    
    def route_change(route):
        page.views.clear()
        page.views.append(
            ft.View(
                "/",
                [
                    ft.AppBar(title=ft.Text("Home")),
                    ft.ElevatedButton(
                        "Settings",
                        on_click=lambda _: page.go("/settings"),
                    ),
                ],
            )
        )
        
        if page.route == "/settings":
            page.views.append(
                ft.View(
                    "/settings",
                    [
                        ft.AppBar(
                            title=ft.Text("Settings"),
                            automatically_imply_leading=True,
                        ),
                        ft.Text("Settings page"),
                    ],
                )
            )
        
        page.update()
    
    page.on_route_change = route_change
    page.on_view_pop = view_pop
    page.go("/")

ft.app(target=main)

Use Consistent Navigation Patterns

# Good: Consistent navigation across app
page.navigation_bar = ft.NavigationBar(
    destinations=[
        ft.NavigationBarDestination(icon=ft.Icons.HOME, label="Home"),
        ft.NavigationBarDestination(icon=ft.Icons.SEARCH, label="Search"),
        ft.NavigationBarDestination(icon=ft.Icons.PERSON, label="Profile"),
    ]
)

Highlight Active Sections

# Navigation automatically highlights selected items
rail = ft.NavigationRail(
    selected_index=0,  # First item selected
    destinations=[...],
)

Provide Clear Visual Feedback

def on_navigation_change(e):
    # Update content
    content_area.content = get_view(e.control.selected_index)
    # Provide feedback
    page.snack_bar = ft.SnackBar(ft.Text(f"Switched to view {e.control.selected_index}"))
    page.snack_bar.open = True
    page.update()

Next Steps

API Reference

Detailed documentation:

Build docs developers (and LLMs) love