Textual

repository·main·Indexed 12 days ago

https://github.com/textualize/textual

A modern Python framework for building cross-platform user interfaces for the terminal or web browser. Textual combines asynchronous execution with web-inspired development patterns, including TCSS (Textual Cascading Style Sheets) for styling and a declarative layout system using a compose() method. Version 8.2.8 includes features such as a built-in command palette, a Dev Console for debugging, and support for Rich-compatible renderables.

Tokens
135.6K
Snippets
586
Records
792
Agent score
99%

What's inside Textual

  1. What is Textual?

    main

    Textual is a Rapid Application Development (RAD) framework for Python. It allows developers to build sophisticated user interfaces using a simple Python API.

    Key features include:

    • Cross-platform: Runs on Windows, macOS, and Linux.
    • Low requirements: Can run on single-board computers (e.g., Raspberry Pi).
    • Remote capability: Apps can be run over SSH.
    • Web support: Apps can be run in a web browser using textual-serve.
    • CLI Integration: Apps are designed to be launched and run from the command prompt.
    • Open Source: Licensed under the MIT license.
  2. What is Textual Web?

    main

    Textual Web is a tool that converts a Textual-powered TUI (Terminal User Interface) into a web application. It allows you to publish Textual apps to the web, making them accessible via a URL.

    Key features include:

    • No Socket Server Required: It works without creating a local socket server, meaning you don't need to configure firewalls or ports to share your applications.
    • Low Barrier to Entry: Developers can build web applications using only Python proficiency, without needing experience with a traditional web stack.
    • Portability: Apps can run anywhere with an outgoing internet connection.

    Note: Textual Web is currently in public beta. Future updates aim to provide PWA (Progressive Web App) support and expose Web platform APIs (like notifications and file system access) directly through Python code.

  3. Use the Input widget for single-line text entry

    main

    The Input widget is a focusable, single-line text input component. It can be used to collect various types of data, from plain text to numbers, and supports features like character restriction, maximum length, and validation.

    To use it, import Input from textual.widgets and add it to your application. By default, it has a border; you can remove it via CSS using border: none; to adjust spacing.

    ```python
    from textual.widgets import Input
    
    # Basic usage
    input = Input(placeholder="Enter text...")
    ```埋
  4. Explore Textual Widgets

    main

    Textual provides a wide variety of built-in widgets for building Terminal User Interfaces (TUIs). These include input controls (Button, Checkbox, Input, Select, Switch), data display widgets (DataTable, Digits, ListView, Sparkline), and layout/navigation widgets (Header, Footer, Tabs, ContentSwitcher).

    Note that Textual is a TUI framework; all widgets run within the terminal environment.

  5. Supported Markdown features in Textual

    main

    Textual supports a wide range of Markdown syntax for rendering rich text within terminal applications. Supported features include:

    • Headers: Levels 1 through 6 (# to ######).
    • Typography:
      • Emphasis: Rendered with *asterisks*.
      • Strong: Rendered with **double asterisks**.
      • Strikethrough: Rendered with ~~two tildes~~.
      • Inline code: Rendered with backticks.
    • Structural Elements:
      • Horizontal rules: Created with three dashes (---).
      • Lists: Both ordered (1.) and unordered (-) lists, including nested levels.
      • Quotes: Introduced with a chevron (>), supporting nested quotes.
    • Advanced Elements:
      • Fenced Code Blocks: Introduced with triple backticks (```) and optional language parsers (e.g., ```python). These render in sub-widgets with syntax highlighting and indent guides.
      • Tables: Rendered using Rich table formatting.
  6. Use the SelectionList widget

    main

    The SelectionList is a focusable widget used to display a vertical list of selectable options. Each option consists of a prompt (which can be Rich Text) and an associated unique value. It is a Generic widget, allowing you to specify the type of the selection values using Python typing.

    selections = [("First", 1), ("Second", 2)]
    my_selection_list: SelectionList[int] = SelectionList(*selections)
  7. What is a widget and how to create custom widgets

    main

    A widget is a UI component responsible for managing a rectangular region of the screen. Every widget runs in its own asyncio task and can respond to events.

    To create a custom widget, import and extend the Widget base class (or one of its subclasses) and implement the render() method. The render() method returns the content to be displayed in the widget's content area. You can use content markup (e.g., [b]text[/]) within the returned content to apply styles.

    from textual.widget import Widget
    
    class MyGreeting(Widget):
        def render(self):
            return "[b]Hello[/] World"
  8. What is a screen and how to create one

    main

    Screens are containers for widgets that occupy the full dimensions of the terminal. While an app can have many screens, only one is active at a time. Textual creates a default screen implicitly in the App class; any widgets you mount or compose without changing the screen will be added to this default screen.

    To create a custom screen, extend the textual.screen.Screen class. You can style screens using TCSS, but you cannot modify their dimensions as they are always terminal-sized.

    from textual.screen import Screen
    
    class MyCustomScreen(Screen):
        def compose(self):
            yield Label("Hello from my custom screen!")
  9. Understand text-overflow values

    main

    The text-overflow property determines the visual treatment of text that overflows its container (often occurring when text-wrap is disabled or a single word is too wide).

    Supported values:

    • clip: The overflowing portion of the text is simply removed from the output.
    • fold: The overflowing text wraps onto subsequent lines. Note that fold does not necessarily respect word boundaries, which may result in words being broken across lines.
    • ellipsis: The text is truncated, and the last visible character is replaced with an ellipsis (...), signaling to the user that more text exists.
  10. Use the Line API for high-performance widgets

    main

    When a widget returns Rich renderables, Textual redraws the entire widget on every update or size change. For large widgets (like a DataTable) or those that update frequently, this can cause lag.

    The Line API allows you to update specific portions of a widget (as small as a single character) without a full redraw, significantly improving responsiveness.

    To implement the Line API, instead of overriding render(), you must implement the render_line(y: int) method. This method is called by Textual for every row of characters in the widget. It should return a Strip object representing that specific line.

    from textual.widget import Widget
    from textual.strip import Strip
    
    class MyLineWidget(Widget):
        def render_line(self, y: int) -> Strip:
            # Return a Strip for the requested row 'y'
            return Strip(Segment("Hello", Style(bold=True)))