Skip to content

TabView

TabView is a tabbed container that combines a Tabs bar with a PageStack for seamless tab-based content switching.

Each tab corresponds to a page, and selecting a tab automatically navigates to its associated content.


Quick start

Create a tabbed view with pages:

import bootstack as bs

app = bs.App()

tabview = bs.TabView(app, height=200)
tabview.pack(fill="both", expand=True, padx=10, pady=10)

# Add tabs with content
home = tabview.add("home", text="Home", icon="house")
bs.Label(home, text="Welcome to the Home page!").pack(padx=20, pady=20)

files = tabview.add("files", text="Files", icon="folder2")
bs.Label(files, text="Browse your files here.").pack(padx=20, pady=20)

settings = tabview.add("settings", text="Settings", icon="gear")
bs.Label(settings, text="Configure your settings.").pack(padx=20, pady=20)

app.mainloop()

When to use

Use TabView when:

  • you need tabs that switch between content panels

  • users access content by category or section

  • all tabs are equally important and accessible

Consider a different control when:

  • navigation is sequential - use PageStack instead

  • you need a standalone tab bar - use Tabs instead

  • content must be visible simultaneously - use PanedWindow instead


Appearance

Variants

TabView supports two visual variants:

Variant Description
bar Default style with underline indicator and divider
pill Rounded pill-style tabs without divider
# Bar variant (default)
tabview = bs.TabView(app, variant="bar")

# Pill variant
tabview = bs.TabView(app, variant="pill")

Orientation

Tabs can appear above or beside the content:

# Horizontal tabs above content (default)
tabview = bs.TabView(app, orient="horizontal")

# Vertical tabs beside content
tabview = bs.TabView(app, orient="vertical")

Examples and patterns

Adding tabs and pages

Use add() to create a tab and its content page:

page = tabview.add("profile", text="Profile", icon="person")
# page is a Frame - add widgets to it
bs.Label(page, text="User profile").pack()

The key uniquely identifies each tab/page pair.

Closable tabs

Enable close buttons to allow users to remove tabs:

tabview = bs.TabView(app, enable_closing=True)

With enable_closing=True, clicking the close button automatically removes both the tab and its page. You can also provide a custom close handler:

def on_close():
    if confirm_close():
        tabview.remove("doc1")

tabview.add("doc1", text="Document", closable=True, close_command=on_close)

Dynamic tabs with add button

Show an "add" button for creating new tabs:

tabview = bs.TabView(app, enable_adding=True)

counter = [0]

def on_add(event):
    counter[0] += 1
    key = f"doc{counter[0]}"
    page = tabview.add(key, text=f"Document {counter[0]}", icon="file-text")
    bs.Label(page, text=f"Content for Document {counter[0]}").pack()

tabview.on_tab_added(on_add)

Programmatic navigation

Select tabs programmatically:

tabview.select("settings")

Get the current tab:

current_key = tabview.current

Navigate with data:

tabview.navigate("details", data={"user_id": 123})

Accessing components

Access the underlying Tabs and PageStack:

tabs_widget = tabview.tabs
page_stack = tabview.page_stack

Get a specific tab or page:

tab = tabview.tab("settings")  # Returns TabItem
page = tabview.page("settings")  # Returns Frame

Events

TabView emits navigation events:

  • <<TabAdd>> - when add button is clicked
  • <<PageChange>> - when the visible page changes
def on_page_change(event):
    print(f"Now showing: {event.data['page']}")

tabview.on_page_changed(on_page_change)

Behavior

UX guidance

  • Use descriptive tab labels

  • Include icons for visual recognition

  • Limit to 5-7 horizontal tabs for scannability

  • Vertical tabs work well for settings or navigation-heavy interfaces

  • Enable closing only when users should manage tabs (e.g., documents, browser-like interfaces)

Content persistence

Pages are retained when switching tabs. Use PageStack events if you need to refresh content on navigation.


Additional resources

API reference