Textual

A modern framework for building TUI applications in Python. It adopts CSS, DOM, and reactive programming models, bringing web development concepts to the terminal environment.

pythontuiframeworkcssdomreactive

GitHub Overview

Textualize/textual

The lean application framework for Python. Build sophisticated user interfaces with a simple Python API. Run your apps in the terminal and a web browser.

Stars30,007
Watchers174
Forks932
Created:April 8, 2021
Language:Python
License:MIT License

Topics

cliframeworkpythonrichterminaltui

Star History

Textualize/textual Star History
Data as of: 7/25/2025, 06:22 AM

Framework

Textual

Overview

Textual is an innovative framework for building modern TUI (Text-based User Interface) applications in Python. It brings web development concepts (CSS, DOM, reactive programming) to the terminal environment, enabling intuitive and high-performance TUI application development.

Details

Textual was developed by Textualize in 2021, providing a new paradigm for Python TUI development. Unlike traditional curses-based approaches, it adopts modern web development best practices.

Key Features

  • CSS-like Styling: Customize application appearance with CSS-like syntax
  • DOM Structure: Manage UI hierarchy with HTML-like DOM (Document Object Model)
  • Reactive Attributes: Automatic UI updates when data changes
  • Rich Widget Set: Diverse built-in widgets including buttons, inputs, tables, trees
  • Event-Driven: Message-based event system
  • Animations: Smooth animation effects
  • Theme System: Customizable themes and color schemes
  • Web Deployment: Terminal apps can also run in web browsers

Architecture

Textual's architecture consists of the following main components:

  • App: Application entry point
  • Screen: Special Widget representing the entire screen
  • Widget: Base class for UI elements
  • MessagePump: Foundation for event processing
  • Compositor: Rendering system
  • CSS Engine: Styling engine

Pros and Cons

Pros

  • Leverage modern web development knowledge
  • High-performance rendering and animations
  • Rich documentation and community support
  • Cross-platform support (Linux, macOS, Windows)
  • Can run in web browsers
  • Rich set of built-in widgets
  • Intuitive CSS-like styling
  • Powerful development tools (debug console, live reload, etc.)

Cons

  • Limited learning resources as a relatively new framework
  • Limited track record for large-scale applications
  • Dependency on Rich library
  • May be feature-heavy for lightweight applications

Key Links

Code Example

from textual.app import App, ComposeResult
from textual.containers import Container
from textual.widgets import Button, Header, Footer, Static

class CounterApp(App):
    \"\"\"A simple counter app.\"\"\"
    
    CSS_PATH = "counter.tcss"
    
    def __init__(self):
        super().__init__()
        self.counter = 0
    
    def compose(self) -> ComposeResult:
        \"\"\"Create child widgets for the app.\"\"\"
        yield Header()
        yield Footer()
        yield Container(
            Static(f"Count: {self.counter}", id="counter"),
            Button("Increment", id="increment"),
            Button("Decrement", id="decrement"),
            id="app-grid",
        )
    
    def on_button_pressed(self, event: Button.Pressed) -> None:
        \"\"\"Event handler called when a button is pressed.\"\"\"
        if event.button.id == "increment":
            self.counter += 1
        elif event.button.id == "decrement":
            self.counter -= 1
        
        # Update the counter display
        counter_widget = self.query_one("#counter", Static)
        counter_widget.update(f"Count: {self.counter}")

if __name__ == "__main__":
    app = CounterApp()
    app.run()

CSS file (counter.tcss):

#app-grid {
    display: grid;
    grid-size: 1 3;
    grid-rows: 1fr;
    margin: 1 2;
    min-height: 0;
}

#counter {
    content-align: center middle;
    text-style: bold;
}

Button {
    margin: 1 2;
}