Modern Text User Interface framework for building cross-platform terminal and web applications with Python
Overall
score
93%
Essential application framework components for building Textual applications, including the main App class, base Widget class, screen management, and decorators for event handling and background tasks.
The App class is the foundation of every Textual application, managing the event loop, screen stack, styling, and overall application lifecycle.
class App:
"""
The main application class.
Generic type parameter for return value: App[ReturnType]
"""
def __init__(self, **kwargs):
"""
Initialize the application.
Parameters:
- css_path: str | list[str] - Path(s) to CSS files for styling
- watch_css: bool - Automatically reload CSS files during development
"""
def run(self) -> None:
"""Run the application synchronously."""
async def run_async(self) -> None:
"""Run the application asynchronously."""
def push_screen(self, screen: Screen) -> None:
"""
Push a new screen onto the screen stack.
Parameters:
- screen: Screen instance to display
"""
def pop_screen(self) -> Screen:
"""Pop the current screen from the stack and return it."""
def exit(self, result=None) -> None:
"""
Exit the application.
Parameters:
- result: Optional return value for the application
"""
def compose(self) -> ComposeResult:
"""Compose the application's default screen widgets."""
def on_mount(self) -> None:
"""Called when the application starts."""
def on_ready(self) -> None:
"""Called when the application is ready to receive events."""
# Properties
screen_stack: list[Screen]
title: str
sub_title: str
css_path: str | list[str] | NoneThe Widget class is the base for all UI components in Textual, providing composition, rendering, lifecycle management, and event handling capabilities.
class Widget:
"""
Base class for all widgets.
"""
def __init__(self, **kwargs):
"""
Initialize the widget.
Parameters:
- name: str - Widget name for CSS targeting
- id: str - Unique identifier for the widget
- classes: str - CSS classes for styling
- disabled: bool - Whether the widget is disabled
"""
def compose(self) -> ComposeResult:
"""
Compose child widgets.
Returns:
Iterator of child widgets
"""
def render(self) -> RenderableType:
"""
Render the widget content.
Returns:
Rich renderable object
"""
def on_mount(self) -> None:
"""Called when widget is added to the DOM."""
def on_unmount(self) -> None:
"""Called when widget is removed from the DOM."""
def refresh(self, *, repaint: bool = True, layout: bool = False) -> None:
"""
Refresh the widget.
Parameters:
- repaint: bool - Whether to repaint the widget
- layout: bool - Whether to recalculate layout
"""
def remove(self) -> None:
"""Remove the widget from its parent."""
def focus(self, scroll_visible: bool = True) -> None:
"""
Give focus to the widget.
Parameters:
- scroll_visible: bool - Scroll to make widget visible
"""
def blur(self) -> None:
"""Remove focus from the widget."""
def scroll_to(self, x: int = None, y: int = None, *, animate: bool = True) -> None:
"""
Scroll to a position.
Parameters:
- x: int - X coordinate to scroll to
- y: int - Y coordinate to scroll to
- animate: bool - Whether to animate the scroll
"""
# Properties
id: str | None
name: str | None
classes: set[str]
disabled: bool
parent: Widget | None
children: list[Widget]
styles: Styles
has_focus: boolScreen classes represent full-screen views that can be pushed onto a screen stack, enabling complex navigation patterns and modal dialogs.
class Screen:
"""
A screen is a special widget that represents the entire terminal.
Generic type parameter for return value: Screen[ScreenResultType]
"""
def __init__(self, **kwargs):
"""
Initialize the screen.
Parameters:
- name: str - Screen name
- id: str - Unique identifier
- classes: str - CSS classes
"""
def compose(self) -> ComposeResult:
"""Compose the screen's widgets."""
def dismiss(self, result=None) -> None:
"""
Dismiss the screen with an optional result.
Parameters:
- result: Value to return when screen is dismissed
"""
# Properties
title: str
sub_title: str
auto_focus: str | None
class ModalScreen(Screen):
"""A modal screen that doesn't cover the entire terminal."""
passDecorators for handling events and creating background tasks in Textual applications.
def on(*selectors, **kwargs):
"""
Decorator for handling events with CSS selector support.
Parameters:
- *selectors: CSS selectors to match against event targets
- **kwargs: Additional event filtering options
Usage:
@on(Button.Pressed, "#my-button")
def handle_button(self, event):
pass
"""
def work(exclusive: bool = False, thread: bool = False):
"""
Decorator for creating background tasks.
Parameters:
- exclusive: bool - Whether to cancel other workers when starting
- thread: bool - Whether to run in a separate thread
Usage:
@work
async def background_task(self):
pass
"""ComposeResult = Iterator[Widget]
"""Type alias for widget composition results."""
class AwaitMount:
"""Awaitable for widget mounting completion."""
def __await__(self):
"""Wait for widget to be mounted."""
class MountError(Exception):
"""Raised when widget mounting fails."""
class ScreenStackError(Exception):
"""Raised when screen stack operations fail."""from textual.app import App
from textual.widgets import Static
from textual.containers import Container
class MyApp(App):
"""A simple Textual application."""
CSS_PATH = "app.css" # Optional CSS file
def compose(self):
"""Create the UI."""
yield Container(
Static("Hello World!"),
id="main-container"
)
def on_mount(self):
"""Set up the application."""
self.title = "My Application"
self.sub_title = "v1.0.0"
# Run the application
if __name__ == "__main__":
MyApp().run()from textual.app import App
from textual.screen import Screen
from textual.widgets import Button
class SecondScreen(Screen):
"""A secondary screen."""
def compose(self):
yield Button("Go Back", id="back")
def on_button_pressed(self, event):
if event.button.id == "back":
self.dismiss("result from second screen")
class MainApp(App):
def compose(self):
yield Button("Go to Second Screen", id="goto")
def on_button_pressed(self, event):
if event.button.id == "goto":
self.push_screen(SecondScreen())from textual.app import App
from textual.widgets import Button, Input
from textual import on, work
class EventApp(App):
def compose(self):
yield Input(placeholder="Type something...", id="input")
yield Button("Process", id="process")
@on(Button.Pressed, "#process")
def handle_process_button(self, event):
"""Handle the process button."""
input_widget = self.query_one("#input", Input)
self.process_text(input_widget.value)
@work
async def process_text(self, text: str):
"""Background task to process text."""
# Simulate processing
await asyncio.sleep(1)
self.log(f"Processed: {text}")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