Skip to content

Tabs

Tabs switch between peer panels of content in the same region. They map to Bootstrap 5 tabbed navigation (nav-tabs / nav-pills) and are the usual pattern for settings pages, item inspectors, and any view where the user flips between a small set of named sections.

Use Tabs when every panel is equally important and should stay mounted in the page. Use an Offcanvas or a separate route when a section is a destination of its own.

Basic usage

tabs_basic_usage example

def demo() -> None:
    def on_change(_event: object) -> None:
        pass

    with bs.scope():
        bs.Tabs(
            bs.Tab("Overview"),
            bs.Tab("Settings"),
            active_tab="Overview",
            on_change=on_change,
        )

Compose Tabs with Tab children. Each Tab holds the panel body for that section. active_tab selects which panel is shown first; on_change runs when the user picks another tab.

Live example

The snippets below are exactly what the demo service runs. Each highlighted demo() function is the same source the demo executes, not a rewritten copy.

Card tabs

tabs_card example

def demo() -> None:
    with bs.scope():
        tabs = bs.tabs(card=True)
        with tabs:
            bs.tab(label="Home")
            bs.tab(label="Profile")
            bs.tab(label="Contact")
        ui.label("Active tab is tracked on the tabs component.")

Tabs without ids

tabs_no_ids example

def demo() -> None:
    with bs.scope(), bs.tabs():
        bs.tab(label="Alpha")
        bs.tab(label="Beta")
        bs.tab(label="Gamma")

Options

Composition

Pass every panel as a Tab child of Tabs. The tab label and the panel content come from that child. Keep the number of tabs small; a long row of labels is harder to scan than a vertical nav.

tabs_composition example

def demo() -> None:
    with bs.scope():
        bs.Tabs(
            bs.Tab("Team"),
            bs.Tab("Billing"),
            bs.Tab("Audit log"),
            active_tab="Team",
        )

Put structured widgets inside each Tab when the panel is more than a sentence. The tab strip stays the navigation; the child is the page.

Active tab and on_change

active_tab is the identifier of the selected panel. Keep it in application state so deep links, breadcrumbs, and the tab strip all agree. on_change is the Python handler for a user-driven switch: persist the choice, lazy-load the panel, or sync a URL parameter.

tabs_active_tab_on_change example

def demo() -> None:
    def on_change(_event: object) -> None:
        ui.notify("tab changed")

    with bs.scope():
        bs.Tabs(
            bs.Tab("Overview"),
            bs.Tab("Metrics"),
            active_tab="Overview",
            on_change=on_change,
            class_name="nav-pills",
        )

Do not rebuild the whole Tabs tree just to change the selection; update active_tab and let the component restyle the strip.

Pills and card

class_name="nav-pills" switches the strip to Bootstrap's pill style instead of underlined tabs. That style sits well on tinted headers and compact toolbars. card wraps the strip and panels in a card-like frame so the tabs read as one surface, which is useful on dashboards where the control is a standalone block.

tabs_with_card example

def demo() -> None:
    with bs.scope():
        bs.Tabs(
            bs.Tab("Day"),
            bs.Tab("Week"),
            card=True,
            active_tab="Day",
        )

Pill styling and card compose: nav-pills changes the labels, card changes the chrome. Use one or both, but keep the choice consistent across the app so tab strips do not look like different components.

Argument reference

Property Type Default DBC 2.0.4 name Support (native) Support (compat)
children a list of or a singular dash component, string or number None children supported supported
id string None id supported supported
active_tab string None active_tab supported supported
style unknown None style supported supported
class_name string None className supported supported
persistence boolean | string | number None persistence unsupported unsupported
persisted_props list of a value equal to: 'active_tab's None persisted_props unsupported unsupported
persistence_type a value equal to: 'local', 'session', 'memory' None persistence_type unsupported unsupported
key string None key unsupported unsupported
class_name string None className supported supported