From b729177680d06acc52578a181094688e67d9f41c Mon Sep 17 00:00:00 2001 From: Edward Jazzhands Date: Tue, 24 Jun 2025 13:25:45 -0300 Subject: [PATCH 1/3] Fixed CSS transparency bug in _style_properties.py --- CHANGELOG.md | 6 ++++++ src/textual/css/_style_properties.py | 1 + 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19b78b6104..63bf7dd9df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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 + +### Fixed + +- Fixed issue with the "transparent" CSS value not being transparent when set using python + ## [3.5.0] - 2025-06-20 ### Changed diff --git a/src/textual/css/_style_properties.py b/src/textual/css/_style_properties.py index 472e5fd26c..02c19fb0c7 100644 --- a/src/textual/css/_style_properties.py +++ b/src/textual/css/_style_properties.py @@ -984,6 +984,7 @@ def __set__(self, obj: StylesBase, color: Color | str | None) -> None: continue try: parsed_color = Color.parse(token) + _r, _g, _b, alpha, _, _ = parsed_color except ColorParseError as error: raise StyleValueError( f"Invalid color value '{token}'", From 0fb00474beadae19989371dbf5fc912a4c0530e9 Mon Sep 17 00:00:00 2001 From: Edward Jazzhands Date: Tue, 24 Jun 2025 14:20:43 -0300 Subject: [PATCH 2/3] Better method, using multiply_alpha --- src/textual/css/_style_properties.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/textual/css/_style_properties.py b/src/textual/css/_style_properties.py index 02c19fb0c7..7860eb32e0 100644 --- a/src/textual/css/_style_properties.py +++ b/src/textual/css/_style_properties.py @@ -984,7 +984,6 @@ def __set__(self, obj: StylesBase, color: Color | str | None) -> None: continue try: parsed_color = Color.parse(token) - _r, _g, _b, alpha, _, _ = parsed_color except ColorParseError as error: raise StyleValueError( f"Invalid color value '{token}'", @@ -992,7 +991,7 @@ def __set__(self, obj: StylesBase, color: Color | str | None) -> None: self.name, context="inline", error=error, value=token ), ) - parsed_color = parsed_color.with_alpha(alpha) + parsed_color = parsed_color.multiply_alpha(alpha) if obj.set_rule(self.name, parsed_color): obj.refresh(children=True) From 58f576c373b8bcbe4800561de7eab00eac91d7bb Mon Sep 17 00:00:00 2001 From: Edward Jazzhands Date: Wed, 25 Jun 2025 12:55:46 -0300 Subject: [PATCH 3/3] Added regression snapshot test for transparency issue --- .../test_setting_transparency.svg | 154 ++++++++++++++++++ tests/snapshot_tests/test_snapshots.py | 49 ++++++ 2 files changed, 203 insertions(+) create mode 100644 tests/snapshot_tests/__snapshots__/test_snapshots/test_setting_transparency.svg diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_setting_transparency.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_setting_transparency.svg new file mode 100644 index 0000000000..9067444ae6 --- /dev/null +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_setting_transparency.svg @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TransparentPythonApp + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +Baseline normal TextArea, not transparent      + + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎ +This TextArea made transparent by adding a     +CSS class                                      + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎ +This TextArea made transparent by setting      +style with python                              + +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎ +▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▎ +1) This is an OptionList + +2) With a transparent background + +3) Made transparent by setting style with +python +▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▎ + + + + diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 5b9db68929..fea3b0c5a4 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -3540,6 +3540,55 @@ def compose(self) -> ComposeResult: assert snap_compare(FocusWithinTransparentApp(), press=["tab"]) + +def test_setting_transparency(snap_compare): + """Check that setting a widget's background color to transparent + works as expected using python. + Regression test for https://github.com/Textualize/textual/pull/5890""" + + class TransparentPythonApp(App): + + CSS = """ + Screen { + background: darkblue; + align: center middle; + } + + TextArea { + height: 5; + width: 50; + &.-transparent { background: transparent; } + } + + OptionList { + height: 8; + width: 50; + } + """ + + def compose(self): + + yield TextArea("Baseline normal TextArea, not transparent") + text_area2 = TextArea( + "This TextArea made transparent by adding a CSS class", classes="-transparent" + ) + yield text_area2 + text_area3 = TextArea( + "This TextArea made transparent by setting style with python" + ) + text_area3.styles.background = "transparent" + yield text_area3 + option_list = OptionList( + "1) This is an OptionList\n", + "2) With a transparent background\n", + "3) Made transparent by setting style with python", + ) + option_list.styles.background = "transparent" + yield option_list + + assert snap_compare(TransparentPythonApp()) + + def test_option_list_wrapping(snap_compare): """You should see a 40 cell wide Option list with a single line, ending in an ellipsis."""