Textual: Modern Text User Interface Framework

raw JSON →
8.2.0 verified Tue May 12 auth: no python install: verified quickstart: verified

Textual is a Python framework for building sophisticated user interfaces with a simple API. The current version is 8.2.0, released on March 27, 2026. It follows a regular release cadence, with updates approximately every few weeks.

pip install textual
error ModuleNotFoundError: No module named 'textual'
cause The 'textual' library is not installed in the current Python environment.
fix
pip install textual
error ImportError: cannot import name 'Button' from 'textual'
cause Widgets like Button are located within the 'textual.widgets' submodule, not directly in the top-level 'textual' package.
fix
from textual.widgets import Button
error TypeError: Button.__init__() missing 1 required positional argument: 'label'
cause The Button widget requires a string 'label' argument to be provided during its instantiation.
fix
Button('Click Me')
error AttributeError: 'Button' object has no attribute 'on_click'
cause Textual uses a reactive event system where event handlers are defined as methods (e.g., 'on_button_pressed') in the App or Screen class, rather than being directly assigned to a widget attribute.
fix
Define a method in your App or Screen class: def on_button_pressed(self, event: Button.Pressed): ...
breaking In version 8.0.0, 'Select.BLANK' was renamed to 'Select.NULL' to avoid a name clash.
fix Update code to use 'Select.NULL' instead of 'Select.BLANK'.
deprecated The 'App.PAUSE_GC_ON_SCROLL_' attribute is experimental and may be removed in future versions.
fix Avoid using 'App.PAUSE_GC_ON_SCROLL_' in production code.
breaking The `on_resize()` function or method signature has changed and now requires a 'height' argument.
fix Update calls to `on_resize()` to include the `height` argument, or modify its definition to match the new signature if you are implementing it.
breaking The `MyApp.on_resize()` method is being called without a required 'height' argument.
fix Update the signature of `MyApp.on_resize()` to accept a 'height' argument, or ensure it is called with the 'height' argument if the signature is already correct according to the expected API.
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.79s 37.6M
3.10 slim (glibc) - - 0.41s 38M
3.11 alpine (musl) - - 0.86s 41.9M
3.11 slim (glibc) - - 0.70s 42M
3.12 alpine (musl) - - 0.95s 33.2M
3.12 slim (glibc) - - 0.94s 34M
3.13 alpine (musl) - - 0.92s 32.9M
3.13 slim (glibc) - - 0.91s 33M
3.9 alpine (musl) - - 0.49s 36.7M
3.9 slim (glibc) - - 0.44s 37M

A minimal Textual application with a header, footer, and placeholder.

import os
from textual.app import App
from textual.widgets import Header, Footer, Placeholder

class MyApp(App):
    async def on_mount(self) -> None:
        self.set_interval(1, self.update)

    async def update(self) -> None:
        pass

    async def on_resize(self, width: int, height: int) -> None:
        pass

if __name__ == '__main__':
    app = MyApp()
    app.run()