Skip to content
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
https://github.com/Textualize/textual/issues/1094
- Added Pilot.wait_for_animation
- Added `Widget.move_child` https://github.com/Textualize/textual/issues/1121
- Added a `Label` widget https://github.com/Textualize/textual/issues/1190
- Support lazy-instantiated Screens (callables in App.SCREENS) https://github.com/Textualize/textual/pull/1185

### Changed
Expand Down
1 change: 1 addition & 0 deletions docs/api/label.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: textual.widgets.Label
12 changes: 12 additions & 0 deletions docs/examples/widgets/label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from textual.app import App, ComposeResult
from textual.widgets import Label


class LabelApp(App):
def compose(self) -> ComposeResult:
yield Label("Hello, world!")


if __name__ == "__main__":
app = LabelApp()
app.run()
33 changes: 33 additions & 0 deletions docs/widgets/label.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Label

A widget which displays static text, but which can also contain more complex Rich renderables.

- [ ] Focusable
- [ ] Container

## Example

The example below shows how you can use a `Label` widget to display some text.

=== "Output"

```{.textual path="docs/examples/widgets/label.py"}
```

=== "label.py"

```python
--8<-- "docs/examples/widgets/label.py"
```

## Reactive Attributes

This widget has no reactive attributes.

## Messages

This widget sends no messages.

## See Also

* [Label](../api/label.md) code reference
7 changes: 4 additions & 3 deletions docs/widgets/static.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Static

A widget which displays static content.
Can be used for simple text labels, but can also contain more complex Rich renderables.
Can be used for Rich renderables and can also for the base for other types of widgets.

- [ ] Focusable
- [x] Container
- [ ] Container

## Example

The example below shows how you can use a `Static` widget as a simple text label.
The example below shows how you can use a `Static` widget as a simple text label (but see [Label](./label.md) as a way of displaying text).

=== "Output"

Expand All @@ -32,3 +32,4 @@ This widget sends no messages.
## See Also

* [Static](../api/static.md) code reference
* [Label](./label.md)
16 changes: 8 additions & 8 deletions examples/five_by_five.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from textual.app import App, ComposeResult
from textual.screen import Screen
from textual.widget import Widget
from textual.widgets import Footer, Button, Static
from textual.widgets import Footer, Button, Label
from textual.css.query import DOMQuery
from textual.reactive import reactive
from textual.binding import Binding
Expand All @@ -33,10 +33,10 @@ def compose(self) -> ComposeResult:
Returns:
ComposeResult: The result of composing the help screen.
"""
yield Static(Markdown(Path(__file__).with_suffix(".md").read_text()))
yield Label(Markdown(Path(__file__).with_suffix(".md").read_text()))


class WinnerMessage(Static):
class WinnerMessage(Label):
"""Widget to tell the user they have won."""

MIN_MOVES: Final = 14
Expand Down Expand Up @@ -91,9 +91,9 @@ def compose(self) -> ComposeResult:
ComposeResult: The result of composing the game header.
"""
yield Horizontal(
Static(self.app.title, id="app-title"),
Static(id="moves"),
Static(id="progress"),
Label(self.app.title, id="app-title"),
Label(id="moves"),
Label(id="progress"),
)

def watch_moves(self, moves: int):
Expand All @@ -102,15 +102,15 @@ def watch_moves(self, moves: int):
Args:
moves (int): The number of moves made.
"""
self.query_one("#moves", Static).update(f"Moves: {moves}")
self.query_one("#moves", Label).update(f"Moves: {moves}")

def watch_filled(self, filled: int):
"""Watch the on-count reactive and update when it changes.

Args:
filled (int): The number of cells that are currently on.
"""
self.query_one("#progress", Static).update(f"Filled: {filled}")
self.query_one("#progress", Label).update(f"Filled: {filled}")


class GameCell(Button):
Expand Down
10 changes: 6 additions & 4 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ nav:
- "widgets/footer.md"
- "widgets/header.md"
- "widgets/input.md"
- "widgets/label.md"
- "widgets/static.md"
- "widgets/tree_control.md"
- API:
Expand All @@ -109,6 +110,7 @@ nav:
- "api/footer.md"
- "api/geometry.md"
- "api/header.md"
- "api/label.md"
- "api/message_pump.md"
- "api/message.md"
- "api/pilot.md"
Expand Down Expand Up @@ -185,13 +187,13 @@ plugins:

- blog:
- rss:
match_path: blog/posts/.*
match_path: blog/posts/.*
date_from_meta:
as_creation: date
categories:
- categories
- release
- tags
- tags
- search:
- autorefs:
- mkdocstrings:
Expand All @@ -215,10 +217,10 @@ extra_css:

extra:
social:
- icon: fontawesome/brands/twitter
- icon: fontawesome/brands/twitter
link: https://twitter.com/textualizeio
name: textualizeio on Twitter
- icon: fontawesome/brands/github
- icon: fontawesome/brands/github
link: https://github.com/textualize/textual/
name: Textual on Github
- icon: fontawesome/brands/discord
Expand Down
4 changes: 2 additions & 2 deletions src/textual/cli/previews/borders.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from textual.app import App, ComposeResult
from textual.constants import BORDERS
from textual.widgets import Button, Static
from textual.widgets import Button, Label
from textual.containers import Vertical


Expand Down Expand Up @@ -48,7 +48,7 @@ class BorderApp(App):

def compose(self):
yield BorderButtons()
self.text = Static(TEXT, id="text")
self.text = Label(TEXT, id="text")
yield self.text

def on_button_pressed(self, event: Button.Pressed) -> None:
Expand Down
2 changes: 1 addition & 1 deletion src/textual/cli/previews/colors.css
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ ColorGroup.-active {
}


ColorLabel {
Label {
padding: 0 0 1 0;
content-align: center middle;
color: $text;
Expand Down
8 changes: 2 additions & 6 deletions src/textual/cli/previews/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from textual.containers import Horizontal, Vertical
from textual.design import ColorSystem
from textual.widget import Widget
from textual.widgets import Button, Footer, Static
from textual.widgets import Button, Footer, Static, Label


class ColorButtons(Vertical):
Expand All @@ -28,10 +28,6 @@ class Content(Vertical):
pass


class ColorLabel(Static):
pass


class ColorsView(Vertical):
def compose(self) -> ComposeResult:

Expand All @@ -47,7 +43,7 @@ def compose(self) -> ComposeResult:

for color_name in ColorSystem.COLOR_NAMES:

items: list[Widget] = [ColorLabel(f'"{color_name}"')]
items: list[Widget] = [Label(f'"{color_name}"')]
for level in LEVELS:
color = f"{color_name}-{level}" if level else color_name
item = ColorItem(
Expand Down
10 changes: 5 additions & 5 deletions src/textual/cli/previews/easing.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from textual.reactive import Reactive
from textual.scrollbar import ScrollBarRender
from textual.widget import Widget
from textual.widgets import Button, Footer, Static, Input
from textual.widgets import Button, Footer, Label, Input

VIRTUAL_SIZE = 100
WINDOW_SIZE = 10
Expand All @@ -27,7 +27,7 @@ class Bar(Widget):
animation_running = Reactive(False)

DEFAULT_CSS = """

Bar {
background: $surface;
color: $error;
Expand All @@ -37,7 +37,7 @@ class Bar(Widget):
background: $surface;
color: $success;
}

"""

def watch_animation_running(self, running: bool) -> None:
Expand Down Expand Up @@ -67,14 +67,14 @@ def compose(self) -> ComposeResult:
self.animated_bar.position = START_POSITION
duration_input = Input("1.0", placeholder="Duration", id="duration-input")

self.opacity_widget = Static(
self.opacity_widget = Label(
f"[b]Welcome to Textual![/]\n\n{TEXT}", id="opacity-widget"
)

yield EasingButtons()
yield Vertical(
Horizontal(
Static("Animation Duration:", id="label"), duration_input, id="inputs"
Label("Animation Duration:", id="label"), duration_input, id="inputs"
),
Horizontal(
self.animated_bar,
Expand Down
2 changes: 2 additions & 0 deletions src/textual/widgets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from ._directory_tree import DirectoryTree
from ._footer import Footer
from ._header import Header
from ._label import Label
from ._placeholder import Placeholder
from ._pretty import Pretty
from ._static import Static
Expand All @@ -30,6 +31,7 @@
"DirectoryTree",
"Footer",
"Header",
"Label",
"Placeholder",
"Pretty",
"Static",
Expand Down
1 change: 1 addition & 0 deletions src/textual/widgets/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ from ._checkbox import Checkbox as Checkbox
from ._directory_tree import DirectoryTree as DirectoryTree
from ._footer import Footer as Footer
from ._header import Header as Header
from ._label import Label as Label
from ._placeholder import Placeholder as Placeholder
from ._pretty import Pretty as Pretty
from ._static import Static as Static
Expand Down
7 changes: 7 additions & 0 deletions src/textual/widgets/_label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Provides a simple Label widget."""

from ._static import Static


class Label(Static):
"""A simple label widget for displaying text-oriented renderables."""