From c881a9657fe3c967139c07ce45673ece6a2e7221 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Wed, 16 Nov 2022 15:03:24 +0000 Subject: [PATCH 1/9] Add a Label widget For the moment this does nothing more than inherit from a Static; but what it does do is make it easier for someone to add text to their application and to style it by styling all the Labels. Before now it would be common to use a Static but if you try and style (or query) all Statics, you'd also get things like Buttons, which inherit from Static. See #1190 --- CHANGELOG.md | 1 + examples/five_by_five.py | 16 ++++++++-------- src/textual/widgets/__init__.py | 2 ++ src/textual/widgets/__init__.pyi | 1 + src/textual/widgets/_label.py | 7 +++++++ 5 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 src/textual/widgets/_label.py diff --git a/CHANGELOG.md b/CHANGELOG.md index dd2fdb3318..39bd22dc67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 ### Changed diff --git a/examples/five_by_five.py b/examples/five_by_five.py index 20bbea80f0..f4574a8a44 100644 --- a/examples/five_by_five.py +++ b/examples/five_by_five.py @@ -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 @@ -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 @@ -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): @@ -102,7 +102,7 @@ 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. @@ -110,7 +110,7 @@ def watch_filled(self, filled: int): 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): diff --git a/src/textual/widgets/__init__.py b/src/textual/widgets/__init__.py index c42b011a9c..8cbcb9f3b8 100644 --- a/src/textual/widgets/__init__.py +++ b/src/textual/widgets/__init__.py @@ -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 @@ -30,6 +31,7 @@ "DirectoryTree", "Footer", "Header", + "Label", "Placeholder", "Pretty", "Static", diff --git a/src/textual/widgets/__init__.pyi b/src/textual/widgets/__init__.pyi index 5ceb018352..57f87df82e 100644 --- a/src/textual/widgets/__init__.pyi +++ b/src/textual/widgets/__init__.pyi @@ -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 diff --git a/src/textual/widgets/_label.py b/src/textual/widgets/_label.py new file mode 100644 index 0000000000..a3adba462d --- /dev/null +++ b/src/textual/widgets/_label.py @@ -0,0 +1,7 @@ +"""Provides a simple Label widget.""" + +from ._static import Static + + +class Label(Static): + """A simple label widget for displaying text-oriented rendenrables.""" From 22863148ef628d9c3d9dbe1d8527f98b2e156e2f Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Wed, 16 Nov 2022 15:09:27 +0000 Subject: [PATCH 2/9] Update src/textual/widgets/_label.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com> --- src/textual/widgets/_label.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/textual/widgets/_label.py b/src/textual/widgets/_label.py index a3adba462d..df519ae4f1 100644 --- a/src/textual/widgets/_label.py +++ b/src/textual/widgets/_label.py @@ -4,4 +4,4 @@ class Label(Static): - """A simple label widget for displaying text-oriented rendenrables.""" + """A simple label widget for displaying text-oriented renderables.""" From 67386478effd65a52ffea7f1207eab86d477a0d1 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 17 Nov 2022 10:14:55 +0000 Subject: [PATCH 3/9] Trailing whitespace squishing --- mkdocs.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index e7b4e5f9e4..8bf9c7f34d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -185,13 +185,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: @@ -215,10 +215,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 From 8a6d21da5eefe751ef8c6e057e323a28c2a1579a Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 17 Nov 2022 10:15:35 +0000 Subject: [PATCH 4/9] Add the basics of Label docs for the manual --- docs/api/label.md | 1 + docs/examples/widgets/label.py | 12 ++++++++++++ docs/widgets/label.md | 33 +++++++++++++++++++++++++++++++++ docs/widgets/static.md | 5 +++-- mkdocs.yml | 2 ++ 5 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 docs/api/label.md create mode 100644 docs/examples/widgets/label.py create mode 100644 docs/widgets/label.md diff --git a/docs/api/label.md b/docs/api/label.md new file mode 100644 index 0000000000..eee506a2c7 --- /dev/null +++ b/docs/api/label.md @@ -0,0 +1 @@ +::: textual.widgets.Label diff --git a/docs/examples/widgets/label.py b/docs/examples/widgets/label.py new file mode 100644 index 0000000000..43a50bb104 --- /dev/null +++ b/docs/examples/widgets/label.py @@ -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() diff --git a/docs/widgets/label.md b/docs/widgets/label.md new file mode 100644 index 0000000000..d4c22feac9 --- /dev/null +++ b/docs/widgets/label.md @@ -0,0 +1,33 @@ +# Label + +A widget which displays static text, but which can also contain more complex Rich renderables. + +- [ ] Focusable +- [x] 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 diff --git a/docs/widgets/static.md b/docs/widgets/static.md index 342e2daf7e..4d9fc994ca 100644 --- a/docs/widgets/static.md +++ b/docs/widgets/static.md @@ -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 ## 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" @@ -32,3 +32,4 @@ This widget sends no messages. ## See Also * [Static](../api/static.md) code reference +* [Label](./label.md) diff --git a/mkdocs.yml b/mkdocs.yml index 8bf9c7f34d..332298e5d3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -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: @@ -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" From f1be4e21aa147d6e975aa0f1017f7b214a07b297 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 17 Nov 2022 11:34:04 +0000 Subject: [PATCH 5/9] Move the labels in the easing preview away from Static and into Label --- src/textual/cli/previews/easing.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/textual/cli/previews/easing.py b/src/textual/cli/previews/easing.py index 6edcdb82a1..b81290302f 100644 --- a/src/textual/cli/previews/easing.py +++ b/src/textual/cli/previews/easing.py @@ -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 @@ -27,7 +27,7 @@ class Bar(Widget): animation_running = Reactive(False) DEFAULT_CSS = """ - + Bar { background: $surface; color: $error; @@ -37,7 +37,7 @@ class Bar(Widget): background: $surface; color: $success; } - + """ def watch_animation_running(self, running: bool) -> None: @@ -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, From 5a1b436e918809f7c94c1fa03f854d6c8245bd3c Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 17 Nov 2022 11:36:07 +0000 Subject: [PATCH 6/9] Move the label in the border preview away from Static and into Label --- src/textual/cli/previews/borders.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/textual/cli/previews/borders.py b/src/textual/cli/previews/borders.py index 6133434436..e5d453d86f 100644 --- a/src/textual/cli/previews/borders.py +++ b/src/textual/cli/previews/borders.py @@ -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 @@ -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: From 5dcbd07f0878db2b7ebf02f833194ee15904b8df Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 17 Nov 2022 11:42:04 +0000 Subject: [PATCH 7/9] Move the labels in the colour preview away from Static and into Label --- src/textual/cli/previews/colors.css | 2 +- src/textual/cli/previews/colors.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/textual/cli/previews/colors.css b/src/textual/cli/previews/colors.css index 3af8eabd7e..657a8aabbd 100644 --- a/src/textual/cli/previews/colors.css +++ b/src/textual/cli/previews/colors.css @@ -68,7 +68,7 @@ ColorGroup.-active { } -ColorLabel { +Label { padding: 0 0 1 0; content-align: center middle; color: $text; diff --git a/src/textual/cli/previews/colors.py b/src/textual/cli/previews/colors.py index 56ac645c6b..e25c70d7fe 100644 --- a/src/textual/cli/previews/colors.py +++ b/src/textual/cli/previews/colors.py @@ -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): @@ -28,10 +28,6 @@ class Content(Vertical): pass -class ColorLabel(Static): - pass - - class ColorsView(Vertical): def compose(self) -> ComposeResult: @@ -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( From 28bc889f7b0fbadfc9d194b40e84a537b7b57bfd Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 17 Nov 2022 20:24:39 +0000 Subject: [PATCH 8/9] Correct the container status of Static in the docs See https://github.com/Textualize/textual/pull/1193#discussion_r1025466567 --- docs/widgets/static.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/widgets/static.md b/docs/widgets/static.md index 4d9fc994ca..c8e41606f2 100644 --- a/docs/widgets/static.md +++ b/docs/widgets/static.md @@ -4,7 +4,7 @@ A widget which displays static content. Can be used for Rich renderables and can also for the base for other types of widgets. - [ ] Focusable -- [x] Container +- [ ] Container ## Example From c9484c64cacd294e297b98e185a99c0dad7c8193 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Thu, 17 Nov 2022 20:25:02 +0000 Subject: [PATCH 9/9] Correct the container status of Label in the docs See https://github.com/Textualize/textual/pull/1193#discussion_r1025466567 --- docs/widgets/label.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/widgets/label.md b/docs/widgets/label.md index d4c22feac9..96a31bcc60 100644 --- a/docs/widgets/label.md +++ b/docs/widgets/label.md @@ -3,7 +3,7 @@ A widget which displays static text, but which can also contain more complex Rich renderables. - [ ] Focusable -- [x] Container +- [ ] Container ## Example