Navigation

Three pages in a NavigationStack. Buttons move between them with push() and pop_to_root().

What it shows

  • NavigationStack in route mode: routes={name: builder} and initial
  • nav.push("about") from a button action
  • nav.pop_to_root() from the last page
  • The back button is provided by the runtime

app_navigation

import nib


def connect_page():
    return nib.VStack(
        controls=[
            nib.Text("Connect", font=nib.Font.TITLE),
            nib.Text(
                "You reached the last page.",
                foreground_color=nib.Color.SECONDARY,
            ),
            nib.Spacer(),
            nib.Button("Back to root", action=lambda: nav.pop_to_root()),
        ],
        spacing=12,
        padding=20,
    )


def about_page():
    return nib.VStack(
        controls=[
            nib.Text("About", font=nib.Font.TITLE),
            nib.Text(
                "This is a navigation demo.",
                foreground_color=nib.Color.SECONDARY,
            ),
            nib.Spacer(),
            nib.Button("Go to Connect", action=lambda: nav.push("connect")),
        ],
        spacing=12,
        padding=20,
    )


def home_page():
    return nib.VStack(
        controls=[
            nib.Text("Home", font=nib.Font.TITLE),
            nib.Text(
                "Welcome to the app.",
                foreground_color=nib.Color.SECONDARY,
            ),
            nib.Spacer(),
            nib.Button("Go to About", action=lambda: nav.push("about")),
        ],
        spacing=12,
        padding=20,
    )


nav = nib.NavigationStack(
    routes={
        "home": home_page,
        "about": about_page,
        "connect": connect_page,
    },
    initial="home",
)


def main(app: nib.App):
    app.title = "Navigation"
    app.icon = nib.SFSymbol("list.bullet")
    app.width = 320
    app.height = 240

    app.build(nav)


nib.run(main)

Walkthrough

Routes

nav = nib.NavigationStack(
    routes={"home": home_page, "about": about_page, "connect": connect_page},
    initial="home",
)

Each value is a function that returns the page view. push() calls the function on every push, so a page can read current state when it is built. Only initial is built up front.

Pushing from a page

nib.Button("Go to About", action=lambda: nav.push("about"))

nav is a module-level variable, so the page functions can reach it. A push with a name that is not in routes does nothing.

Back

The back button and swipe back are handled by the runtime. It reports every route change to Python, so nav always knows the current page; pass on_navigate= to be told as well. pop_to_root() returns to initial from any depth.