diff --git a/CHANGELOG.md b/CHANGELOG.md index fd2533a91..cc1be2443 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## Unreleased +## [0.16.0] - 2023-03-22 ### Added - Added `parser_factory` argument to `Markdown` and `MarkdownViewer` constructors https://github.com/Textualize/textual/pull/2075 @@ -629,6 +629,7 @@ https://textual.textualize.io/blog/2022/11/08/version-040/#version-040 - New handler system for messages that doesn't require inheritance - Improved traceback handling +[0.16.0]: https://github.com/Textualize/textual/compare/v0.15.1...v0.16.0 [0.15.1]: https://github.com/Textualize/textual/compare/v0.15.0...v0.15.1 [0.15.0]: https://github.com/Textualize/textual/compare/v0.14.0...v0.15.0 [0.14.0]: https://github.com/Textualize/textual/compare/v0.13.0...v0.14.0 diff --git a/docs/blog/images/border-title.svg b/docs/blog/images/border-title.svg new file mode 100644 index 000000000..d2391f90e --- /dev/null +++ b/docs/blog/images/border-title.svg @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BorderApp + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +ascii +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +none +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔════════════════════════════════double════════════════════════════════ +hidden +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔I must not fear. +blankFear is the mind-killer. +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Fear is the little-death that brings total obliteration. +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔I will face my fear. +roundI will permit it to pass over me and through me. +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁And when it has gone past, I will turn the inner eye to see its  +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔path. +solid▆▆Where the fear has gone there will be nothing. Only I will  +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁remain. +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +double +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁════════════════════════════════════════════════════════════════════════ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +dashed +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +heavy +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + diff --git a/docs/blog/posts/release0-16-0.md b/docs/blog/posts/release0-16-0.md new file mode 100644 index 000000000..add6cdf46 --- /dev/null +++ b/docs/blog/posts/release0-16-0.md @@ -0,0 +1,66 @@ +--- +draft: false +date: 2023-03-22 +categories: + - Release +title: "Textual 0.16.0 adds TabbedContent and border titles" +authors: + - willmcgugan +--- + +# Textual 0.16.0 adds TabbedContent and border titles + +Textual 0.16.0 lands 9 days after the previous release. We have some new features to show you. + + + +There are two highlights in this release. In no particular order, the first is [TabbedContent](../../widgets/tabbed_content.md) which uses a row of *tabs* to navigate content. You will have likely encountered this UI in the desktop and web. I think in Windows they are known as "Tabbed Dialogs". + +This widget combines existing [Tabs](../../widgets/tabs.md) and [ContentSwitcher](../../api/content_switcher.md) widgets and adds an expressive interface for composing. Here's a trivial example to use content tabs to navigate a set of three markdown documents: + +```python +def compose(self) -> ComposeResult: + with TabbedContent("Leto", "Jessica", "Paul"): + yield Markdown(LETO) + yield Markdown(JESSICA) + yield Markdown(PAUL) +``` + +Here's an example of the UI you can create with this widget (note the nesting)! + +```{.textual path="docs/examples/widgets/tabbed_content.py" press="j"} +``` + + +## Border titles + +The second highlight is a frequently requests feature (FRF?). Widgets now have the two new string properties, `border_title` and `border_subtitle`, which will be displayed within the widget's border. + +You can set the alignment of these titles via [`border-title-align`](../../styles/border_title_align.md) and [`border-subtitle-align`](../../styles/border_subtitle_align.md). Titles may contain [Console Markup](https://rich.readthedocs.io/en/latest/markup.html), so you can add additional color and style to the labels. + +Here's an example of a widget with a title: + +
+--8<-- "docs/blog/images/border-title.svg" +
+ +BTW the above is a command you can run to see the various border styles you can apply to widgets. + +``` +textual borders +``` + +## Container changes + +!!! warning "Breaking change" + + If you have an app that uses any container classes, you should read this section. + +We've made a change to containers in this release. Previously all containers had *auto* scrollbars, which means that any container would scroll if its children didn't fit. With nested layouts, it could be tricky to understand exactly which containers were scrolling. In 0.16.0 we split containers in to scrolling and non-scrolling versions. So `Horizontal` will now *not* scroll by default, but `HorizontalScroll` will have automatic scrollbars. + + +## What else? + +As always, see the [release notes](https://github.com/Textualize/textual/releases/tag/v0.16.0) for the full details on this update. + +If you want to talk about this update or anything else Textual related, join us on our [Discord server](https://discord.gg/Enf6Z3qhVr). diff --git a/docs/styles/border_subtitle_align.md b/docs/styles/border_subtitle_align.md index 3aeb7c974..73108892d 100644 --- a/docs/styles/border_subtitle_align.md +++ b/docs/styles/border_subtitle_align.md @@ -1,6 +1,6 @@ # Border-subtitle-align -The `border-subtitle-align` sets the horizontal alignment for the border subtitle. +The `border-subtitle-align` rule sets the horizontal alignment for the border subtitle. ## Syntax diff --git a/docs/styles/border_title_align.md b/docs/styles/border_title_align.md index 8a7608d63..01b55bad8 100644 --- a/docs/styles/border_title_align.md +++ b/docs/styles/border_title_align.md @@ -1,6 +1,6 @@ # Border-title-align -The `border-title-align` sets the horizontal alignment for the border title. +The `border-title-align` rule sets the horizontal alignment for the border title. ## Syntax diff --git a/pyproject.toml b/pyproject.toml index 42dbb358f..149433271 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "textual" -version = "0.15.1" +version = "0.16.0" homepage = "https://github.com/Textualize/textual" description = "Modern Text User Interface framework" authors = ["Will McGugan "] diff --git a/src/textual/cli/previews/borders.py b/src/textual/cli/previews/borders.py index 09dbcaab4..cebaac092 100644 --- a/src/textual/cli/previews/borders.py +++ b/src/textual/cli/previews/borders.py @@ -46,6 +46,7 @@ class BorderApp(App): height: auto; background: $panel; color: $text; + border-title-align: center; } """ @@ -53,9 +54,11 @@ class BorderApp(App): yield BorderButtons() self.text = Label(TEXT, id="text") self.text.shrink = True + self.text.border_title = "solid" yield self.text def on_button_pressed(self, event: Button.Pressed) -> None: + self.text.border_title = event.button.id self.text.styles.border = ( event.button.id, self.stylesheet._variables["secondary"], diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 6aa03f848..a12d9621b 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -729,141 +729,141 @@ font-weight: 700; } - .terminal-1117153209-matrix { + .terminal-3364910686-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1117153209-title { + .terminal-3364910686-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1117153209-r1 { fill: #05080f } - .terminal-1117153209-r2 { fill: #e1e1e1 } - .terminal-1117153209-r3 { fill: #c5c8c6 } - .terminal-1117153209-r4 { fill: #1e2226;font-weight: bold } - .terminal-1117153209-r5 { fill: #35393d } - .terminal-1117153209-r6 { fill: #454a50 } - .terminal-1117153209-r7 { fill: #fea62b } - .terminal-1117153209-r8 { fill: #e2e3e3;font-weight: bold } - .terminal-1117153209-r9 { fill: #000000 } - .terminal-1117153209-r10 { fill: #e2e3e3 } - .terminal-1117153209-r11 { fill: #14191f } + .terminal-3364910686-r1 { fill: #05080f } + .terminal-3364910686-r2 { fill: #e1e1e1 } + .terminal-3364910686-r3 { fill: #c5c8c6 } + .terminal-3364910686-r4 { fill: #1e2226;font-weight: bold } + .terminal-3364910686-r5 { fill: #35393d } + .terminal-3364910686-r6 { fill: #454a50 } + .terminal-3364910686-r7 { fill: #fea62b } + .terminal-3364910686-r8 { fill: #e2e3e3;font-weight: bold } + .terminal-3364910686-r9 { fill: #000000 } + .terminal-3364910686-r10 { fill: #e2e3e3 } + .terminal-3364910686-r11 { fill: #14191f } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - BorderApp + BorderApp - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ascii - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔+----------------------------------------------+ - none|| - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|| - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔|I must not fear.| - hidden|Fear is the mind-killer.| - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|Fear is the little-death that brings | - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔|total obliteration.| - blank|I will face my fear.| - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|I will permit it to pass over me and | - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁|through me.| - round|And when it has gone past, I will turn| - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|the inner eye to see its path.| - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔|Where the fear has gone there will be | - solid|nothing. Only I will remain.| - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|| - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔|| - double+----------------------------------------------+ - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - dashed - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ascii + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔+-------------------ascii--------------------+ + none|| + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|| + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔|I must not fear.| + hidden|Fear is the mind-killer.| + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|Fear is the little-death that brings | + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔|total obliteration.| + blank|I will face my fear.| + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|I will permit it to pass over me and | + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁|through me.| + round|And when it has gone past, I will turn| + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|the inner eye to see its path.| + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔|Where the fear has gone there will be | + solid|nothing. Only I will remain.| + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁|| + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔|| + double+----------------------------------------------+ + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + dashed + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁