# Common Widgets ## Display Widgets ### Label / Static Display static or updatable text: ```python from textual.widgets import Label, Static # Label is just an alias for Static label = Label("Hello World") static = Static("Initial text") # Update later static.update("New text") static.update("[bold]Rich markup[/bold]") ``` ### Placeholder Useful for prototyping layouts: ```python from textual.widgets import Placeholder # Shows widget ID and size info yield Placeholder("Custom label", id="p1") yield Placeholder(variant="size") # Shows dimensions yield Placeholder(variant="text") # Shows placeholder text ``` ## Input Widgets ### Button ```python from textual.widgets import Button yield Button("Click Me", id="my-button") yield Button("Disabled", disabled=True) # Handle click def on_button_pressed(self, event: Button.Pressed) -> None: button_id = event.button.id self.notify(f"{button_id} clicked!") ``` ### Input Single-line text input: ```python from textual.widgets import Input yield Input(placeholder="Enter text...", id="name-input") def on_input_changed(self, event: Input.Changed) -> None: self.text_value = event.value def on_input_submitted(self, event: Input.Submitted) -> None: # User pressed Enter self.process_input(event.value) ``` ### TextArea Multi-line text editor: ```python from textual.widgets import TextArea text_area = TextArea() text_area.load_text("Initial content") # Get content content = text_area.text ``` ### Switch Toggle switch (like checkbox): ```python from textual.widgets import Switch yield Switch(value=True) # Initially on def on_switch_changed(self, event: Switch.Changed) -> None: is_on = event.value self.toggle_feature(is_on) ``` ## Data Display ### DataTable Display tabular data: ```python from textual.widgets import DataTable table = DataTable() # Add columns table.add_columns("Name", "Age", "Country") # Add rows table.add_row("Alice", 30, "USA") table.add_row("Bob", 25, "UK") # Add row with custom label from rich.text import Text label = Text("1", style="bold cyan") table.add_row("Charlie", 35, "Canada", label=label) # Configuration table.zebra_stripes = True # Alternating row colors table.cursor_type = "row" # "cell", "row", "column", or "none" table.show_header = True table.show_row_labels = True # Handle selection def on_data_table_row_selected(self, event: DataTable.RowSelected) -> None: row_key = event.row_key row_data = table.get_row(row_key) def on_data_table_cell_selected(self, event: DataTable.CellSelected) -> None: value = event.value coordinate = event.coordinate ``` ## Layout Containers ### Container Generic container for grouping widgets: ```python from textual.containers import Container with Container(id="sidebar"): yield Label("Title") yield Button("Action") ``` ### Vertical / Horizontal / VerticalScroll / HorizontalScroll Directional containers: ```python from textual.containers import Vertical, Horizontal, VerticalScroll with Horizontal(): yield Button("Left") yield Button("Right") with VerticalScroll(): for i in range(100): yield Label(f"Item {i}") ``` ### Grid Grid layout container: ```python from textual.containers import Grid with Grid(id="my-grid"): yield Label("A") yield Label("B") yield Label("C") yield Label("D") # Style in CSS: # Grid { # grid-size: 2 2; /* 2 columns, 2 rows */ # } ``` ## App Widgets ### Header / Footer Standard app chrome: ```python from textual.widgets import Header, Footer def compose(self) -> ComposeResult: yield Header() # ... content ... yield Footer() ``` Footer automatically shows key bindings defined in BINDINGS. ## Custom Widgets Create reusable components: ```python from textual.widget import Widget from textual.widgets import Label, Button class Card(Widget): """A card widget with title and content.""" DEFAULT_CSS = """ Card { width: 30; height: 15; border: round white; padding: 1; } """ def __init__(self, title: str, content: str) -> None: super().__init__() self.title = title self.content = content def compose(self) -> ComposeResult: yield Label(self.title, classes="card-title") yield Label(self.content, classes="card-content") yield Button("Select", id=f"select-{self.title}") ``` ### Render Method For simple custom widgets that just render text: ```python from textual.widget import Widget class FizzBuzz(Widget): def render(self) -> str: return "FizzBuzz!" ```