Modern Text User Interface framework for building cross-platform terminal and web applications with Python
Overall
score
93%
Complete collection of built-in UI components for creating rich terminal interfaces, including input controls, display widgets, navigation components, data widgets, and utility components.
Interactive widgets for user input and form creation.
class Button(Widget):
"""A clickable button widget."""
class Pressed(Message):
"""Sent when the button is pressed."""
def __init__(self, button: Button): ...
def __init__(
self,
label: RenderableType = "",
*,
variant: str = "default",
disabled: bool = False,
**kwargs
):
"""
Initialize a button.
Parameters:
- label: Button text or renderable content
- variant: Button style ("default", "primary", "success", "warning", "error")
- disabled: Whether the button is disabled
"""
def press(self) -> None:
"""Programmatically press the button."""
class Input(Widget):
"""Single-line text input widget."""
class Changed(Message):
"""Sent when input value changes."""
def __init__(self, input: Input, value: str): ...
class Submitted(Message):
"""Sent when input is submitted (Enter key)."""
def __init__(self, input: Input, value: str): ...
def __init__(
self,
value: str = "",
placeholder: str = "",
*,
password: bool = False,
restrict: str | None = None,
type: str = "text",
max_length: int = 0,
**kwargs
):
"""
Initialize an input widget.
Parameters:
- value: Initial input value
- placeholder: Placeholder text when empty
- password: Whether to hide input characters
- restrict: Regex pattern to restrict input
- type: Input type ("text", "integer", "number")
- max_length: Maximum input length (0 for unlimited)
"""
# Properties
value: str
placeholder: str
cursor_position: int
class TextArea(Widget):
"""Multi-line text editor with syntax highlighting."""
class Changed(Message):
"""Sent when text content changes."""
def __init__(
self,
text: str = "",
*,
language: str | None = None,
theme: str = "monokai",
soft_wrap: bool = True,
tab_size: int = 4,
**kwargs
):
"""
Initialize a text area.
Parameters:
- text: Initial text content
- language: Programming language for syntax highlighting
- theme: Color theme for highlighting
- soft_wrap: Whether to wrap long lines
- tab_size: Number of spaces per tab
"""
def load_text(self, text: str) -> None:
"""Load new text content."""
# Properties
text: str
cursor_position: tuple[int, int]
class Checkbox(Widget):
"""Boolean checkbox input."""
class Changed(Message):
"""Sent when checkbox state changes."""
def __init__(self, checkbox: Checkbox, value: bool): ...
def __init__(self, label: str = "", *, value: bool = False, **kwargs):
"""
Initialize a checkbox.
Parameters:
- label: Checkbox label text
- value: Initial checked state
"""
def toggle(self) -> None:
"""Toggle the checkbox state."""
# Properties
value: bool
class Switch(Widget):
"""Toggle switch control."""
class Changed(Message):
"""Sent when switch state changes."""
def __init__(self, *, value: bool = False, **kwargs):
"""
Initialize a switch.
Parameters:
- value: Initial switch state
"""
def toggle(self) -> None:
"""Toggle the switch state."""
# Properties
value: bool
class RadioButton(Widget):
"""Individual radio button."""
class Changed(Message):
"""Sent when radio button selection changes."""
def __init__(self, label: str = "", *, value: bool = False, **kwargs):
"""
Initialize a radio button.
Parameters:
- label: Radio button label
- value: Whether this button is selected
"""
# Properties
value: bool
class RadioSet(Widget):
"""Group of radio buttons."""
class Changed(Message):
"""Sent when selection changes."""
def __init__(self, radio_set: RadioSet, pressed: RadioButton): ...
def __init__(self, *labels: str, **kwargs):
"""
Initialize a radio set.
Parameters:
- *labels: Radio button labels
"""
# Properties
pressed_button: RadioButton | None
pressed_index: int
class Select(Widget):
"""Dropdown selection widget."""
class Changed(Message):
"""Sent when selection changes."""
def __init__(
self,
options: Iterable[tuple[str, Any]] | Iterable[str],
*,
value: Any = None,
allow_blank: bool = True,
**kwargs
):
"""
Initialize a select widget.
Parameters:
- options: Selection options as (label, value) tuples or strings
- value: Initial selected value
- allow_blank: Whether to allow no selection
"""
# Properties
value: Any
options: list[tuple[str, Any]]Widgets for displaying static and dynamic content.
class Static(Widget):
"""Display static rich content."""
def __init__(self, renderable: RenderableType = "", **kwargs):
"""
Initialize a static widget.
Parameters:
- renderable: Content to display (string, Rich object, etc.)
"""
def update(self, renderable: RenderableType) -> None:
"""Update the displayed content."""
class Label(Widget):
"""Simple text label."""
def __init__(self, text: str = "", **kwargs):
"""
Initialize a label.
Parameters:
- text: Label text content
"""
# Properties
text: str
class Pretty(Widget):
"""Pretty-printed Python objects using Rich."""
def __init__(self, obj: Any, **kwargs):
"""
Initialize a pretty widget.
Parameters:
- obj: Python object to pretty-print
"""
def update(self, obj: Any) -> None:
"""Update the displayed object."""
class Markdown(Widget):
"""Markdown content renderer."""
class LinkClicked(Message):
"""Sent when a markdown link is clicked."""
def __init__(self, markdown: str = "", **kwargs):
"""
Initialize a markdown widget.
Parameters:
- markdown: Markdown text content
"""
# Properties
markdown: str
class MarkdownViewer(Widget):
"""Scrollable markdown viewer with navigation."""
def __init__(self, markdown: str = "", **kwargs):
"""
Initialize a markdown viewer.
Parameters:
- markdown: Markdown content to display
"""
def go(self, location: str) -> None:
"""Navigate to a specific location in the document."""
class RichLog(Widget):
"""Rich text logging display."""
def __init__(self, *, max_lines: int | None = None, **kwargs):
"""
Initialize a rich log.
Parameters:
- max_lines: Maximum number of log lines to keep
"""
def write(self, content: RenderableType) -> None:
"""Write content to the log."""
def clear(self) -> None:
"""Clear all log content."""
class Log(Widget):
"""Simple text logging widget."""
def write_line(self, line: str) -> None:
"""Write a line to the log."""
def clear(self) -> None:
"""Clear the log."""
class Digits(Widget):
"""Large digital display for numbers."""
def __init__(self, value: str = "", **kwargs):
"""
Initialize a digits display.
Parameters:
- value: Number to display as string
"""
def update(self, value: str) -> None:
"""Update the displayed number."""
class ProgressBar(Widget):
"""Progress indicator bar."""
def __init__(
self,
total: float = 100,
*,
show_eta: bool = True,
show_percentage: bool = True,
**kwargs
):
"""
Initialize a progress bar.
Parameters:
- total: Total progress value
- show_eta: Whether to show estimated time remaining
- show_percentage: Whether to show percentage
"""
def advance(self, amount: float = 1) -> None:
"""Advance progress by amount."""
def update(self, *, completed: float = None, total: float = None) -> None:
"""Update progress values."""
# Properties
progress: float
percentage: floatWidgets for organizing content and navigation.
class Header(Widget):
"""Application header bar."""
def __init__(self, *, show_clock: bool = False, **kwargs):
"""
Initialize a header.
Parameters:
- show_clock: Whether to display a clock
"""
class Footer(Widget):
"""Application footer bar."""
def __init__(self, **kwargs):
"""Initialize a footer."""
class Tabs(Widget):
"""Tab navigation container."""
class TabActivated(Message):
"""Sent when a tab is activated."""
def __init__(self, tabs: Tabs, tab: Tab): ...
def add_tab(self, tab: str | Tab, **kwargs) -> Tab:
"""
Add a new tab.
Parameters:
- tab: Tab instance or tab label
Returns:
The added Tab instance
"""
def remove_tab(self, tab_id: str) -> None:
"""Remove a tab by ID."""
# Properties
active_tab: Tab | None
class Tab(Widget):
"""Individual tab component."""
def __init__(self, label: str, **kwargs):
"""
Initialize a tab.
Parameters:
- label: Tab display label
"""
# Properties
label: str
class TabbedContent(Widget):
"""Tabbed content container."""
def add_pane(self, pane: TabPane) -> None:
"""Add a content pane."""
def remove_pane(self, pane_id: str) -> None:
"""Remove a content pane."""
class TabPane(Widget):
"""Individual tab content pane."""
def __init__(self, title: str, **kwargs):
"""
Initialize a tab pane.
Parameters:
- title: Pane title for the tab
"""
class Tree(Widget):
"""Hierarchical tree view."""
class NodeSelected(Message):
"""Sent when a tree node is selected."""
class NodeExpanded(Message):
"""Sent when a tree node is expanded."""
def __init__(self, label: str, **kwargs):
"""
Initialize a tree.
Parameters:
- label: Root node label
"""
def add(self, label: str, *, data: Any = None) -> TreeNode:
"""
Add a child node.
Parameters:
- label: Node display label
- data: Associated node data
Returns:
The created TreeNode
"""
def clear(self) -> None:
"""Clear all tree nodes."""
class DirectoryTree(Widget):
"""File system directory browser."""
class DirectorySelected(Message):
"""Sent when a directory is selected."""
class FileSelected(Message):
"""Sent when a file is selected."""
def __init__(self, path: str | Path, **kwargs):
"""
Initialize a directory tree.
Parameters:
- path: Root directory path
"""
def reload(self) -> None:
"""Reload the directory tree."""
class Collapsible(Widget):
"""Expandable/collapsible sections."""
class Toggled(Message):
"""Sent when collapsed state changes."""
def __init__(
self,
title: str = "",
*,
collapsed: bool = True,
**kwargs
):
"""
Initialize a collapsible.
Parameters:
- title: Section title
- collapsed: Initial collapsed state
"""
def toggle(self) -> None:
"""Toggle collapsed/expanded state."""
# Properties
collapsed: bool
class Rule(Widget):
"""Horizontal or vertical separator line."""
def __init__(
self,
orientation: str = "horizontal",
*,
line_style: str = "solid",
**kwargs
):
"""
Initialize a rule.
Parameters:
- orientation: "horizontal" or "vertical"
- line_style: Line drawing style
"""Widgets for displaying and interacting with structured data.
class DataTable(Widget):
"""Spreadsheet-like data grid."""
class RowSelected(Message):
"""Sent when a row is selected."""
class CellSelected(Message):
"""Sent when a cell is selected."""
def __init__(self, *, zebra_stripes: bool = False, **kwargs):
"""
Initialize a data table.
Parameters:
- zebra_stripes: Whether to alternate row colors
"""
def add_column(
self,
key: str,
*,
label: str | None = None,
width: int | None = None,
**kwargs
) -> None:
"""
Add a table column.
Parameters:
- key: Unique column identifier
- label: Column header label
- width: Column width in characters
"""
def add_row(self, *cells: Any, **kwargs) -> RowKey:
"""
Add a data row.
Parameters:
- *cells: Cell values for the row
Returns:
Key identifying the added row
"""
def remove_row(self, row_key: RowKey) -> None:
"""Remove a row by key."""
def clear(self, columns: bool = False) -> None:
"""
Clear table data.
Parameters:
- columns: Whether to also remove columns
"""
# Properties
row_count: int
column_count: int
class ListView(Widget):
"""Scrollable list container."""
class Selected(Message):
"""Sent when list item is selected."""
class Highlighted(Message):
"""Sent when list item is highlighted."""
def __init__(self, *children: ListItem, **kwargs):
"""
Initialize a list view.
Parameters:
- *children: Initial list items
"""
def append(self, item: ListItem) -> None:
"""Add item to end of list."""
def extend(self, items: Iterable[ListItem]) -> None:
"""Add multiple items to list."""
def clear(self) -> None:
"""Remove all list items."""
# Properties
index: int | None
class ListItem(Widget):
"""Individual list item."""
def __init__(self, child: Widget, **kwargs):
"""
Initialize a list item.
Parameters:
- child: Widget to display in the item
"""
class OptionList(Widget):
"""Selectable option list."""
class OptionSelected(Message):
"""Sent when an option is selected."""
def __init__(self, *options: str | Option, **kwargs):
"""
Initialize an option list.
Parameters:
- *options: Initial options
"""
def add_option(self, option: str | Option) -> None:
"""Add a new option."""
def remove_option(self, option_id: str) -> None:
"""Remove an option by ID."""
def clear_options(self) -> None:
"""Remove all options."""
# Properties
highlighted: int | None
class SelectionList(Widget):
"""Multi-select list widget."""
class SelectionToggled(Message):
"""Sent when selection changes."""
def __init__(self, *selections: Selection, **kwargs):
"""
Initialize a selection list.
Parameters:
- *selections: Initial selections
"""
def select_all(self) -> None:
"""Select all items."""
def deselect_all(self) -> None:
"""Deselect all items."""
# Properties
selected: list[int]Specialized widgets for development, loading states, and system functions.
class Placeholder(Widget):
"""Development placeholder widget."""
def __init__(self, label: str = "Placeholder", **kwargs):
"""
Initialize a placeholder.
Parameters:
- label: Placeholder display text
"""
class LoadingIndicator(Widget):
"""Loading animation indicator."""
def __init__(self, **kwargs):
"""Initialize a loading indicator."""
class Tooltip(Widget):
"""Hover help text."""
def __init__(self, text: str, **kwargs):
"""
Initialize a tooltip.
Parameters:
- text: Tooltip text content
"""
class ContentSwitcher(Widget):
"""Dynamic content switching widget."""
def __init__(self, **kwargs):
"""Initialize a content switcher."""
def current(self) -> str | None:
"""Get the current content identifier."""
class Welcome(Widget):
"""Welcome screen component."""
def __init__(self, **kwargs):
"""Initialize a welcome screen."""from textual.app import App
from textual.containers import Container, Horizontal
from textual.widgets import Button, Input, Checkbox, Select
class FormApp(App):
def compose(self):
yield Container(
Input(placeholder="Enter your name", id="name"),
Input(placeholder="Enter email", id="email"),
Select([("Option 1", 1), ("Option 2", 2)], id="choice"),
Checkbox("Subscribe to newsletter", id="subscribe"),
Horizontal(
Button("Submit", variant="primary", id="submit"),
Button("Cancel", id="cancel"),
),
id="form"
)
def on_button_pressed(self, event: Button.Pressed):
if event.button.id == "submit":
name = self.query_one("#name", Input).value
email = self.query_one("#email", Input).value
choice = self.query_one("#choice", Select).value
newsletter = self.query_one("#subscribe", Checkbox).value
self.log(f"Form submitted: {name}, {email}, {choice}, {newsletter}")from textual.app import App
from textual.widgets import DataTable
class TableApp(App):
def compose(self):
yield DataTable(zebra_stripes=True)
def on_mount(self):
table = self.query_one(DataTable)
# Add columns
table.add_column("Name", key="name")
table.add_column("Age", key="age")
table.add_column("City", key="city")
# Add rows
table.add_row("Alice", 30, "New York")
table.add_row("Bob", 25, "London")
table.add_row("Carol", 35, "Tokyo")Install with Tessl CLI
npx tessl i tessl/pypi-textualevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10