diff --git a/CHANGELOG.md b/CHANGELOG.md index c09945c846..6de8ba68fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `ListView.pop` now returns `AwaitComplete` rather than `AwaitRemove` https://github.com/Textualize/textual/pull/5135 - `ListView.remove_items` now returns `AwaitComplete` rather than `AwaitRemove` https://github.com/Textualize/textual/pull/5135 +- Fixed ListView focus styling rule being too broad https://github.com/Textualize/textual/pull/5304 +- Fixed issue with auto-generated tab IDs https://github.com/Textualize/textual/pull/5298 ## [0.87.1] - 2024-11-24 diff --git a/examples/theme_sandbox.py b/examples/theme_sandbox.py index 78d94d974a..f03865b153 100644 --- a/examples/theme_sandbox.py +++ b/examples/theme_sandbox.py @@ -190,12 +190,7 @@ class ChangingThemeApp(App[None]): } ListView { height: auto; - & > ListItem { - width: 1fr; - & > Label { - width: 1fr; - } - } + } Tree { height: 5; diff --git a/poetry.lock b/poetry.lock index 8e9283f7fb..eacdc00634 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -1178,13 +1178,13 @@ dev = ["click", "codecov", "mkdocs-gen-files", "mkdocs-git-authors-plugin", "mkd [[package]] name = "mkdocs-material" -version = "9.5.44" +version = "9.5.46" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_material-9.5.44-py3-none-any.whl", hash = "sha256:47015f9c167d58a5ff5e682da37441fc4d66a1c79334bfc08d774763cacf69ca"}, - {file = "mkdocs_material-9.5.44.tar.gz", hash = "sha256:f3a6c968e524166b3f3ed1fb97d3ed3e0091183b0545cedf7156a2a6804c56c0"}, + {file = "mkdocs_material-9.5.46-py3-none-any.whl", hash = "sha256:98f0a2039c62e551a68aad0791a8d41324ff90c03a6e6cea381a384b84908b83"}, + {file = "mkdocs_material-9.5.46.tar.gz", hash = "sha256:ae2043f4238e572f9a40e0b577f50400d6fc31e2fef8ea141800aebf3bd273d7"}, ] [package.dependencies] @@ -2116,23 +2116,23 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "setuptools" -version = "75.5.0" +version = "75.6.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" files = [ - {file = "setuptools-75.5.0-py3-none-any.whl", hash = "sha256:87cb777c3b96d638ca02031192d40390e0ad97737e27b6b4fa831bea86f2f829"}, - {file = "setuptools-75.5.0.tar.gz", hash = "sha256:5c4ccb41111392671f02bb5f8436dfc5a9a7185e80500531b133f5775c4163ef"}, + {file = "setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d"}, + {file = "setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"}, ] [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"] -core = ["importlib-metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"] +type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"] [[package]] name = "six" @@ -2169,13 +2169,13 @@ files = [ [[package]] name = "syrupy" -version = "4.7.2" +version = "4.8.0" description = "Pytest Snapshot Test Utility" optional = false python-versions = ">=3.8.1" files = [ - {file = "syrupy-4.7.2-py3-none-any.whl", hash = "sha256:eae7ba6be5aed190237caa93be288e97ca1eec5ca58760e4818972a10c4acc64"}, - {file = "syrupy-4.7.2.tar.gz", hash = "sha256:ea45e099f242de1bb53018c238f408a5bb6c82007bc687aefcbeaa0e1c2e935a"}, + {file = "syrupy-4.8.0-py3-none-any.whl", hash = "sha256:544f4ec6306f4b1c460fdab48fd60b2c7fe54a6c0a8243aeea15f9ad9c638c3f"}, + {file = "syrupy-4.8.0.tar.gz", hash = "sha256:648f0e9303aaa8387c8365d7314784c09a6bab0a407455c6a01d6a4f5c6a8ede"}, ] [package.dependencies] @@ -2220,13 +2220,43 @@ textual = ">=0.66.0" [[package]] name = "tomli" -version = "2.1.0" +version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" files = [ - {file = "tomli-2.1.0-py3-none-any.whl", hash = "sha256:a5c57c3d1c56f5ccdf89f6523458f60ef716e210fc47c4cfb188c5ba473e0391"}, - {file = "tomli-2.1.0.tar.gz", hash = "sha256:3f646cae2aec94e17d04973e4249548320197cfabdf130015d023de4b74d8ab8"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, ] [[package]] @@ -2479,13 +2509,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.27.1" +version = "20.28.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" files = [ - {file = "virtualenv-20.27.1-py3-none-any.whl", hash = "sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4"}, - {file = "virtualenv-20.27.1.tar.gz", hash = "sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba"}, + {file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"}, + {file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"}, ] [package.dependencies] diff --git a/src/textual/widgets/_list_view.py b/src/textual/widgets/_list_view.py index 97d2c150bb..b8c36bdd4c 100644 --- a/src/textual/widgets/_list_view.py +++ b/src/textual/widgets/_list_view.py @@ -31,10 +31,6 @@ class ListView(VerticalScroll, can_focus=True, can_focus_children=False): DEFAULT_CSS = """ ListView { background: $surface; - &:focus-within { - background-tint: $foreground 5%; - } - & > ListItem { color: $foreground; height: auto; @@ -52,12 +48,15 @@ class ListView(VerticalScroll, can_focus=True, can_focus_children=False): } } - &:focus > ListItem.-highlight > Widget { - width: 1fr; - color: $block-cursor-foreground; - background: $block-cursor-background; - text-style: $block-cursor-text-style; + &:focus { + background-tint: $foreground 5%; + & > ListItem.-highlight { + color: $block-cursor-foreground; + background: $block-cursor-background; + text-style: $block-cursor-text-style; + } } + } """ diff --git a/src/textual/widgets/_tabbed_content.py b/src/textual/widgets/_tabbed_content.py index 37630b05dc..2d625e7cd0 100644 --- a/src/textual/widgets/_tabbed_content.py +++ b/src/textual/widgets/_tabbed_content.py @@ -332,6 +332,7 @@ def __init__( self.titles = [self.render_str(title) for title in titles] self._tab_content: list[Widget] = [] self._initial = initial + self._tab_counter = 0 super().__init__(name=name, id=id, classes=classes, disabled=disabled) @property @@ -357,6 +358,15 @@ def _set_id(content: TabPane, new_id: int) -> TabPane: content.id = f"tab-{new_id}" return content + def _generate_tab_id(self) -> int: + """Auto generate a new tab id. + + Returns: + An auto-incrementing integer. + """ + self._tab_counter += 1 + return self._tab_counter + def compose(self) -> ComposeResult: """Compose the tabbed content.""" @@ -368,7 +378,7 @@ def compose(self) -> ComposeResult: if isinstance(content, TabPane) else TabPane(title or self.render_str(f"Tab {index}"), content) ), - index, + self._generate_tab_id(), ) for index, (title, content) in enumerate( zip_longest(self.titles, self._tab_content), 1 @@ -424,7 +434,7 @@ def add_pane( if isinstance(after, TabPane): after = after.id tabs = self.get_child_by_type(ContentTabs) - pane = self._set_id(pane, tabs.tab_count + 1) + pane = self._set_id(pane, self._generate_tab_id()) assert pane.id is not None pane.display = False return AwaitComplete( diff --git a/src/textual/widgets/_tree.py b/src/textual/widgets/_tree.py index 79c64be224..c0aae200a8 100644 --- a/src/textual/widgets/_tree.py +++ b/src/textual/widgets/_tree.py @@ -374,7 +374,7 @@ def add( before: Optional index or `TreeNode` to add the node before. after: Optional index or `TreeNode` to add the node after. expand: Node should be expanded. - allow_expand: Allow use to expand the node via keyboard or mouse. + allow_expand: Allow user to expand the node via keyboard or mouse. Returns: A new Tree node diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_add_remove_tabs.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_add_remove_tabs.svg new file mode 100644 index 0000000000..7f987a7129 --- /dev/null +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_add_remove_tabs.svg @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ExampleApp + + + + + + + + + + tab-2New tabNew tab +━━━━━╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +tab-2                                                                            + + + + + + + + + + + + + + + + + + + + + r Remove first pane  a Add pane                                    ^p palette + + + diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_list_view.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_list_view.svg index a8d6dc1341..3fa0dc38fe 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_list_view.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_list_view.svg @@ -19,135 +19,135 @@ font-weight: 700; } - .terminal-1566611737-matrix { + .terminal-3096607170-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1566611737-title { + .terminal-3096607170-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1566611737-r1 { fill: #e0e0e0 } -.terminal-1566611737-r2 { fill: #c5c8c6 } -.terminal-1566611737-r3 { fill: #ddedf9;font-weight: bold } -.terminal-1566611737-r4 { fill: #495259 } -.terminal-1566611737-r5 { fill: #ffa62b;font-weight: bold } + .terminal-3096607170-r1 { fill: #e0e0e0 } +.terminal-3096607170-r2 { fill: #c5c8c6 } +.terminal-3096607170-r3 { fill: #ddedf9;font-weight: bold } +.terminal-3096607170-r4 { fill: #495259 } +.terminal-3096607170-r5 { fill: #ffa62b;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - ListViewExample + ListViewExample - - - - - - - - - - - -One - - -Two - - -Three - - - - - - - - -^p palette + + + + + + + + + + + +One + + +Two + + +Three + + + + + + + + +^p palette diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_listview_index.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_listview_index.svg index bc6a941dfe..05da5a82eb 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots/test_listview_index.svg +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_listview_index.svg @@ -19,134 +19,134 @@ font-weight: 700; } - .terminal-3115202658-matrix { + .terminal-2420511677-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3115202658-title { + .terminal-2420511677-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3115202658-r1 { fill: #e0e0e0 } -.terminal-3115202658-r2 { fill: #c5c8c6 } -.terminal-3115202658-r3 { fill: #003054 } -.terminal-3115202658-r4 { fill: #272727 } -.terminal-3115202658-r5 { fill: #ddedf9;font-weight: bold } + .terminal-2420511677-r1 { fill: #e0e0e0 } +.terminal-2420511677-r2 { fill: #c5c8c6 } +.terminal-2420511677-r3 { fill: #003054 } +.terminal-2420511677-r4 { fill: #272727 } +.terminal-2420511677-r5 { fill: #ddedf9;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - ListViewIndexApp + ListViewIndexApp - - - - 10                                                                             -12                                                                             -14                                                                             -16                                                                            ▆▆ -18                                                                             -20                                                                             -22                                                                             -24                                                                             -26                                                                             -28 - - - - - - - - - - - - - + + + + 10                                                                             +12                                                                             +14                                                                             +16                                                                            ▆▆ +18                                                                             +20                                                                             +22                                                                             +24                                                                             +26                                                                             +28                                                                             + + + + + + + + + + + + + diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index b2fcd41a1d..a6f3a8e36d 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -35,6 +35,8 @@ Tab, Tabs, TextArea, + TabbedContent, + TabPane, ) from textual.widgets.text_area import BUILTIN_LANGUAGES, Selection, TextAreaTheme from textual.theme import Theme @@ -2752,7 +2754,6 @@ async def run_before(pilot: Pilot) -> None: snap_compare(TallSelectApp(), run_before=run_before) - def test_markup_command_list(snap_compare): """Regression test for https://github.com/Textualize/textual/issues/5276 You should see a command list, with console markup applied to the action name and help text.""" @@ -2769,6 +2770,7 @@ def on_mount(self) -> None: snap_compare(MyApp()) + def test_app_resize_order(snap_compare): """Regression test for https://github.com/Textualize/textual/issues/5284 You should see a placeholder with text "BAR", focused and scrolled down so it fills the screen. @@ -2810,3 +2812,32 @@ def on_resize(self) -> None: snap_compare(SCApp()) + +def test_add_remove_tabs(snap_compare): + """Regression test for https://github.com/Textualize/textual/issues/5215 + You should see a TabbedContent with three panes, entitled 'tab-2', 'New tab' and 'New tab'""" + + class ExampleApp(App): + BINDINGS = [ + ("r", "remove_pane", "Remove first pane"), + ("a", "add_pane", "Add pane"), + ] + + def compose(self) -> ComposeResult: + with TabbedContent(initial="tab-2"): + with TabPane("tab-1"): + yield Label("tab-1") + with TabPane("tab-2"): + yield Label("tab-2") + yield Footer() + + def action_remove_pane(self) -> None: + tabbed_content = self.query_one(TabbedContent) + tabbed_content.remove_pane("tab-1") + + def action_add_pane(self) -> None: + tabbed_content = self.query_one(TabbedContent) + new_pane = TabPane("New tab", Label("new")) + tabbed_content.add_pane(new_pane) + + snap_compare(ExampleApp(), press=["a", "r", "a"])