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 @@
+
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"])