mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
tabbed content widget (#2059)
* tabbed content widget * TabbedContent widget and docs * missing docs * fix active * doc fix * test fix * additional test * test for render_str * docstring * changelog * doc update * changelog * fix bad optimization * Update docs/widgets/tabbed_content.md Co-authored-by: Dave Pearson <davep@davep.org> * fix for empty initial * docstrings * Update src/textual/widgets/_content_switcher.py Co-authored-by: Dave Pearson <davep@davep.org> * docstring * remove log * permit nested tabs * renamed TabsCleared to Cleared * added tests, fix types on click * tests * fix broken test * fix for nested tabs --------- Co-authored-by: Dave Pearson <davep@davep.org>
This commit is contained in:
@@ -33,7 +33,7 @@ Example app showing the widget:
|
||||
|
||||
## Bindings
|
||||
|
||||
The WIDGET widget defines directly the following bindings:
|
||||
The WIDGET widget defines the following bindings:
|
||||
|
||||
::: textual.widgets.WIDGET.BINDINGS
|
||||
options:
|
||||
|
||||
@@ -34,7 +34,7 @@ The example below shows check boxes in various states.
|
||||
|
||||
## Bindings
|
||||
|
||||
The checkbox widget defines directly the following bindings:
|
||||
The checkbox widget defines the following bindings:
|
||||
|
||||
::: textual.widgets._toggle_button.ToggleButton.BINDINGS
|
||||
options:
|
||||
|
||||
@@ -23,7 +23,7 @@ The example below populates a table with CSV data.
|
||||
## Reactive Attributes
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|---------------------|---------------------------------------------|--------------------|-------------------------------------------------------|
|
||||
| ------------------- | ------------------------------------------- | ------------------ | ----------------------------------------------------- |
|
||||
| `show_header` | `bool` | `True` | Show the table header |
|
||||
| `fixed_rows` | `int` | `0` | Number of fixed rows (rows which do not scroll) |
|
||||
| `fixed_columns` | `int` | `0` | Number of fixed columns (columns which do not scroll) |
|
||||
@@ -52,7 +52,7 @@ The example below populates a table with CSV data.
|
||||
|
||||
## Bindings
|
||||
|
||||
The data table widget defines directly the following bindings:
|
||||
The data table widget defines the following bindings:
|
||||
|
||||
::: textual.widgets.DataTable.BINDINGS
|
||||
options:
|
||||
|
||||
@@ -41,7 +41,7 @@ The example below shows an app with a simple `ListView`.
|
||||
|
||||
## Bindings
|
||||
|
||||
The list view widget defines directly the following bindings:
|
||||
The list view widget defines the following bindings:
|
||||
|
||||
::: textual.widgets.ListView.BINDINGS
|
||||
options:
|
||||
|
||||
@@ -31,12 +31,12 @@ The example below shows radio buttons, used within a [`RadioSet`](./radioset.md)
|
||||
## Reactive Attributes
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|---------|--------|---------|--------------------------------|
|
||||
| ------- | ------ | ------- | ------------------------------ |
|
||||
| `value` | `bool` | `False` | The value of the radio button. |
|
||||
|
||||
## Bindings
|
||||
|
||||
The radio button widget defines directly the following bindings:
|
||||
The radio button widget defines the following bindings:
|
||||
|
||||
::: textual.widgets._toggle_button.ToggleButton.BINDINGS
|
||||
options:
|
||||
|
||||
@@ -29,12 +29,12 @@ The example below shows switches in various states.
|
||||
## Reactive Attributes
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|---------|--------|---------|--------------------------|
|
||||
| ------- | ------ | ------- | ------------------------ |
|
||||
| `value` | `bool` | `False` | The value of the switch. |
|
||||
|
||||
## Bindings
|
||||
|
||||
The switch widget defines directly the following bindings:
|
||||
The switch widget defines the following bindings:
|
||||
|
||||
::: textual.widgets.Switch.BINDINGS
|
||||
options:
|
||||
|
||||
106
docs/widgets/tabbed_content.md
Normal file
106
docs/widgets/tabbed_content.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# TabbedContent
|
||||
|
||||
Switch between mutually exclusive content panes via a row of tabs.
|
||||
|
||||
- [x] Focusable
|
||||
- [x] Container
|
||||
|
||||
This widget combines the [Tabs](../widgets/tabs.md) and [ContentSwitcher](../widgets/content_switcher.md) 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][textual.widgets.TabbedContent] constructor:
|
||||
|
||||
```python
|
||||
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][textual.widgets.TabPane] widget, which takes the tab title as the first parameter:
|
||||
|
||||
```python
|
||||
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.
|
||||
|
||||
```python
|
||||
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:
|
||||
|
||||
```python
|
||||
# Switch to Jessica tab
|
||||
self.query_one(TabbedContent).active = "jessica"
|
||||
```
|
||||
|
||||
!!! 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:
|
||||
|
||||
```python
|
||||
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.
|
||||
|
||||
=== "Output"
|
||||
|
||||
```{.textual path="docs/examples/widgets/tabbed_content.py"}
|
||||
```
|
||||
|
||||
=== "tabbed_content.py"
|
||||
|
||||
```python
|
||||
--8<-- "docs/examples/widgets/tabbed_content.py"
|
||||
```
|
||||
|
||||
## Reactive attributes
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| -------- | ----- | ------- | -------------------------------------------------------------- |
|
||||
| `active` | `str` | `""` | The `id` attribute of the active tab. Set this to switch tabs. |
|
||||
|
||||
|
||||
## See also
|
||||
|
||||
- [TabbedContent](../api/tabbed_content.md) code reference.
|
||||
- [Tabs](../api/tabs.md) code reference.
|
||||
- [ContentSwitcher](../api/content_switcher.md) code reference.
|
||||
@@ -60,6 +60,7 @@ The following example adds a `Tabs` widget above a text label. Press ++a++ to ad
|
||||
## Messages
|
||||
|
||||
### ::: textual.widgets.Tabs.TabActivated
|
||||
### ::: textual.widgets.Tabs.TabsCleared
|
||||
|
||||
## Bindings
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ Tree widgets have a "root" attribute which is an instance of a [TreeNode][textua
|
||||
|
||||
## Bindings
|
||||
|
||||
The tree widget defines directly the following bindings:
|
||||
The tree widget defines the following bindings:
|
||||
|
||||
::: textual.widgets.Tree.BINDINGS
|
||||
options:
|
||||
|
||||
Reference in New Issue
Block a user