Skip to content

ContentSwitcher

Added in version 0.14.0

A widget for containing and switching display between multiple child widgets.

  • Focusable
  • Container

Example

The example below uses a ContentSwitcher in combination with two Buttons to create a simple tabbed view. Note how each Button has an ID set, and how each child of the ContentSwitcher has a corresponding ID; then a Button.Clicked handler is used to set ContentSwitcher.current to switch between the different views.

ContentSwitcherApp ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔  DataTable  Markdown  ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ╭────────────────────────────────────────────────────────────────────╮  Book                                 Year   Dune                                 1965   Dune Messiah                         1969   Children of Dune                     1976   God Emperor of Dune                  1981   Heretics of Dune                     1984   Chapterhouse: Dune                   1985  ╰────────────────────────────────────────────────────────────────────╯

from textual.app import App, ComposeResult
from textual.containers import Horizontal, VerticalScroll
from textual.widgets import Button, ContentSwitcher, DataTable, Markdown

MARKDOWN_EXAMPLE = """# Three Flavours Cornetto

The Three Flavours Cornetto trilogy is an anthology series of British
comedic genre films directed by Edgar Wright.

## Shaun of the Dead

| Flavour | UK Release Date | Director |
| -- | -- | -- |
| Strawberry | 2004-04-09 | Edgar Wright |

## Hot Fuzz

| Flavour | UK Release Date | Director |
| -- | -- | -- |
| Classico | 2007-02-17 | Edgar Wright |

## The World's End

| Flavour | UK Release Date | Director |
| -- | -- | -- |
| Mint | 2013-07-19 | Edgar Wright |
"""


class ContentSwitcherApp(App[None]):
    CSS_PATH = "content_switcher.tcss"

    def compose(self) -> ComposeResult:
        with Horizontal(id="buttons"):  # (1)!
            yield Button("DataTable", id="data-table")  # (2)!
            yield Button("Markdown", id="markdown")  # (3)!

        with ContentSwitcher(initial="data-table"):  # (4)!
            yield DataTable(id="data-table")
            with VerticalScroll(id="markdown"):
                yield Markdown(MARKDOWN_EXAMPLE)

    def on_button_pressed(self, event: Button.Pressed) -> None:
        self.query_one(ContentSwitcher).current = event.button.id  # (5)!

    def on_mount(self) -> None:
        table = self.query_one(DataTable)
        table.add_columns("Book", "Year")
        table.add_rows(
            [
                (title.ljust(35), year)
                for title, year in (
                    ("Dune", 1965),
                    ("Dune Messiah", 1969),
                    ("Children of Dune", 1976),
                    ("God Emperor of Dune", 1981),
                    ("Heretics of Dune", 1984),
                    ("Chapterhouse: Dune", 1985),
                )
            ]
        )


if __name__ == "__main__":
    ContentSwitcherApp().run()
  1. A Horizontal to hold the buttons, each with a unique ID.
  2. This button will select the DataTable in the ContentSwitcher.
  3. This button will select the Markdown in the ContentSwitcher.
  4. Note that the initial visible content is set by its ID, see below.
  5. When a button is pressed, its ID is used to switch to a different widget in the ContentSwitcher. Remember that IDs are unique within parent, so the buttons and the widgets in the ContentSwitcher can share IDs.
Screen {
    align: center middle;
    padding: 1;
}

#buttons {
    height: 3;
    width: auto;
}

ContentSwitcher {
    background: $panel;
    border: round $primary;
    width: 90%;
    height: 1fr;
}

DataTable {
    background: $panel;
}

MarkdownH2 {
    background: $primary;
    color: yellow;
    border: none;
    padding: 0;
}

When the user presses the "Markdown" button the view is switched:

ContentSwitcherApp ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔  DataTable  Markdown  ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ╭────────────────────────────────────────────────────────────────────╮ Three Flavours Cornetto   The Three Flavours Cornetto trilogy is an anthology series of      British comedic genre films directed by Edgar Wright. Shaun of the Dead Flavour         UK Release Date         Director              ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━       Strawberry       2004-04-09               Edgar Wright          Hot Fuzz Flavour       UK Release Date          Director               ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━       Classico       2007-02-17                Edgar Wright           The World's End Flavour     UK Release Date           Director                ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━       Mint         2013-07-19                 Edgar Wright            ▇▇ ╰────────────────────────────────────────────────────────────────────╯

Reactive Attributes

Name Type Default Description
current str | None None The ID of the currently-visible child. None means nothing is visible.

Messages

This widget posts no messages.

Bindings

This widget has no bindings.

Component Classes

This widget has no component classes.


Bases: Container

A widget for switching between different children.

Note

All child widgets that are to be switched between need a unique ID. Children that have no ID will be hidden and ignored.

Parameters:

Name Type Description Default

*children

Widget

The widgets to switch between.

()

name

str | None

The name of the content switcher.

None

id

str | None

The ID of the content switcher in the DOM.

None

classes

str | None

The CSS classes of the content switcher.

None

disabled

bool

Whether the content switcher is disabled or not.

False

initial

str | None

The ID of the initial widget to show, None or empty string for the first tab.

None
Note

If initial is not supplied no children will be shown to start with.

current class-attribute instance-attribute

current = reactive[Optional[str]](None, init=False)

The ID of the currently-displayed widget.

If set to None then no widget is visible.

Note

If set to an unknown ID, this will result in NoMatches being raised.

visible_content property

visible_content

A reference to the currently-visible widget.

None if nothing is visible.

add_content

add_content(widget, *, id=None, set_current=False)

Add new content to the ContentSwitcher.

Parameters:

Name Type Description Default

widget

Widget

A Widget to add.

required

id

str | None

ID for the widget, or None if the widget already has an ID.

None

set_current

bool

Set the new widget as current (which will cause it to display).

False

Returns:

Type Description
AwaitComplete

An awaitable to wait for the new content to be mounted.

watch_current

watch_current(old, new)

React to the current visible child choice being changed.

Parameters:

Name Type Description Default

old

str | None

The old widget ID (or None if there was no widget).

required

new

str | None

The new widget ID (or None if nothing should be shown).

required