TabbedContent¶
Added in version 0.16.0
Switch between mutually exclusive content panes via a row of tabs.
- Focusable
- Container
This widget combines the Tabs and ContentSwitcher widgets to create a convenient way of navigating content.
Only a single child of TabbedContent is visible at once. Each child has an associated tab which will make it visible and hide the others.
Composing¶
There are two ways to provide the titles for the tab. You can pass them as positional arguments to the TabbedContent constructor:
def compose(self) -> ComposeResult:
with TabbedContent("Leto", "Jessica", "Paul"):
yield Markdown(LETO)
yield Markdown(JESSICA)
yield Markdown(PAUL)
Alternatively you can wrap the content in a TabPane widget, which takes the tab title as the first parameter:
def compose(self) -> ComposeResult:
with TabbedContent():
with TabPane("Leto"):
yield Markdown(LETO)
with TabPane("Jessica"):
yield Markdown(JESSICA)
with TabPane("Paul"):
yield Markdown(PAUL)
Switching tabs¶
If you need to programmatically switch tabs, you should provide an id
attribute to the TabPane
s.
def compose(self) -> ComposeResult:
with TabbedContent():
with TabPane("Leto", id="leto"):
yield Markdown(LETO)
with TabPane("Jessica", id="jessica"):
yield Markdown(JESSICA)
with TabPane("Paul", id="paul"):
yield Markdown(PAUL)
You can then switch tabs by setting the active
reactive attribute:
Note
If you don't provide id
attributes to the tab panes, they will be assigned sequentially starting at tab-1
(then tab-2
etc).
Initial tab¶
The first child of TabbedContent
will be the initial active tab by default. You can pick a different initial tab by setting the initial
argument to the id
of the tab:
def compose(self) -> ComposeResult:
with TabbedContent(initial="jessica"):
with TabPane("Leto", id="leto"):
yield Markdown(LETO)
with TabPane("Jessica", id="jessica"):
yield Markdown(JESSICA)
with TabPane("Paul", id="paul"):
yield Markdown(PAUL)
Example¶
The following example contains a TabbedContent
with three tabs.
from textual.app import App, ComposeResult
from textual.widgets import Footer, Label, Markdown, TabbedContent, TabPane
LETO = """
# Duke Leto I Atreides
Head of House Atreides.
"""
JESSICA = """
# Lady Jessica
Bene Gesserit and concubine of Leto, and mother of Paul and Alia.
"""
PAUL = """
# Paul Atreides
Son of Leto and Jessica.
"""
class TabbedApp(App):
"""An example of tabbed content."""
BINDINGS = [
("l", "show_tab('leto')", "Leto"),
("j", "show_tab('jessica')", "Jessica"),
("p", "show_tab('paul')", "Paul"),
]
def compose(self) -> ComposeResult:
"""Compose app with tabbed content."""
# Footer to show keys
yield Footer()
# Add the TabbedContent widget
with TabbedContent(initial="jessica"):
with TabPane("Leto", id="leto"): # First tab
yield Markdown(LETO) # Tab content
with TabPane("Jessica", id="jessica"):
yield Markdown(JESSICA)
with TabbedContent("Paul", "Alia"):
yield TabPane("Paul", Label("First child"))
yield TabPane("Alia", Label("Second child"))
with TabPane("Paul", id="paul"):
yield Markdown(PAUL)
def action_show_tab(self, tab: str) -> None:
"""Switch to a new tab."""
self.get_child_by_type(TabbedContent).active = tab
if __name__ == "__main__":
app = TabbedApp()
app.run()
Reactive attributes¶
Name | Type | Default | Description |
---|---|---|---|
active |
str |
"" |
The id attribute of the active tab. Set this to switch tabs. |
Messages¶
See also¶
textual.widgets.TabbedContent
class
¶
Bases: Widget
A container with associated tabs to toggle content visibility.
Parameters
Name | Type | Description | Default |
---|---|---|---|
*titles |
TextType
|
Positional argument will be used as title. |
()
|
initial |
str
|
The id of the initial tab, or empty string to select the first tab. |
''
|
name |
str | None
|
The name of the button. |
None
|
id |
str | None
|
The ID of the button in the DOM. |
None
|
classes |
str | None
|
The CSS classes of the button. |
None
|
disabled |
bool
|
Whether the button is disabled or not. |
False
|
active
class-attribute
instance-attribute
¶
The ID of the active tab, or empty string if none are active.
TabActivated
class
¶
Bases: Message
Posted when the active tab changes.
Parameters
Name | Type | Description | Default |
---|---|---|---|
tabbed_content |
TabbedContent
|
The TabbedContent widget. |
required |
tab |
Tab
|
The Tab widget that was selected (contains the tab label). |
required |
ALLOW_SELECTOR_MATCH
class-attribute
instance-attribute
¶
Additional message attributes that can be used with the on
decorator.
control
property
¶
The TabbedContent
widget that contains the tab activated.
This is an alias for TabActivated.tabbed_content
and is used by the on
decorator.
tabbed_content
instance-attribute
¶
The TabbedContent
widget that contains the tab activated.
compose_add_child
method
¶
When using the context manager compose syntax, we want to attach nodes to the switcher.
Parameters
Name | Type | Description | Default |
---|---|---|---|
widget |
Widget
|
A Widget to add. |
required |
validate_active
method
¶
It doesn't make sense for active
to be an empty string.
Parameters
Name | Type | Description | Default |
---|---|---|---|
active |
str
|
Attribute to be validated. |
required |
Returns
Type | Description |
---|---|
str
|
Value of |
Raises
Type | Description |
---|---|
ValueError
|
If the active attribute is set to empty string. |
watch_active
method
¶
Switch tabs when the active attributes changes.
textual.widgets.TabPane
class
¶
Bases: Widget
A container for switchable content, with additional title.
This widget is intended to be used with TabbedContent.
Parameters
Name | Type | Description | Default |
---|---|---|---|
title |
TextType
|
Title of the TabPane (will be displayed in a tab label). |
required |
*children |
Widget
|
Widget to go inside the TabPane. |
()
|
name |
str | None
|
Optional name for the TabPane. |
None
|
id |
str | None
|
Optional ID for the TabPane. |
None
|
classes |
str | None
|
Optional initial classes for the widget. |
None
|
disabled |
bool
|
Whether the TabPane is disabled or not. |
False
|