Skip to content

Navigation

Typed stack, tab, and drawer navigators. Screens are components whose parameters are their route params, listed in module-level StackNavigator, TabNavigator, and DrawerNavigator values with Screen and Group. A NavigationContainer renders the root navigator and derives deep links from each screen's path. Screens navigate through the Navigation handle from use_navigation (nav.push(ItemScreen(id=42))) and set their options with use_screen_options. Code outside the tree navigates through a NavigationRef. Navigator chrome takes its colors from the app Theme.

Navigation: typed stack, tab, and drawer navigators.

Screens are ordinary components whose parameters are their route params; navigators are module-level values listing them:

import pythonnative as pn


@pn.component
def HomeScreen() -> pn.Node:
    nav = pn.use_navigation()
    return pn.Button("Open 42", on_press=lambda: nav.push(ItemScreen(id=42)))


@pn.component
def ItemScreen(id: int) -> pn.Node:
    pn.use_screen_options(title=f"Item {id}")
    return pn.Text(f"Item {id}")


Root = pn.StackNavigator(
    pn.Screen(HomeScreen, title="Home"),
    pn.Screen(ItemScreen, path="items/{id}"),
    screen_options=pn.ScreenOptions(header_large_title=True),
)
nav_ref = pn.NavigationRef()


@pn.component
def App() -> pn.Node:
    return pn.NavigationContainer(Root, link_prefixes=["myapp://"], ref=nav_ref)

nav.push(ItemScreen(id=42)) builds the destination with the screen component's own signature, so a missing or mistyped param is a type error. Public surface (all re-exported from pythonnative):

Stack, tab, and drawer navigators: immutable values rendered by one shared core.

A navigator is a module-level value listing its screens:

Root = pn.StackNavigator(
    pn.Screen(HomeScreen, title="Home"),
    pn.Screen(ItemScreen, path="items/{id}"),
    pn.Group(pn.Screen(ComposeScreen), presentation="modal"),
)

Calling a navigator (Root()) returns the element that renders it, so a navigator is a zero-argument component: pass it to NavigationContainer, list it as a screen of another navigator to nest it, or render it from a component. Navigators listed as screens are statically nested: deep links and navigate resolve screens inside them without rendering anything.

Each rendered navigator owns a NavigationState in use_state, wraps it in a NavigatorCore, and renders its screens under a Navigation provider. Only the rendering differs:

  • Stack: keeps every route mounted (hidden below the top one) so popping back restores the previous screen's state. When a native host is present, every stack, nested or not, renders a native ScreenStack (UINavigationController on iOS, fragments on Android) that draws the navigation bar and runs the platform transitions and back gesture. Without a host (tests, the browser preview's headless mode) the stack draws a themed header with a back button itself.
  • Tabs: keeps visited tabs alive and hidden (lazy mounts them on first focus; unmount_on_blur opts out; freeze_on_blur stops re-rendering them while hidden), and renders the native TabBar styled by tab_bar_style and the theme.
  • Drawer: like tabs, with a Python-drawn, themed slide-in menu instead of a tab bar.

Navigator chrome takes its colors from use_theme. Inactive screens read False from use_is_focused; focus and blur listeners fire as the active route changes.

Classes:

Name Description
Navigator

A navigator definition: its screens, initial screen, and shared options.

StackNavigator

A stack of screens with history, native transitions, and a native navigation bar.

TabNavigator

Sibling screens behind a native tab bar.

DrawerNavigator

Sibling screens behind a slide-in menu.

Functions:

Name Description
navigator_of

The navigator an element renders, when it was produced by calling a navigator.

use_screen_options

Set the calling screen's options from its render.

Navigator

Navigator(
    *screens: ScreenLike,
    name: Optional[str] = None,
    initial: Optional[ScreenTarget] = None,
    screen_options: Optional[ScreenOptions] = None
)

A navigator definition: its screens, initial screen, and shared options.

Create one with StackNavigator, TabNavigator, or DrawerNavigator. Navigators are immutable values, usually defined at module level. Calling one returns the element that renders it.

Attributes:

Name Type Description
kind NavigatorKind

"stack", "tab", or "drawer".

screens Tuple[Screen, ...]

The flattened Screens, in order.

name

Route name used when this navigator is a screen of another navigator.

screen_options

Options applied to every screen.

group_options Dict[str, Dict[str, Any]]

Options contributed by Groups, keyed by route name.

initial_name Dict[str, Dict[str, Any]]

Route name of the screen shown first.

initial_params Dict[str, Dict[str, Any]]

Params of the screen shown first.

Methods:

Name Description
path_to

The chain of screens from this navigator to the one rendering target, or None.

path_to

path_to(target: Any) -> Optional[List[Screen]]

The chain of screens from this navigator to the one rendering target, or None.

Direct screens win over screens of nested navigators; nested navigators are searched in order. The identical component anywhere in the tree wins over a Fast Refresh name match.

StackNavigator

StackNavigator(
    *screens: ScreenLike,
    name: Optional[str] = None,
    initial: Optional[ScreenTarget] = None,
    screen_options: Optional[ScreenOptions] = None
)

Bases: Navigator

A stack of screens with history, native transitions, and a native navigation bar.

Stacks use native screen containers at every nesting level on mobile: UINavigationController on iOS and fragments on Android draw the navigation bar and run the transitions. Without a native host (tests, headless rendering) the stack draws a themed header itself.

Parameters:

Name Type Description Default
*screens ScreenLike

Screens, Groups, bare components, or nested navigators.

()
name Optional[str]

Route name when this navigator is nested as a screen.

None
initial Optional[ScreenTarget]

The screen shown first: a component, or an element carrying its params (initial=ItemScreen(id=1)). Defaults to the first screen.

None
screen_options Optional[ScreenOptions]

ScreenOptions for every screen; groups and screens layer on top.

None
Example
Root = pn.StackNavigator(
    pn.Screen(HomeScreen, title="Home"),
    pn.Screen(ItemScreen, path="items/{id}"),
    pn.Group(pn.Screen(ComposeScreen), presentation="modal"),
    screen_options=pn.ScreenOptions(header_large_title=True),
)

TabNavigator

TabNavigator(
    *screens: ScreenLike,
    name: Optional[str] = None,
    initial: Optional[ScreenTarget] = None,
    screen_options: Optional[ScreenOptions] = None,
    tab_bar_style: Optional[TabBarStyle] = None
)

Bases: _KeepAliveNavigator

Sibling screens behind a native tab bar.

Tabs stay mounted once visited (hidden while inactive) so switching back restores scroll position and state. Use lazy=False on a screen to mount it eagerly, unmount_on_blur=True to tear it down when it loses focus, and freeze_on_blur=True to stop re-rendering it while hidden. tab_bar_visible=False hides the bar while that tab is focused.

Parameters:

Name Type Description Default
*screens ScreenLike

The tabs (see StackNavigator).

()
name Optional[str]

Route name when this navigator is nested as a screen.

None
initial Optional[ScreenTarget]

The tab selected first. Defaults to the first tab.

None
screen_options Optional[ScreenOptions]

Options for every tab.

None
tab_bar_style Optional[TabBarStyle]

A TabBarStyle; unset keys fall back to the theme.

None
Example
Tabs = pn.TabNavigator(
    pn.Screen(FeedScreen, title="Feed", tab_bar_icon="house"),
    pn.Screen(SettingsScreen, title="Settings", tab_bar_icon="settings"),
    name="Main",
)

DrawerNavigator

DrawerNavigator(
    *screens: ScreenLike,
    name: Optional[str] = None,
    initial: Optional[ScreenTarget] = None,
    screen_options: Optional[ScreenOptions] = None,
    drawer_width: float = _DRAWER_WIDTH
)

Bases: _KeepAliveNavigator

Sibling screens behind a slide-in menu.

The drawer is drawn in Python on every platform and styled by the theme. The handle returned by use_navigation inside a drawer screen is a DrawerNavigation with open_drawer(), close_drawer(), and toggle_drawer().

Parameters:

Name Type Description Default
*screens ScreenLike

The drawer's screens.

()
name Optional[str]

Route name when this navigator is nested as a screen.

None
initial Optional[ScreenTarget]

The screen shown first. Defaults to the first screen.

None
screen_options Optional[ScreenOptions]

Options for every screen.

None
drawer_width float

Width of the menu panel, in points.

_DRAWER_WIDTH

navigator_of

navigator_of(element: Element) -> Optional[Navigator]

The navigator an element renders, when it was produced by calling a navigator.

use_screen_options

use_screen_options(
    **options: Unpack[ScreenOptions],
) -> None

Set the calling screen's options from its render.

Options set here layer over the screen's static options and follow the screen's props and state, so dynamic titles and header buttons live next to the code that computes them:

@pn.component
def ItemScreen(id: int) -> pn.Node:
    item = use_item(id)
    pn.use_screen_options(
        title=item.title,
        header_right=pn.Button("Share", on_press=lambda: share(item)),
    )
    return ItemDetails(item)

The navigator re-renders only when the options actually change, and it doesn't re-render the screen in response.

Raises:

Type Description
RuntimeError

If the calling component isn't inside a navigator.

TypeError

For an unknown option key.

Container and deep linking

NavigationContainer: the root of a navigator tree.

The container renders the root navigator and wires it to the outside world: deep links derived from the navigators' screen paths, a caller-supplied initial state, on_state_change / on_ready callbacks, and a NavigationRef for navigating from outside the tree. Navigator chrome takes its colors from the app Theme. Every app with navigation renders exactly one container at the top.

Functions:

Name Description
NavigationContainer

Render navigator as the root of the app's navigation.

NavigationContainer

NavigationContainer(
    navigator: "Navigator",
    *,
    link_prefixes: Sequence[str] = (),
    initial_state: Optional[StateLike] = None,
    on_state_change: Optional[
        Callable[[NavigationState], None]
    ] = None,
    on_ready: Optional[Callable[[], None]] = None,
    ref: Optional[NavigationRef] = None
) -> Element

Render navigator as the root of the app's navigation.

Parameters:

Name Type Description Default
navigator 'Navigator' required
link_prefixes Sequence[str]

URL prefixes that open deep links ("myapp://", "https://example.com"). Paths come from each screen's path. The URL the app was launched with seeds the initial state; URLs that arrive later navigate. Empty disables deep linking.

()
initial_state Optional[StateLike]

Explicit initial state for the root navigator (a NavigationState or its to_dict() form). Takes precedence over the launch URL. State restored by a native host (a pushed native screen re-entering Python) takes precedence over both.

None
on_state_change Optional[Callable[[NavigationState], None]]

Called with the root navigator's state after every change. Persist state.to_dict() to restore later.

None
on_ready Optional[Callable[[], None]]

Called once the root navigator has mounted.

None
ref Optional[NavigationRef]

A NavigationRef; bound to the root navigator while the container is mounted.

None
Example
Root = pn.StackNavigator(pn.Screen(HomeScreen, title="Home"), pn.Screen(ItemScreen, path="items/{id}"))
nav_ref = pn.NavigationRef()


@pn.component
def App() -> pn.Node:
    return pn.NavigationContainer(Root, link_prefixes=["myapp://"], ref=nav_ref)

Deep links derived from the navigator tree.

Each Screen may declare a path with Python format placeholders for its params. A nested navigator's path prefixes the paths of its screens:

Tabs = pn.TabNavigator(
    pn.Screen(FeedScreen, path="feed"),
    pn.Screen(ProfileScreen, path="users/{user}"),
    name="Main",
)
Root = pn.StackNavigator(
    pn.Screen(Tabs),
    pn.Screen(ItemScreen, path="items/{id}"),
)

pn.NavigationContainer(Root, link_prefixes=["myapp://", "https://example.com"])

myapp://items/42?tab=reviews opens ItemScreen(id=42, tab="reviews"): path placeholders and query parameters become the screen component's arguments, converted with its annotations (str, int, float, bool, Enum subclasses, Literal values, and Optional of those). Query parameters the component doesn't accept are ignored. A URL whose values don't convert, or that lacks a required parameter, matches nothing.

Path placeholders arrive percent-decoded, once, before conversion, so users/Ada%20Lovelace gives user="Ada Lovelace" and an encoded %2F stays inside one value instead of splitting the path. A + in a path is a literal plus, unlike in the query string, where it means a space. Bytes that don't decode as UTF-8 are left as they arrived. Literal segments are matched exactly as written.

Classes:

Name Description
LinkTable

URL <-> navigation state mapping built from a navigator tree.

LinkTable

LinkTable(navigator: 'Navigator', prefixes: Sequence[str])

URL <-> navigation state mapping built from a navigator tree.

Path placeholders are percent-decoded once, where the segment is captured and before conversion; + in a path stays a literal plus, and undecodable bytes are left as-is. Literal segments match exactly as the paths declare them, and query values are decoded by parse_qsl alone.

Parameters:

Name Type Description Default
navigator 'Navigator'

The root navigator.

required
prefixes Sequence[str]

URL prefixes the app answers to (schemes such as "myapp://" or web origins). Matching is case-insensitive and a trailing slash is optional.

required

Raises:

Type Description
ValueError

If a path names a placeholder its component doesn't accept, or a segment mixes literal text with a placeholder.

Methods:

Name Description
strip_prefix

Return the path and query of url if it matches a prefix (or is relative), else None.

state_from_url

Translate url into a (possibly nested) state, or None when nothing matches.

url_from_state

Build a URL for the focused leaf of state (None if no screen on the way has a path).

strip_prefix

strip_prefix(url: str) -> Optional[str]

Return the path and query of url if it matches a prefix (or is relative), else None.

state_from_url

state_from_url(url: str) -> Optional[NavigationState]

Translate url into a (possibly nested) state, or None when nothing matches.

url_from_state

url_from_state(state: NavigationState) -> Optional[str]

Build a URL for the focused leaf of state (None if no screen on the way has a path).

NavigationRef: navigate from outside the component tree.

nav_ref = pn.NavigationRef()


@pn.component
def App() -> pn.Node:
    return pn.NavigationContainer(Root, ref=nav_ref)


def on_push_notification(payload: dict[str, str]) -> None:
    if nav_ref.is_ready():
        nav_ref.navigate(ThreadScreen(id=payload["thread"]))

The container binds the root navigator's handle to ref.current when it mounts and clears it on unmount. Every proxied method raises RuntimeError while no container is mounted, so call is_ready() first from code that may run before the UI is up.

Classes:

Name Description
NavigationRef

Handle to the root navigator, usable outside components.

NavigationRef

NavigationRef()

Handle to the root navigator, usable outside components.

Create one at module level and bind it with NavigationContainer(ref=...), so push-notification handlers, deep-link code, and services can navigate without a component in scope. The proxied methods mirror Navigation and act from the root navigator, which reaches every statically nested screen.

Attributes:

Name Type Description
current Optional[Navigation]

The root navigator's Navigation handle, or None while no container is mounted.

Methods:

Name Description
is_ready

Whether a NavigationContainer has bound this ref.

navigate

Go to target (see Navigation.navigate).

push

Push target (see Navigation.push).

replace

Replace the active screen with target (see Navigation.replace).

pop

Pop count screens; returns whether anything happened.

go_back

Pop one screen; returns whether anything happened.

pop_to

Pop back to target (see Navigation.pop_to).

pop_to_top

Pop every screen above the first one.

reset

Replace the root navigator's history (see Navigation.reset).

get_state

The root navigator's current state.

is_ready

is_ready() -> bool

Whether a NavigationContainer has bound this ref.

navigate

navigate(target: Element) -> None

Go to target (see Navigation.navigate).

push

push(target: Element) -> None

Push target (see Navigation.push).

replace

replace(target: Element) -> None

Replace the active screen with target (see Navigation.replace).

pop

pop(count: int = 1) -> bool

Pop count screens; returns whether anything happened.

go_back

go_back() -> bool

Pop one screen; returns whether anything happened.

pop_to

pop_to(target: ScreenTarget) -> None

Pop back to target (see Navigation.pop_to).

pop_to_top

pop_to_top() -> None

Pop every screen above the first one.

reset

reset(
    *targets: Element, index: Optional[int] = None
) -> None

Replace the root navigator's history (see Navigation.reset).

get_state

get_state() -> NavigationState

The root navigator's current state.

Hooks

Hooks for reading navigation state from inside a screen.

Functions:

Name Description
use_navigation

Return the Navigation handle for the current screen.

use_route

Return the current screen's Route.

use_is_focused

Whether the calling component is on the focused screen.

use_focus_effect

Run effect while the screen is focused; its cleanup runs on blur.

use_navigation

use_navigation() -> Navigation

Return the Navigation handle for the current screen.

Raises:

Type Description
RuntimeError

When no navigator encloses the calling component.

Example
@pn.component
def HomeScreen():
    nav = pn.use_navigation()
    return pn.Button("Open", on_press=lambda: nav.push(ItemScreen(id=42)))

use_route

use_route() -> Route

Return the current screen's Route.

A screen receives its params as arguments, so most screens never need this. Use it for the route's identity: its key (unique per visit) or its name.

Outside any navigator a placeholder route named "__root__" with empty params is returned, so components can be rendered standalone (previews, tests) without special-casing.

use_is_focused

use_is_focused() -> bool

Whether the calling component is on the focused screen.

Combines the native host's lifecycle (a screen covered by a pushed native screen is not focused) with the in-tree state of declarative navigators (inactive tabs are not focused).

use_focus_effect

use_focus_effect(
    effect: Callable[[], Any],
    deps: Optional[Sequence[Any]] = None,
) -> None

Run effect while the screen is focused; its cleanup runs on blur.

Like use_effect, but the callback runs only when use_is_focused is True and re-runs each time the screen regains focus.

Parameters:

Name Type Description Default
effect Callable[[], Any]

Zero-arg callable, optionally returning a cleanup.

required
deps Optional[Sequence[Any]]

Extra dependencies (None re-runs on every focused render).

None
Example
@pn.component
def Feed():
    pn.use_focus_effect(lambda: refresh(), [])
    ...

The Navigation handle

The Navigation handle and the navigator core behind it.

Every screen rendered by a navigator receives a Navigation object through use_navigation. The handle is scoped to the screen's route (so add_listener("focus", ...) fires for that screen) and forwards every action to the NavigatorCore that owns the navigator's state.

Destinations are screen components, called with their params: nav.push(ItemScreen(id=42)). The core looks the component up in its own navigator, then in navigators statically nested in it, then in each ancestor, so nav.navigate(ProfileScreen(user="ada")) reaches a screen inside a sibling tab without naming the tab.

Every route removal (pop, pop_to, navigate back to an existing route, replace, and reset) first emits before_remove for each route that would leave the state; a listener that calls prevent_default() cancels the whole operation. On a native host the stack navigator re-synchronizes the native screen stack after a vetoed back gesture.

Classes:

Name Description
HostNavigator

What a root stack needs from the native screen host.

NavigationEvent

Payload delivered to add_listener callbacks.

NavigatorCore

State machine shared by every Navigation handle a navigator hands out.

Navigation

Imperative navigation API for one screen.

TabNavigation

Handle for screens inside a tab navigator (adds jump_to).

DrawerNavigation

Handle for screens inside a drawer navigator (adds drawer controls).

Functions:

Name Description
provide

Return a provider element for context carrying value over children.

split_target

Split a navigation target into (component_or_navigator, params).

Attributes:

Name Type Description
NavigationContext Context[Optional[Navigation]]

Provides the Navigation handle for the current screen.

FocusContext Context[bool]

Whether the current subtree is the focused screen (see use_is_focused).

CONTAINER_ROUTE_KEY module-attribute

CONTAINER_ROUTE_KEY = '__container__'

Route key of the navigator-level handle bound to a NavigationRef; it always resolves to the active route.

NavigationContext module-attribute

NavigationContext: Context[Optional[Navigation]] = (
    create_context(None, name="Navigation")
)

Provides the Navigation handle for the current screen.

FocusContext module-attribute

FocusContext: Context[bool] = create_context(
    True, name="Focus"
)

Whether the current subtree is the focused screen (see use_is_focused).

HostNavigator

Bases: Protocol

What a root stack needs from the native screen host.

Hosts and FakeHost publish application focus and cached navigation state. Screen presentation belongs to the logical tree and its native containers.

Methods:

Name Description
initial_navigation_state

The serialized state this screen was pushed with, if any.

set_screen_options

Apply header options (title and friends) to the native bar.

add_focus_listener

Subscribe to the host covering / revealing this screen; returns an unsubscribe.

initial_navigation_state

initial_navigation_state() -> Optional[Dict[str, Any]]

The serialized state this screen was pushed with, if any.

set_screen_options

set_screen_options(options: Dict[str, Any]) -> None

Apply header options (title and friends) to the native bar.

add_focus_listener

add_focus_listener(
    callback: Callable[[bool], None],
) -> Callable[[], None]

Subscribe to the host covering / revealing this screen; returns an unsubscribe.

NavigationEvent

NavigationEvent(
    type_: str,
    route: Route,
    data: Optional[Mapping[str, Any]] = None,
)

Payload delivered to add_listener callbacks.

Attributes:

Name Type Description
type

"focus", "blur", "before_remove", or "state".

route

The route the event concerns.

data Dict[str, Any]

Extra event data (before_remove carries the action that caused it).

Methods:

Name Description
prevent_default

Cancel the action (only meaningful for before_remove).

prevent_default

prevent_default() -> None

Cancel the action (only meaningful for before_remove).

NavigatorCore

NavigatorCore(
    navigator: "Navigator",
    state: NavigationState,
    set_state: Callable[[Any], None],
    parent: Optional["Navigation"] = None,
    host: Optional[HostNavigator] = None,
    request_render: Optional[Callable[[], None]] = None,
)

State machine shared by every Navigation handle a navigator hands out.

Owned by the navigator component: created once per mount, updated every render with the latest navigator value, state, and setter (see update). Internally routes are addressed by name, which is what serialized state and native screens carry; the public API addresses screens by component.

Methods:

Name Description
update

Sync the core with the owning component's latest render.

handle_for

The (cached) handle scoped to route.

route_by_key

Return the route with key, falling back to the active route once it has left the state.

container_handle

The navigator-level handle bound to a NavigationRef; its route is always the active route.

body_for

The screen element for route, reused while its params and component are unchanged.

options_for

Effective options: navigator, then groups, then the screen, then runtime options.

resolve

Locate target from this navigator and split off its params.

act

Run action (navigate, push, replace, pop_to, jump_to) toward target.

add_listener

Subscribe listener to event for the route with route_key; returns an unsubscribe callable.

has_listeners

Whether any listener is registered for event on the route with route_key.

emit

Deliver event to the listeners registered for route and return the event.

navigate

Go to the route name: stacks pop back to it or push it; tabs and drawers jump to it.

push

Push a new route name (stacks); tabs and drawers fall back to navigate.

replace

Swap the active route for a fresh name (stacks); tabs and drawers fall back to navigate.

pop

Pop count screens. Returns whether anything was popped here or by a parent.

pop_to_top

Pop every screen above the first one (no-op when only one screen is present).

pop_to

Pop back to the most recent name, merging params into it.

reset

Replace the whole history with routes, activating index (the last route by default).

set_params

Merge params into the route with route_key; its screen re-renders with the new arguments.

set_options

Merge runtime options for the route with route_key; re-render only if something changed.

set_drawer_open

Open or close the drawer (no-op unless a drawer navigator owns this core).

Attributes:

Name Type Description
is_native_root bool

Whether this core drives a native screen stack through the host.

is_native_root property

is_native_root: bool

Whether this core drives a native screen stack through the host.

update

update(
    navigator: "Navigator",
    state: NavigationState,
    set_state: Callable[[Any], None],
    parent: Optional["Navigation"],
    host: Optional[HostNavigator],
) -> None

Sync the core with the owning component's latest render.

Handles, cached screen bodies, and runtime options for routes no longer in state are dropped.

handle_for

handle_for(route: Route) -> 'Navigation'

The (cached) handle scoped to route.

route_by_key

route_by_key(key: str) -> Route

Return the route with key, falling back to the active route once it has left the state.

container_handle

container_handle() -> 'Navigation'

The navigator-level handle bound to a NavigationRef; its route is always the active route.

body_for

body_for(route: Route) -> Element

The screen element for route, reused while its params and component are unchanged.

Returning the identical element lets the reconciler skip the screen when only the navigator re-renders (an option change, a focus change, another route's update).

options_for

options_for(route: Route) -> Dict[str, Any]

Effective options: navigator, then groups, then the screen, then runtime options.

resolve

resolve(target: Any) -> Tuple[List[Screen], Dict[str, Any]]

Locate target from this navigator and split off its params.

Returns the chain of screens from this navigator down to the target (one entry when the target is a direct screen), and the params for the target screen.

Raises:

Type Description
LookupError

If neither this navigator nor any navigator nested in it statically renders the target.

TypeError

If target isn't a screen element, component, or navigator.

act

act(action: str, target: Any) -> None

Run action (navigate, push, replace, pop_to, jump_to) toward target.

A target this navigator can't reach is handed to the parent navigator; at the root an unknown target raises ValueError.

add_listener

add_listener(
    route_key: str, event: str, listener: Listener
) -> Callable[[], None]

Subscribe listener to event for the route with route_key; returns an unsubscribe callable.

has_listeners

has_listeners(route_key: str, event: str) -> bool

Whether any listener is registered for event on the route with route_key.

emit

emit(
    route: Route,
    event: str,
    data: Optional[Mapping[str, Any]] = None,
) -> NavigationEvent

Deliver event to the listeners registered for route and return the event.

Check default_prevented on the result to see whether a before_remove listener cancelled the action.

navigate

navigate(
    name: str,
    params: Mapping[str, Any],
    nested: Optional[NavigationState] = None,
) -> None

Go to the route name: stacks pop back to it or push it; tabs and drawers jump to it.

push

push(
    name: str,
    params: Mapping[str, Any],
    nested: Optional[NavigationState] = None,
) -> None

Push a new route name (stacks); tabs and drawers fall back to navigate.

replace

replace(
    name: str,
    params: Mapping[str, Any],
    nested: Optional[NavigationState] = None,
) -> None

Swap the active route for a fresh name (stacks); tabs and drawers fall back to navigate.

pop

pop(count: int = 1, *, source: str = 'pop') -> bool

Pop count screens. Returns whether anything was popped here or by a parent.

A before_remove veto counts as handled (True) while leaving the state unchanged.

pop_to_top

pop_to_top() -> None

Pop every screen above the first one (no-op when only one screen is present).

pop_to

pop_to(
    name: str,
    params: Mapping[str, Any],
    nested: Optional[NavigationState] = None,
) -> None

Pop back to the most recent name, merging params into it.

When name isn't in the history the active screen is replaced by a fresh name instead (React Navigation's popTo semantics). Non-stack navigators fall back to navigate.

reset

reset(
    routes: Sequence[Route], index: Optional[int] = None
) -> None

Replace the whole history with routes, activating index (the last route by default).

before_remove fires for every current route whose key isn't in routes; a veto leaves the state untouched.

set_params

set_params(
    route_key: str, params: Mapping[str, Any]
) -> None

Merge params into the route with route_key; its screen re-renders with the new arguments.

set_options

set_options(
    route_key: str, options: Mapping[str, Any]
) -> None

Merge runtime options for the route with route_key; re-render only if something changed.

Raises:

Type Description
TypeError

For an unknown option key.

ValueError

For an unknown presentation or animation value.

set_drawer_open

set_drawer_open(open_: bool) -> None

Open or close the drawer (no-op unless a drawer navigator owns this core).

Navigation

Navigation(core: NavigatorCore, route_key: str)

Imperative navigation API for one screen.

Obtained with use_navigation. Destinations are screen components called with their params, so the type checker verifies them:

nav.push(ItemScreen(id=42))
nav.navigate(SettingsScreen())
nav.replace(LoginScreen())
nav.pop()
nav.pop_to(HomeScreen)
nav.pop_to_top()
nav.set_params(id=44)
nav.set_options(title="Edited")
unsubscribe = nav.add_listener("focus", lambda e: print("focused", e.route.name))

A destination this navigator doesn't know is looked up in the navigators nested in it and then in each enclosing navigator, so screens can navigate anywhere in the tree without knowing its shape.

Methods:

Name Description
get_state

The owning navigator's current state.

get_parent

The handle of the enclosing navigator, or None at the top.

get_options

Effective options for this handle's route (static merged with runtime options).

can_go_back

Whether pop() would do anything (here or in a parent).

is_focused

Whether this handle's route is the navigator's active route.

navigate

Go to target: pop back to it if it's in the stack (merging params), otherwise push it.

push

Push a new instance of target (stacks; tabs and drawers switch to it).

replace

Replace the current screen with target.

pop

Pop count screens off the nearest stack; returns whether anything happened.

go_back

Pop one screen off the nearest stack; returns whether anything happened.

pop_to_top

Pop every screen above the first one.

pop_to

Pop back to the most recent target (a component, or an element whose params are merged in).

reset

Replace the whole history of this navigator with targets (index active, the last by default).

set_params

Merge params into this screen's arguments; the screen re-renders with them.

set_options

Set ScreenOptions for this screen at runtime.

add_listener

Subscribe to "focus", "blur", "before_remove", or "state" for this route.

Attributes:

Name Type Description
route Route

The route this handle belongs to.

kind NavigatorKind

"stack", "tab", or "drawer".

route property

route: Route

The route this handle belongs to.

kind property

kind: NavigatorKind

"stack", "tab", or "drawer".

get_state

get_state() -> NavigationState

The owning navigator's current state.

get_parent

get_parent() -> Optional['Navigation']

The handle of the enclosing navigator, or None at the top.

get_options

get_options() -> Dict[str, Any]

Effective options for this handle's route (static merged with runtime options).

can_go_back

can_go_back() -> bool

Whether pop() would do anything (here or in a parent).

is_focused

is_focused() -> bool

Whether this handle's route is the navigator's active route.

navigate

navigate(target: Element) -> None

Go to target: pop back to it if it's in the stack (merging params), otherwise push it.

Tab and drawer navigators switch to it. A target inside a nested navigator opens that navigator on the target.

push

push(target: Element) -> None

Push a new instance of target (stacks; tabs and drawers switch to it).

replace

replace(target: Element) -> None

Replace the current screen with target.

pop

pop(count: int = 1) -> bool

Pop count screens off the nearest stack; returns whether anything happened.

go_back

go_back() -> bool

Pop one screen off the nearest stack; returns whether anything happened.

pop_to_top

pop_to_top() -> None

Pop every screen above the first one.

pop_to

pop_to(target: ScreenTarget) -> None

Pop back to the most recent target (a component, or an element whose params are merged in).

If target isn't in the history, the active screen is replaced by it. before_remove fires for every screen popped.

reset

reset(
    *targets: Element, index: Optional[int] = None
) -> None

Replace the whole history of this navigator with targets (index active, the last by default).

nav.reset(HomeScreen(), ItemScreen(id=1))

set_params

set_params(**params: Any) -> None

Merge params into this screen's arguments; the screen re-renders with them.

set_options

set_options(**options: Unpack[ScreenOptions]) -> None

Set ScreenOptions for this screen at runtime.

Prefer use_screen_options from the screen's own render; call this to change another screen's options (nav.get_parent().set_options(...)).

add_listener

add_listener(
    event: EventName, listener: Listener
) -> Callable[[], None]

Subscribe to "focus", "blur", "before_remove", or "state" for this route.

Returns an unsubscribe callable. before_remove fires for every removal (pop, pop_to, navigate back to an existing route, replace, reset, and the system back gesture) and its data["action"] names the cause. Listeners may call event.prevent_default() to keep the screen (useful for unsaved-changes prompts); after a vetoed native back the stack restores the native screens to match. Set gesture_enabled=False (iOS only) to disable the swipe gesture outright instead of animating it out and back.

TabNavigation

TabNavigation(core: NavigatorCore, route_key: str)

Bases: Navigation

Handle for screens inside a tab navigator (adds jump_to).

Methods:

Name Description
jump_to

Switch to the tab rendering target (an element's params are merged into the tab's).

jump_to

jump_to(target: ScreenTarget) -> None

Switch to the tab rendering target (an element's params are merged into the tab's).

DrawerNavigation

DrawerNavigation(core: NavigatorCore, route_key: str)

Bases: Navigation

Handle for screens inside a drawer navigator (adds drawer controls).

Methods:

Name Description
jump_to

Switch to the drawer screen rendering target and close the drawer.

open_drawer

Slide the drawer menu open.

close_drawer

Close the drawer menu.

toggle_drawer

Open the drawer menu if it's closed, otherwise close it.

is_drawer_open

Return whether the drawer menu is currently open.

jump_to

jump_to(target: ScreenTarget) -> None

Switch to the drawer screen rendering target and close the drawer.

open_drawer

open_drawer() -> None

Slide the drawer menu open.

close_drawer

close_drawer() -> None

Close the drawer menu.

toggle_drawer

toggle_drawer() -> None

Open the drawer menu if it's closed, otherwise close it.

is_drawer_open

is_drawer_open() -> bool

Return whether the drawer menu is currently open.

provide

provide(
    context: Context[Any],
    value: Any,
    *children: Node,
    key: Optional[str] = None
) -> Element

Return a provider element for context carrying value over children.

Equivalent to context.Provider(...); navigation builds the element directly so it doesn't depend on the Provider call signature.

split_target

split_target(target: Any) -> Tuple[Any, Dict[str, Any]]

Split a navigation target into (component_or_navigator, params).

An element built by calling a screen component carries the params as its props; a navigator's element carries none. A bare component or navigator means "no params".

Raises:

Type Description
TypeError

If target isn't a screen element, component, or navigator.

Screens and options

Screen definitions, screen groups, and the typed options a screen accepts.

Classes:

Name Description
ScreenOptions

Per-screen options accepted by Screen(...), Group(...), screen_options=, and set_options(...).

TabBarStyle

Appearance of a tab navigator's bar, passed as TabNavigator(..., tab_bar_style=...).

Screen

One screen in a navigator: the component it renders, its route name, deep-link path, and options.

Group

Screens that share a layer of options.

Functions:

Name Description
validate_screen_options

Reject unknown option keys and presentation / animation values outside their Literal.

find_screen

The screen rendering target: an identity match wins over a Fast Refresh name match.

flatten_screens

Expand groups into (screens, group_options_by_name).

Attributes:

Name Type Description
Presentation

How a stack screen is presented (see ScreenOptions.presentation).

Animation

Transition used when a stack screen is pushed (see ScreenOptions.animation).

PYTHON_ONLY_OPTIONS

Options consumed by Python that never travel to the native Screen element.

ScreenLike

An entry in a navigator's screen list.

ScreenTarget

A navigation destination: an element carrying params, or a component or navigator with none.

Presentation module-attribute

Presentation = Literal[
    "card",
    "modal",
    "full_screen_modal",
    "form_sheet",
    "transparent_modal",
]

How a stack screen is presented (see ScreenOptions.presentation).

Animation module-attribute

Animation = Literal[
    "default",
    "none",
    "fade",
    "slide_from_right",
    "slide_from_bottom",
]

Transition used when a stack screen is pushed (see ScreenOptions.animation).

PYTHON_ONLY_OPTIONS module-attribute

PYTHON_ONLY_OPTIONS = frozenset(
    {
        "header_left",
        "header_right",
        "tab_bar_icon",
        "tab_bar_visible",
        "freeze_on_blur",
    }
)

Options consumed by Python that never travel to the native Screen element.

ScreenComponent module-attribute

ScreenComponent = Union[Component[...], 'Navigator']

What a screen renders: a @component whose parameters are the route params, or a nested navigator.

ScreenLike module-attribute

ScreenLike = Union[
    Screen, Group, Component[...], "Navigator"
]

An entry in a navigator's screen list.

ScreenTarget module-attribute

ScreenTarget = Union[Element, Component[...], 'Navigator']

A navigation destination: an element carrying params, or a component or navigator with none.

ScreenOptions

Bases: TypedDict

Per-screen options accepted by Screen(...), Group(...), screen_options=, and set_options(...).

All keys are optional. Navigators ignore keys they don't use; the native host applies the header keys it can (see the platform notes on each key). Options layer in this order, later entries winning: the navigator's screen_options, each enclosing Group, the Screen itself, then options set at runtime with use_screen_options or nav.set_options(...).

Attributes:

Name Type Description
title str

Screen title. Stack navigators show it in the native navigation bar; tab and drawer navigators use it as the item label. Defaults to the route name.

header_shown bool

Whether the navigation bar is visible for this screen (default True).

header_large_title bool

Use a large title that collapses on scroll. iOS renders the system large title; Android renders an expanded toolbar with a larger title.

header_back_title str

iOS only: label of the back button shown on the next screen when it navigates back to this one. Android shows a bare back arrow and ignores this key.

header_back_visible bool

Whether the back button is shown (default True).

header_left Optional[Element]

Element rendered at the leading edge of the navigation bar.

header_right Optional[Element]

Element rendered at the trailing edge of the navigation bar.

header_tint_color str

Color of the bar's buttons and back chevron. Defaults to the theme's colors.primary.

header_style Dict[str, Any]

Style dict for the bar itself; background_color is honored on every platform that draws a bar and defaults to the theme's colors.surface.

header_title_style Dict[str, Any]

Style dict for the title label (color, font_size, bold). color defaults to the theme's colors.text.

presentation Presentation

"card" (default) pushes onto the stack. The modal styles present the screen over the stack: on iOS "modal" is a page sheet, "full_screen_modal" covers the screen, "form_sheet" is a centered form sheet, and "transparent_modal" is presented over the current context with a transparent background. Android presents every modal style as a full-screen screen with a slide-from-bottom transition, which is what React Navigation's native stack does there.

gesture_enabled bool

iOS only: whether the interactive swipe-back gesture can pop this screen (default True). Android's system back is always available.

animation Animation

Transition used when the screen is pushed: "default", "none", "fade", "slide_from_right", or "slide_from_bottom". Honored on iOS and Android.

tab_bar_icon Union[IconName, Asset]

Icon for the tab item: a bundled icon name from pythonnative.icons ("house", "settings") drawn as a vector on every platform, or a pn.asset pointing at a PNG that's drawn as a template image.

tab_bar_badge Union[str, int]

Badge text or count shown on the tab item.

tab_bar_label str

Label used for the tab item when it should differ from title.

tab_bar_visible bool

Tab navigators only: whether the tab bar is shown while this tab is focused (default True). Set it to False on a tab whose nested stack pushes detail screens, or toggle it at runtime with nav.get_parent().set_options(tab_bar_visible=False).

lazy bool

Tab and drawer navigators only: mount the screen the first time it's focused (default True) instead of at navigator mount.

unmount_on_blur bool

Tab and drawer navigators only: unmount the screen when it loses focus instead of keeping it alive hidden (default False).

freeze_on_blur bool

Tab and drawer navigators only: while the screen is unfocused, hold back new params (from set_params or a jump_to element) until it's focused again (default False). Navigators already skip unfocused screens whose params didn't change, and the screen's own state updates still apply.

TabBarStyle

Bases: TypedDict

Appearance of a tab navigator's bar, passed as TabNavigator(..., tab_bar_style=...).

Every key is optional; unset keys fall back to the theme (active_tint_color to colors.primary, background_color to colors.surface) or to the platform default.

Attributes:

Name Type Description
background_color str

Bar background.

active_tint_color str

Tint of the selected item's icon and label.

inactive_tint_color str

Tint of unselected items.

translucent bool

iOS: whether the bar blurs the content behind it. Ignored on Android.

show_labels bool

Whether item labels are shown next to icons (default True).

Screen

Screen(
    component: ScreenComponent,
    *,
    name: Optional[str] = None,
    path: Optional[str] = None,
    **options: Unpack[ScreenOptions]
)

One screen in a navigator: the component it renders, its route name, deep-link path, and options.

A screen's component receives its route params as ordinary arguments, so the component's signature is the screen's params type:

@pn.component
def ItemScreen(id: int, tab: str = "details") -> pn.Node: ...

Root = pn.StackNavigator(pn.Screen(ItemScreen, title="Item", path="items/{id}"))
nav.push(ItemScreen(id=42))

A bare component or navigator listed in a navigator is shorthand for Screen(component).

Parameters:

Name Type Description Default
component ScreenComponent

The @component to render, or a nested Navigator.

required
name Optional[str]

Route name, used in serialized state and diagnostics. Defaults to the component's name or the navigator's name.

None
path Optional[str]

Deep-link path relative to the enclosing navigator's path, with Python format placeholders for params ("items/{id}"). Params are converted with the component's annotations. Nested navigators use path as a prefix for their screens.

None
**options Unpack[ScreenOptions]

Static ScreenOptions.

{}

Raises:

Type Description
TypeError

If component isn't a component or navigator, or an option key is unknown.

ValueError

If no route name can be derived.

Methods:

Name Description
required_params

Parameters the screen's component needs a value for.

render

Build the screen's element for a route carrying params.

matches

Whether target (a component or navigator) is what this screen renders.

Attributes:

Name Type Description
navigator Optional['Navigator']

The nested navigator this screen renders, or None for a component screen.

navigator property

navigator: Optional['Navigator']

The nested navigator this screen renders, or None for a component screen.

required_params

required_params() -> list[str]

Parameters the screen's component needs a value for.

render

render(params: Mapping[str, Any]) -> Element

Build the screen's element for a route carrying params.

matches

matches(target: Any, *, exact: bool = False) -> bool

Whether target (a component or navigator) is what this screen renders.

Identity decides; unless exact, a component replaced by Fast Refresh also matches its predecessor by module, qualified name, and display name. Components made by one factory share a qualified name, so callers try an identity match across every screen first (see find_screen).

Group

Group(
    *screens: "ScreenLike", **options: Unpack[ScreenOptions]
)

Screens that share a layer of options.

pn.StackNavigator(
    Home,
    pn.Group(pn.Screen(Compose), pn.Screen(Filters), presentation="modal"),
)

Parameters:

Name Type Description Default
*screens 'ScreenLike'

The grouped screens (Screen objects, bare components or navigators, or nested groups).

()
**options Unpack[ScreenOptions]

ScreenOptions layered between the navigator's screen_options and each screen's own options.

{}

validate_screen_options

validate_screen_options(options: Mapping[str, Any]) -> None

Reject unknown option keys and presentation / animation values outside their Literal.

Raises:

Type Description
TypeError

If options names a key that isn't a ScreenOptions field.

ValueError

If an enumerated option holds a value outside its Literal.

find_screen

find_screen(
    screens: Iterable[Screen], target: Any
) -> Optional[Screen]

The screen rendering target: an identity match wins over a Fast Refresh name match.

flatten_screens

flatten_screens(
    items: Sequence[ScreenLike],
) -> tuple[tuple[Screen, ...], Dict[str, Dict[str, Any]]]

Expand groups into (screens, group_options_by_name).

Raises:

Type Description
TypeError

For an entry that isn't a screen, group, component, or navigator.

ValueError

For duplicate route names.

State

Immutable navigation state and the pure operations on it.

A navigator's state is a NavigationState: an ordered tuple of Route entries plus the index of the active one. Stack navigators treat the tuple as a history (the active route is always the last); tab and drawer navigators keep one route per screen and move the index.

Every operation returns a new state, so navigators can store the state in use_state and diff it like any other value. States serialize to plain dicts (to_dict / from_dict) so a native host can hand a pushed screen the full history it belongs to.

Classes:

Name Description
Route

One entry in a navigator's state.

NavigationState

Immutable ordered routes plus the active index.

Route

Route(
    name: str,
    params: Optional[Mapping[str, Any]] = None,
    key: Optional[str] = None,
    state: Optional["NavigationState"] = None,
)

One entry in a navigator's state.

A screen receives its route's params as component arguments, so most code never reads a Route. Use use_route when a screen needs its identity (key) or its route name.

Attributes:

Name Type Description
name

The route name of the screen this route renders.

params Dict[str, Any]

The screen component's arguments, as a plain dict.

key

Stable identity for this particular visit to the screen, unique per process. Two pushes of the same screen have different keys, so their component state never mixes.

state

Seed state for a navigator rendered by this screen (set when navigating to a screen inside a nested navigator, and by deep links). None for ordinary screens.

Methods:

Name Description
with_params

Return a copy carrying params (merged over the current ones by default).

with_state

Return a copy carrying a nested navigator seed state.

to_dict

Serialize to a plain dict (name, params, key, and state when nested).

from_dict

Rebuild a route from to_dict output, keeping its key so component state carries over.

with_params

with_params(
    params: Mapping[str, Any], *, merge: bool = True
) -> "Route"

Return a copy carrying params (merged over the current ones by default).

with_state

with_state(state: Optional['NavigationState']) -> 'Route'

Return a copy carrying a nested navigator seed state.

to_dict

to_dict() -> Dict[str, Any]

Serialize to a plain dict (name, params, key, and state when nested).

from_dict classmethod

from_dict(data: Mapping[str, Any]) -> 'Route'

Rebuild a route from to_dict output, keeping its key so component state carries over.

NavigationState

NavigationState(
    routes: Iterable[Route], index: Optional[int] = None
)

Immutable ordered routes plus the active index.

Attributes:

Name Type Description
routes Tuple[Route, ...]

The routes, oldest first.

index

Position of the active route in routes.

Methods:

Name Description
find

Index of the most recent route named name, or None.

push

Append a new route and make it active (drops any forward entries).

pop

Remove up to count routes from the end (never below one).

pop_to_top

Keep only the first route.

pop_to

Pop back to the most recent route named name, merging params into it.

replace

Swap the active route for a fresh one (new key, so state resets).

navigate

Go to name: pop back to it if it's in the history, else push it.

jump_to

Activate the route named name in place, merging params.

set_params

Merge params into the active route.

reset

Return a state holding exactly routes with index active (the last route by default).

to_dict

Serialize to a plain dict with routes (each via Route.to_dict) and index.

from_dict

Rebuild a state from to_dict output; a missing index activates the last route.

current property

current: Route

The active route.

can_go_back property

can_go_back: bool

Whether a route precedes the active one.

find

find(name: str) -> Optional[int]

Index of the most recent route named name, or None.

push

push(
    name: str,
    params: Optional[Mapping[str, Any]] = None,
    state: Optional["NavigationState"] = None,
) -> "NavigationState"

Append a new route and make it active (drops any forward entries).

pop

pop(count: int = 1) -> 'NavigationState'

Remove up to count routes from the end (never below one).

pop_to_top

pop_to_top() -> 'NavigationState'

Keep only the first route.

pop_to

pop_to(
    name: str,
    params: Optional[Mapping[str, Any]] = None,
    state: Optional["NavigationState"] = None,
) -> "NavigationState"

Pop back to the most recent route named name, merging params into it.

replace

replace(
    name: str,
    params: Optional[Mapping[str, Any]] = None,
    state: Optional["NavigationState"] = None,
) -> "NavigationState"

Swap the active route for a fresh one (new key, so state resets).

navigate

navigate(
    name: str,
    params: Optional[Mapping[str, Any]] = None,
    state: Optional["NavigationState"] = None,
) -> "NavigationState"

Go to name: pop back to it if it's in the history, else push it.

jump_to

jump_to(
    name: str,
    params: Optional[Mapping[str, Any]] = None,
    state: Optional["NavigationState"] = None,
) -> "NavigationState"

Activate the route named name in place, merging params.

set_params

set_params(params: Mapping[str, Any]) -> 'NavigationState'

Merge params into the active route.

reset

reset(
    routes: Sequence[Route], index: Optional[int] = None
) -> "NavigationState"

Return a state holding exactly routes with index active (the last route by default).

to_dict

to_dict() -> Dict[str, Any]

Serialize to a plain dict with routes (each via Route.to_dict) and index.

from_dict classmethod

from_dict(data: Mapping[str, Any]) -> 'NavigationState'

Rebuild a state from to_dict output; a missing index activates the last route.

Host bridge

Bridge between the native screen host and the navigation tree.

The host wraps the app's root element in HostRoot, which publishes:

Pushed screens receive their navigation history under the "pn_nav" key of the host's launch arguments; the root stack reads it through HostNavigator.initial_navigation_state.

Functions:

Name Description
HostRoot

Publish the host bridge and its focus state to the tree below.

Attributes:

Name Type Description
NAV_STATE_ARG

Launch-argument key under which a pushed screen receives its serialized navigation state.

HostContext Context[Optional[HostNavigator]]

The native host bridging this tree, or None when rendering without one (tests, rows).

NAV_STATE_ARG module-attribute

NAV_STATE_ARG = 'pn_nav'

Launch-argument key under which a pushed screen receives its serialized navigation state.

HostContext module-attribute

HostContext: Context[Optional[HostNavigator]] = (
    create_context(None, name="Host")
)

The native host bridging this tree, or None when rendering without one (tests, rows).

HostRoot

HostRoot(*children: Node, host: HostNavigator) -> Element

Publish the host bridge and its focus state to the tree below.

initial_state_from_args

initial_state_from_args(
    args: Optional[Dict[str, Any]],
) -> Optional[Dict[str, Any]]

Extract a serialized navigation state from host launch arguments.

Next steps