From 563ccb8f0c3d70568c0c5e3a17559eb8a504bd85 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 9 Sep 2024 17:32:29 +0100 Subject: [PATCH 1/6] enable app focus styles --- src/textual/app.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/textual/app.py b/src/textual/app.py index 8f3fe1089c..81ef895e95 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -321,6 +321,9 @@ class App(Generic[ReturnType], DOMNode): dock: initial !important; } } + &:blur Screen Widget{ + tint: $panel 50%; + } } *:disabled:can-focus { opacity: 0.7; @@ -820,6 +823,20 @@ def _context(self) -> Generator[None, None, None]: active_message_pump.reset(message_pump_reset_token) active_app.reset(app_reset_token) + def get_pseudo_classes(self) -> Iterable[str]: + """Pseudo classes for a widget. + + Returns: + Names of the pseudo classes. + """ + if self.app_focus: + yield "focus" + else: + yield "blur" + yield "dark" if self.app.dark else "light" + if self.is_inline: + yield "inline" + def animate( self, attribute: str, @@ -3608,6 +3625,7 @@ def post_mount() -> None: def _watch_app_focus(self, focus: bool) -> None: """Respond to changes in app focus.""" + self.screen._update_styles() if focus: # If we've got a last-focused widget, if it still has a screen, # and if the screen is still the current screen and if nothing From d4ccc67109ef9851b9a4fe4ecaabda42f5aad1d6 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 9 Sep 2024 17:42:34 +0100 Subject: [PATCH 2/6] test fix --- src/textual/app.py | 7 +++++-- tests/test_test_runner.py | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index 81ef895e95..417574babb 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -312,6 +312,8 @@ class App(Generic[ReturnType], DOMNode): App { background: $background; color: $text; + + /* When a widget is maximized */ Screen.-maximized-view { layout: vertical !important; hatch: right $panel; @@ -321,8 +323,9 @@ class App(Generic[ReturnType], DOMNode): dock: initial !important; } } - &:blur Screen Widget{ - tint: $panel 50%; + /* Fade the header title when app is blurred */ + &:blur HeaderTitle { + text-opacity: 50%; } } *:disabled:can-focus { diff --git a/tests/test_test_runner.py b/tests/test_test_runner.py index b47bed98d2..0bae14a0bd 100644 --- a/tests/test_test_runner.py +++ b/tests/test_test_runner.py @@ -13,7 +13,8 @@ def on_key(self, event: events.Key) -> None: app = TestApp() async with app.run_test() as pilot: assert ( - str(pilot) == "" + str(pilot) + == "" ) await pilot.press("tab", *"foo") await pilot.exit("bar") From 12f0ed090df7ebba90a4618dfd71b7227e7deced Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 9 Sep 2024 17:47:23 +0100 Subject: [PATCH 3/6] simplify --- src/textual/app.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/textual/app.py b/src/textual/app.py index 417574babb..7b2675437d 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -832,11 +832,8 @@ def get_pseudo_classes(self) -> Iterable[str]: Returns: Names of the pseudo classes. """ - if self.app_focus: - yield "focus" - else: - yield "blur" - yield "dark" if self.app.dark else "light" + yield "focus" if self.app_focus else "blur" + yield "dark" if self.dark else "light" if self.is_inline: yield "inline" From 54c3a2e0da26a91237b6e17983419439d13c5bae Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Mon, 9 Sep 2024 17:55:35 +0100 Subject: [PATCH 4/6] test fix --- tests/test_test_runner.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_test_runner.py b/tests/test_test_runner.py index 0bae14a0bd..8bb80d2071 100644 --- a/tests/test_test_runner.py +++ b/tests/test_test_runner.py @@ -12,9 +12,9 @@ def on_key(self, event: events.Key) -> None: app = TestApp() async with app.run_test() as pilot: - assert ( - str(pilot) - == "" + assert str(pilot) in ( + "", + "", ) await pilot.press("tab", *"foo") await pilot.exit("bar") From 2cd38d1b07d04a251329469d18e1d392136e73b1 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 11 Sep 2024 15:09:43 +0100 Subject: [PATCH 5/6] added test --- tests/snapshot_tests/test_snapshots.py | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 864f80e3fe..f0d1fdc9b1 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -3,6 +3,7 @@ import pytest from tests.snapshot_tests.language_snippets import SNIPPETS +from textual import events from textual.app import App, ComposeResult from textual.binding import Binding from textual.containers import Vertical @@ -1676,3 +1677,37 @@ def on_mount(self) -> None: # ctrl+m to maximize, escape *should* minimize assert snap_compare(TextAreaExample(), press=["ctrl+m", "escape"]) + + +async def test_app_focus_style(snap_compare): + class FocusApp(App): + CSS = """ + Label { + padding: 1 2; + margin: 1 2; + background: $panel; + border: $primary; + } + App:focus { + .blurred { + visibility: hidden; + } + } + + App:blur { + .focussed { + visibility: hidden; + } + } + + """ + + def compose(self) -> ComposeResult: + yield Label("BLURRED", classes="blurred") + yield Label("FOCUSED", classes="focussed") + + async def run_before(pilot: Pilot) -> None: + pilot.app.post_message(events.AppBlur()) + await pilot.pause() + + assert snap_compare(FocusApp(), run_before=run_before) From ef2281cceb80d91d47bc4bca6e766db8a375ab4b Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 11 Sep 2024 15:53:01 +0100 Subject: [PATCH 6/6] snapshot --- .../test_snapshots/test_app_focus_style.svg | 152 ++++++++++++++++++ tests/snapshot_tests/test_snapshots.py | 12 +- 2 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 tests/snapshot_tests/__snapshots__/test_snapshots/test_app_focus_style.svg diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_focus_style.svg b/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_focus_style.svg new file mode 100644 index 0000000000..79cdfbd91a --- /dev/null +++ b/tests/snapshot_tests/__snapshots__/test_snapshots/test_app_focus_style.svg @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + FocusApp + + + + + + + + + + +┌───────────┐ + +BLURRED + +└───────────┘ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index dea18c8423..bec3ce2b6b 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -122,7 +122,9 @@ async def run_before(pilot): pilot.app.query(Input).first().cursor_blink = False assert snap_compare( - SNAPSHOT_APPS_DIR / "masked_input.py", press=["A","B","C","0","1","-","D","E"], run_before=run_before + SNAPSHOT_APPS_DIR / "masked_input.py", + press=["A", "B", "C", "0", "1", "-", "D", "E"], + run_before=run_before, ) @@ -1688,7 +1690,9 @@ def on_mount(self) -> None: assert snap_compare(TextAreaExample(), press=["ctrl+m", "escape"]) -async def test_app_focus_style(snap_compare): +def test_app_focus_style(snap_compare): + """Test that app blur style can be selected.""" + class FocusApp(App): CSS = """ Label { @@ -1700,13 +1704,13 @@ class FocusApp(App): App:focus { .blurred { visibility: hidden; - } + } } App:blur { .focussed { visibility: hidden; - } + } } """