diff --git a/CHANGELOG.md b/CHANGELOG.md index c35703853c..327997b90d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fixed `TreeNode.toggle` and `TreeNode.toggle_all` not posting a `Tree.NodeExpanded` or `Tree.NodeCollapsed` message https://github.com/Textualize/textual/issues/2535 - `footer--description` component class was being ignored https://github.com/Textualize/textual/issues/2544 - Pasting empty selection in `Input` would raise an exception https://github.com/Textualize/textual/issues/2563 +- `Screen.AUTO_FOCUS` now focuses the first _focusable_ widget that matches the selector https://github.com/Textualize/textual/issues/2578 +- `Screen.AUTO_FOCUS` now works on the default screen on startup https://github.com/Textualize/textual/pull/2581 - Fix for setting dark in App `__init__` https://github.com/Textualize/textual/issues/2583 - Fix issue with scrolling and docks https://github.com/Textualize/textual/issues/2525 diff --git a/src/textual/app.py b/src/textual/app.py index 74585c166d..d92c858dc1 100644 --- a/src/textual/app.py +++ b/src/textual/app.py @@ -2140,6 +2140,7 @@ async def on_event(self, event: events.Event) -> None: screen = Screen(id="_default") self._register(self, screen) self._screen_stack.append(screen) + screen.post_message(events.ScreenResume()) await super().on_event(event) elif isinstance(event, events.InputEvent) and not event.is_forwarded: diff --git a/src/textual/screen.py b/src/textual/screen.py index 775223a038..4d38d25e56 100644 --- a/src/textual/screen.py +++ b/src/textual/screen.py @@ -668,15 +668,13 @@ def _on_screen_resume(self) -> None: """Screen has resumed.""" self.stack_updates += 1 size = self.app.size - if self.AUTO_FOCUS is not None and self.focused is None: - try: - to_focus = self.query(self.AUTO_FOCUS).first() - except NoMatches: - pass - else: - self.set_focus(to_focus) self._refresh_layout(size, full=True) self.refresh() + if self.AUTO_FOCUS is not None and self.focused is None: + for widget in self.query(self.AUTO_FOCUS): + if widget.focusable: + self.set_focus(widget) + break def _on_screen_suspend(self) -> None: """Screen has suspended.""" diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index a5c7a6ea63..c0e2e96b98 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -21,138 +21,138 @@ font-weight: 700; } - .terminal-1593336641-matrix { + .terminal-644510384-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1593336641-title { + .terminal-644510384-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1593336641-r1 { fill: #c5c8c6 } - .terminal-1593336641-r2 { fill: #7ae998 } - .terminal-1593336641-r3 { fill: #0a180e;font-weight: bold } - .terminal-1593336641-r4 { fill: #008139 } - .terminal-1593336641-r5 { fill: #e3dbce } - .terminal-1593336641-r6 { fill: #e1e1e1 } - .terminal-1593336641-r7 { fill: #e76580 } - .terminal-1593336641-r8 { fill: #f5e5e9;font-weight: bold } - .terminal-1593336641-r9 { fill: #780028 } + .terminal-644510384-r1 { fill: #c5c8c6 } + .terminal-644510384-r2 { fill: #7ae998 } + .terminal-644510384-r3 { fill: #4ebf71;font-weight: bold } + .terminal-644510384-r4 { fill: #008139 } + .terminal-644510384-r5 { fill: #e3dbce } + .terminal-644510384-r6 { fill: #e1e1e1 } + .terminal-644510384-r7 { fill: #e76580 } + .terminal-644510384-r8 { fill: #f5e5e9;font-weight: bold } + .terminal-644510384-r9 { fill: #780028 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - AlignContainersApp + AlignContainersApp - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - center - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - middle - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + center + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + middle + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + @@ -1739,139 +1739,140 @@ font-weight: 700; } - .terminal-2222688117-matrix { + .terminal-78223076-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2222688117-title { + .terminal-78223076-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2222688117-r1 { fill: #c5c8c6 } - .terminal-2222688117-r2 { fill: #e1e1e1 } - .terminal-2222688117-r3 { fill: #454a50 } - .terminal-2222688117-r4 { fill: #e2e3e3;font-weight: bold } - .terminal-2222688117-r5 { fill: #000000 } - .terminal-2222688117-r6 { fill: #004578 } - .terminal-2222688117-r7 { fill: #dde6ed;font-weight: bold } - .terminal-2222688117-r8 { fill: #dde6ed } - .terminal-2222688117-r9 { fill: #211505 } - .terminal-2222688117-r10 { fill: #e2e3e3 } + .terminal-78223076-r1 { fill: #c5c8c6 } + .terminal-78223076-r2 { fill: #e1e1e1 } + .terminal-78223076-r3 { fill: #454a50 } + .terminal-78223076-r4 { fill: #24292f;font-weight: bold } + .terminal-78223076-r5 { fill: #e2e3e3;font-weight: bold } + .terminal-78223076-r6 { fill: #000000 } + .terminal-78223076-r7 { fill: #004578 } + .terminal-78223076-r8 { fill: #dde6ed;font-weight: bold } + .terminal-78223076-r9 { fill: #dde6ed } + .terminal-78223076-r10 { fill: #211505 } + .terminal-78223076-r11 { fill: #e2e3e3 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - ContentSwitcherApp + ContentSwitcherApp - - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - DataTableMarkdown - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ──────────────────────────────────────────────────────────────────── -  Book                                 Year  -  Dune                                 1965  -  Dune Messiah                         1969  -  Children of Dune                     1976  -  God Emperor of Dune                  1981  -  Heretics of Dune                     1984  -  Chapterhouse: Dune                   1985  - - - - - - - - - - - ──────────────────────────────────────────────────────────────────── + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + DataTableMarkdown + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ──────────────────────────────────────────────────────────────────── +  Book                                 Year  +  Dune                                 1965  +  Dune Messiah                         1969  +  Children of Dune                     1976  +  God Emperor of Dune                  1981  +  Heretics of Dune                     1984  +  Chapterhouse: Dune                   1985  + + + + + + + + + + + ──────────────────────────────────────────────────────────────────── @@ -13760,161 +13761,162 @@ font-weight: 700; } - .terminal-65653754-matrix { + .terminal-1022810985-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-65653754-title { + .terminal-1022810985-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-65653754-r1 { fill: #454a50 } - .terminal-65653754-r2 { fill: #507bb3 } - .terminal-65653754-r3 { fill: #7ae998 } - .terminal-65653754-r4 { fill: #ffcf56 } - .terminal-65653754-r5 { fill: #e76580 } - .terminal-65653754-r6 { fill: #c5c8c6 } - .terminal-65653754-r7 { fill: #e2e3e3;font-weight: bold } - .terminal-65653754-r8 { fill: #dde6ed;font-weight: bold } - .terminal-65653754-r9 { fill: #0a180e;font-weight: bold } - .terminal-65653754-r10 { fill: #211505;font-weight: bold } - .terminal-65653754-r11 { fill: #f5e5e9;font-weight: bold } - .terminal-65653754-r12 { fill: #000000 } - .terminal-65653754-r13 { fill: #001541 } - .terminal-65653754-r14 { fill: #008139 } - .terminal-65653754-r15 { fill: #b86b00 } - .terminal-65653754-r16 { fill: #780028 } - .terminal-65653754-r17 { fill: #35383c } - .terminal-65653754-r18 { fill: #3c5577 } - .terminal-65653754-r19 { fill: #559767 } - .terminal-65653754-r20 { fill: #a5883f } - .terminal-65653754-r21 { fill: #964858 } - .terminal-65653754-r22 { fill: #7c7d7e;font-weight: bold } - .terminal-65653754-r23 { fill: #75828b;font-weight: bold } - .terminal-65653754-r24 { fill: #192e1f;font-weight: bold } - .terminal-65653754-r25 { fill: #3a2a13;font-weight: bold } - .terminal-65653754-r26 { fill: #978186;font-weight: bold } - .terminal-65653754-r27 { fill: #0c0c0c } - .terminal-65653754-r28 { fill: #0c1833 } - .terminal-65653754-r29 { fill: #0c592e } - .terminal-65653754-r30 { fill: #7a4c0c } - .terminal-65653754-r31 { fill: #540c24 } + .terminal-1022810985-r1 { fill: #454a50 } + .terminal-1022810985-r2 { fill: #507bb3 } + .terminal-1022810985-r3 { fill: #7ae998 } + .terminal-1022810985-r4 { fill: #ffcf56 } + .terminal-1022810985-r5 { fill: #e76580 } + .terminal-1022810985-r6 { fill: #c5c8c6 } + .terminal-1022810985-r7 { fill: #24292f;font-weight: bold } + .terminal-1022810985-r8 { fill: #dde6ed;font-weight: bold } + .terminal-1022810985-r9 { fill: #0a180e;font-weight: bold } + .terminal-1022810985-r10 { fill: #211505;font-weight: bold } + .terminal-1022810985-r11 { fill: #f5e5e9;font-weight: bold } + .terminal-1022810985-r12 { fill: #000000 } + .terminal-1022810985-r13 { fill: #001541 } + .terminal-1022810985-r14 { fill: #008139 } + .terminal-1022810985-r15 { fill: #b86b00 } + .terminal-1022810985-r16 { fill: #780028 } + .terminal-1022810985-r17 { fill: #35383c } + .terminal-1022810985-r18 { fill: #3c5577 } + .terminal-1022810985-r19 { fill: #559767 } + .terminal-1022810985-r20 { fill: #a5883f } + .terminal-1022810985-r21 { fill: #964858 } + .terminal-1022810985-r22 { fill: #7c7d7e;font-weight: bold } + .terminal-1022810985-r23 { fill: #75828b;font-weight: bold } + .terminal-1022810985-r24 { fill: #192e1f;font-weight: bold } + .terminal-1022810985-r25 { fill: #3a2a13;font-weight: bold } + .terminal-1022810985-r26 { fill: #978186;font-weight: bold } + .terminal-1022810985-r27 { fill: #0c0c0c } + .terminal-1022810985-r28 { fill: #0c1833 } + .terminal-1022810985-r29 { fill: #0c592e } + .terminal-1022810985-r30 { fill: #7a4c0c } + .terminal-1022810985-r31 { fill: #540c24 } + .terminal-1022810985-r32 { fill: #e2e3e3;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - WidgetDisableTestApp + WidgetDisableTestApp - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ButtonButtonButtonButtonButton - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ButtonButtonButtonButtonButton - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ButtonButtonButtonButtonButton - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ButtonButtonButtonButtonButton - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ButtonButtonButtonButtonButton - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ButtonButtonButtonButtonButton - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ButtonButtonButtonButtonButton - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ButtonButtonButtonButtonButton - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ButtonButtonButtonButtonButton + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ButtonButtonButtonButtonButton + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ButtonButtonButtonButtonButton + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ButtonButtonButtonButtonButton + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ButtonButtonButtonButtonButton + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ButtonButtonButtonButtonButton + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ButtonButtonButtonButtonButton + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ButtonButtonButtonButtonButton + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ @@ -14592,147 +14594,148 @@ font-weight: 700; } - .terminal-2863933047-matrix { + .terminal-432027110-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2863933047-title { + .terminal-432027110-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2863933047-r1 { fill: #454a50 } - .terminal-2863933047-r2 { fill: #e1e1e1 } - .terminal-2863933047-r3 { fill: #c5c8c6 } - .terminal-2863933047-r4 { fill: #e2e3e3;font-weight: bold } - .terminal-2863933047-r5 { fill: #262626 } - .terminal-2863933047-r6 { fill: #000000 } - .terminal-2863933047-r7 { fill: #e2e2e2 } - .terminal-2863933047-r8 { fill: #e3e3e3 } - .terminal-2863933047-r9 { fill: #14191f } - .terminal-2863933047-r10 { fill: #b93c5b } - .terminal-2863933047-r11 { fill: #121212 } - .terminal-2863933047-r12 { fill: #1e1e1e } - .terminal-2863933047-r13 { fill: #fea62b } - .terminal-2863933047-r14 { fill: #211505;font-weight: bold } - .terminal-2863933047-r15 { fill: #211505 } - .terminal-2863933047-r16 { fill: #dde8f3;font-weight: bold } - .terminal-2863933047-r17 { fill: #ddedf9 } + .terminal-432027110-r1 { fill: #454a50 } + .terminal-432027110-r2 { fill: #e1e1e1 } + .terminal-432027110-r3 { fill: #c5c8c6 } + .terminal-432027110-r4 { fill: #24292f;font-weight: bold } + .terminal-432027110-r5 { fill: #262626 } + .terminal-432027110-r6 { fill: #000000 } + .terminal-432027110-r7 { fill: #e2e2e2 } + .terminal-432027110-r8 { fill: #e3e3e3 } + .terminal-432027110-r9 { fill: #e2e3e3;font-weight: bold } + .terminal-432027110-r10 { fill: #14191f } + .terminal-432027110-r11 { fill: #b93c5b } + .terminal-432027110-r12 { fill: #121212 } + .terminal-432027110-r13 { fill: #1e1e1e } + .terminal-432027110-r14 { fill: #fea62b } + .terminal-432027110-r15 { fill: #211505;font-weight: bold } + .terminal-432027110-r16 { fill: #211505 } + .terminal-432027110-r17 { fill: #dde8f3;font-weight: bold } + .terminal-432027110-r18 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - EasingApp + EasingApp - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - round▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Animation Duration:1.0 - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - out_sine - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - out_quint - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Welcome to Textual! - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - out_quartI must not fear. - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Fear is the  - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔mind-killer. - out_quadFear is the  - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁little-death that  - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔brings total  - out_expoobliteration. - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁I will face my fear. - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔I will permit it to  - out_elasticpass over me and  - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁through me. - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔And when it has gone  - out_cubic - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ CTRL+P  Focus: Duration Input  CTRL+B  Toggle Dark  + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + round▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Animation Duration:1.0 + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + out_sine + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + out_quint + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Welcome to Textual! + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + out_quartI must not fear. + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁Fear is the  + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔mind-killer. + out_quadFear is the  + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁little-death that  + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔brings total  + out_expoobliteration. + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁I will face my fear. + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔I will permit it to  + out_elasticpass over me and  + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁through me. + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔And when it has gone  + out_cubic + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ CTRL+P  Focus: Duration Input  CTRL+B  Toggle Dark  @@ -16809,146 +16812,146 @@ font-weight: 700; } - .terminal-2572323619-matrix { + .terminal-4085160594-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2572323619-title { + .terminal-4085160594-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2572323619-r1 { fill: #c5c8c6 } - .terminal-2572323619-r2 { fill: #e3e3e3 } - .terminal-2572323619-r3 { fill: #e1e1e1 } - .terminal-2572323619-r4 { fill: #e1e1e1;text-decoration: underline; } - .terminal-2572323619-r5 { fill: #e1e1e1;font-weight: bold } - .terminal-2572323619-r6 { fill: #e1e1e1;font-style: italic; } - .terminal-2572323619-r7 { fill: #98729f;font-weight: bold } - .terminal-2572323619-r8 { fill: #d0b344 } - .terminal-2572323619-r9 { fill: #98a84b } - .terminal-2572323619-r10 { fill: #00823d;font-style: italic; } - .terminal-2572323619-r11 { fill: #ffcf56 } - .terminal-2572323619-r12 { fill: #e76580 } - .terminal-2572323619-r13 { fill: #211505;font-weight: bold } - .terminal-2572323619-r14 { fill: #f5e5e9;font-weight: bold } - .terminal-2572323619-r15 { fill: #b86b00 } - .terminal-2572323619-r16 { fill: #780028 } + .terminal-4085160594-r1 { fill: #c5c8c6 } + .terminal-4085160594-r2 { fill: #e3e3e3 } + .terminal-4085160594-r3 { fill: #e1e1e1 } + .terminal-4085160594-r4 { fill: #e1e1e1;text-decoration: underline; } + .terminal-4085160594-r5 { fill: #e1e1e1;font-weight: bold } + .terminal-4085160594-r6 { fill: #e1e1e1;font-style: italic; } + .terminal-4085160594-r7 { fill: #98729f;font-weight: bold } + .terminal-4085160594-r8 { fill: #d0b344 } + .terminal-4085160594-r9 { fill: #98a84b } + .terminal-4085160594-r10 { fill: #00823d;font-style: italic; } + .terminal-4085160594-r11 { fill: #ffcf56 } + .terminal-4085160594-r12 { fill: #e76580 } + .terminal-4085160594-r13 { fill: #fea62b;font-weight: bold } + .terminal-4085160594-r14 { fill: #f5e5e9;font-weight: bold } + .terminal-4085160594-r15 { fill: #b86b00 } + .terminal-4085160594-r16 { fill: #780028 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - Textual Keys + Textual Keys - - - - Textual Keys - ╭────────────────────────────────────────────────────────────────────────────╮ - Press some keys! - - To quit the app press ctrl+ctwice or press the Quit button below. - ╰────────────────────────────────────────────────────────────────────────────╯ - Key(key='a'character='a'name='a'is_printable=True) - Key(key='b'character='b'name='b'is_printable=True) - - - - - - - - - - - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - ClearQuit - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + Textual Keys + ╭────────────────────────────────────────────────────────────────────────────╮ + Press some keys! + + To quit the app press ctrl+ctwice or press the Quit button below. + ╰────────────────────────────────────────────────────────────────────────────╯ + Key(key='a'character='a'name='a'is_printable=True) + Key(key='b'character='b'name='b'is_printable=True) + + + + + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + ClearQuit + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ @@ -17452,143 +17455,144 @@ font-weight: 700; } - .terminal-4197777529-matrix { + .terminal-4055437288-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-4197777529-title { + .terminal-4055437288-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-4197777529-r1 { fill: #7ae998 } - .terminal-4197777529-r2 { fill: #e76580 } - .terminal-4197777529-r3 { fill: #1e1e1e } - .terminal-4197777529-r4 { fill: #121212 } - .terminal-4197777529-r5 { fill: #c5c8c6 } - .terminal-4197777529-r6 { fill: #0a180e;font-weight: bold } - .terminal-4197777529-r7 { fill: #f5e5e9;font-weight: bold } - .terminal-4197777529-r8 { fill: #e2e2e2 } - .terminal-4197777529-r9 { fill: #008139 } - .terminal-4197777529-r10 { fill: #780028 } - .terminal-4197777529-r11 { fill: #e1e1e1 } - .terminal-4197777529-r12 { fill: #23568b } - .terminal-4197777529-r13 { fill: #14191f } + .terminal-4055437288-r1 { fill: #7ae998 } + .terminal-4055437288-r2 { fill: #e76580 } + .terminal-4055437288-r3 { fill: #1e1e1e } + .terminal-4055437288-r4 { fill: #121212 } + .terminal-4055437288-r5 { fill: #c5c8c6 } + .terminal-4055437288-r6 { fill: #4ebf71;font-weight: bold } + .terminal-4055437288-r7 { fill: #f5e5e9;font-weight: bold } + .terminal-4055437288-r8 { fill: #e2e2e2 } + .terminal-4055437288-r9 { fill: #0a180e;font-weight: bold } + .terminal-4055437288-r10 { fill: #008139 } + .terminal-4055437288-r11 { fill: #780028 } + .terminal-4055437288-r12 { fill: #e1e1e1 } + .terminal-4055437288-r13 { fill: #23568b } + .terminal-4055437288-r14 { fill: #14191f } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - MyApp + MyApp - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - AcceptDeclineAcceptDecline - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - AcceptAccept - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - DeclineDecline - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆▆ - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - 00 - - 10000001000000 + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + AcceptDeclineAcceptDecline + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + AcceptAccept + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + DeclineDecline + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▆▆ + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + 00 + + 10000001000000 @@ -19058,136 +19062,136 @@ font-weight: 700; } - .terminal-1812315577-matrix { + .terminal-4119903855-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1812315577-title { + .terminal-4119903855-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1812315577-r1 { fill: #c5c8c6 } - .terminal-1812315577-r2 { fill: #e3e3e3 } - .terminal-1812315577-r3 { fill: #e1e1e1 } - .terminal-1812315577-r4 { fill: #004578 } - .terminal-1812315577-r5 { fill: #e0e8ee;font-weight: bold } - .terminal-1812315577-r6 { fill: #e2e3e3 } - .terminal-1812315577-r7 { fill: #ddedf9 } + .terminal-4119903855-r1 { fill: #c5c8c6 } + .terminal-4119903855-r2 { fill: #e3e3e3 } + .terminal-4119903855-r3 { fill: #e1e1e1 } + .terminal-4119903855-r4 { fill: #004578 } + .terminal-4119903855-r5 { fill: #ddedf9;font-weight: bold } + .terminal-4119903855-r6 { fill: #e2e3e3 } + .terminal-4119903855-r7 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - OptionListApp + OptionListApp - - - - OptionListApp - - - - ────────────────────────────────────────────────────── - Aerilon - Aquaria - Canceron - Caprica - Gemenon - Leonis - Libran - Picon - Sagittaron - Scorpia - Tauron - Virgon - - - ────────────────────────────────────────────────────── - - - + + + + OptionListApp + + + + ────────────────────────────────────────────────────── + Aerilon + Aquaria + Canceron + Caprica + Gemenon + Leonis + Libran + Picon + Sagittaron + Scorpia + Tauron + Virgon + + + ────────────────────────────────────────────────────── + + + @@ -19218,139 +19222,139 @@ font-weight: 700; } - .terminal-1041266590-matrix { + .terminal-3443619924-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1041266590-title { + .terminal-3443619924-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1041266590-r1 { fill: #c5c8c6 } - .terminal-1041266590-r2 { fill: #e3e3e3 } - .terminal-1041266590-r3 { fill: #e1e1e1 } - .terminal-1041266590-r4 { fill: #004578 } - .terminal-1041266590-r5 { fill: #e0e8ee;font-weight: bold } - .terminal-1041266590-r6 { fill: #e2e3e3 } - .terminal-1041266590-r7 { fill: #42464b } - .terminal-1041266590-r8 { fill: #777a7e } - .terminal-1041266590-r9 { fill: #14191f } - .terminal-1041266590-r10 { fill: #ddedf9 } + .terminal-3443619924-r1 { fill: #c5c8c6 } + .terminal-3443619924-r2 { fill: #e3e3e3 } + .terminal-3443619924-r3 { fill: #e1e1e1 } + .terminal-3443619924-r4 { fill: #004578 } + .terminal-3443619924-r5 { fill: #ddedf9;font-weight: bold } + .terminal-3443619924-r6 { fill: #e2e3e3 } + .terminal-3443619924-r7 { fill: #42464b } + .terminal-3443619924-r8 { fill: #777a7e } + .terminal-3443619924-r9 { fill: #14191f } + .terminal-3443619924-r10 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - OptionListApp + OptionListApp - - - - OptionListApp - - - - ────────────────────────────────────────────────────── - Aerilon - Aquaria - ──────────────────────────────────────────────────── - Canceron - Caprica - ──────────────────────────────────────────────────── - Gemenon - ──────────────────────────────────────────────────── - Leonis - Libran - ────────────────────────────────────────────────────▅▅ - Picon - ──────────────────────────────────────────────────── - Sagittaron - ────────────────────────────────────────────────────── - - - + + + + OptionListApp + + + + ────────────────────────────────────────────────────── + Aerilon + Aquaria + ──────────────────────────────────────────────────── + Canceron + Caprica + ──────────────────────────────────────────────────── + Gemenon + ──────────────────────────────────────────────────── + Leonis + Libran + ────────────────────────────────────────────────────▅▅ + Picon + ──────────────────────────────────────────────────── + Sagittaron + ────────────────────────────────────────────────────── + + + @@ -19381,140 +19385,140 @@ font-weight: 700; } - .terminal-1620527509-matrix { + .terminal-589190207-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1620527509-title { + .terminal-589190207-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1620527509-r1 { fill: #c5c8c6 } - .terminal-1620527509-r2 { fill: #e3e3e3 } - .terminal-1620527509-r3 { fill: #e1e1e1 } - .terminal-1620527509-r4 { fill: #004578 } - .terminal-1620527509-r5 { fill: #e0e8ee;font-weight: bold;font-style: italic; } - .terminal-1620527509-r6 { fill: #e2e3e3 } - .terminal-1620527509-r7 { fill: #e0e8ee;font-weight: bold } - .terminal-1620527509-r8 { fill: #14191f } - .terminal-1620527509-r9 { fill: #e2e3e3;font-style: italic; } - .terminal-1620527509-r10 { fill: #e2e3e3;font-weight: bold } - .terminal-1620527509-r11 { fill: #ddedf9 } + .terminal-589190207-r1 { fill: #c5c8c6 } + .terminal-589190207-r2 { fill: #e3e3e3 } + .terminal-589190207-r3 { fill: #e1e1e1 } + .terminal-589190207-r4 { fill: #004578 } + .terminal-589190207-r5 { fill: #ddedf9;font-weight: bold;font-style: italic; } + .terminal-589190207-r6 { fill: #e2e3e3 } + .terminal-589190207-r7 { fill: #ddedf9;font-weight: bold } + .terminal-589190207-r8 { fill: #14191f } + .terminal-589190207-r9 { fill: #e2e3e3;font-style: italic; } + .terminal-589190207-r10 { fill: #e2e3e3;font-weight: bold } + .terminal-589190207-r11 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - OptionListApp + OptionListApp - - - - OptionListApp - - - - ────────────────────────────────────────────────────── -                   Data for Aerilon                   - ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ - Patron God   Population    Capital City   ▂▂ - ┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩ - Demeter      1.2 Billion   Gaoth           - └───────────────┴────────────────┴─────────────────┘ -                   Data for Aquaria                   - ┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ - Patron God    Population   Capital City    - ┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩ - Hermes        75,000       None            - └────────────────┴───────────────┴─────────────────┘ -                  Data for Canceron                   - ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ - ────────────────────────────────────────────────────── - - - + + + + OptionListApp + + + + ────────────────────────────────────────────────────── +                   Data for Aerilon                   + ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ + Patron God   Population    Capital City   ▂▂ + ┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩ + Demeter      1.2 Billion   Gaoth           + └───────────────┴────────────────┴─────────────────┘ +                   Data for Aquaria                   + ┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ + Patron God    Population   Capital City    + ┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩ + Hermes        75,000       None            + └────────────────┴───────────────┴─────────────────┘ +                  Data for Canceron                   + ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ + ────────────────────────────────────────────────────── + + + @@ -19545,134 +19549,135 @@ font-weight: 700; } - .terminal-2380819869-matrix { + .terminal-1891986877-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2380819869-title { + .terminal-1891986877-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2380819869-r1 { fill: #e1e9ef;font-weight: bold } - .terminal-2380819869-r2 { fill: #c5c8c6 } - .terminal-2380819869-r3 { fill: #e4e5e6 } - .terminal-2380819869-r4 { fill: #4f5459 } - .terminal-2380819869-r5 { fill: #cc555a } + .terminal-1891986877-r1 { fill: #ddedf9;font-weight: bold } + .terminal-1891986877-r2 { fill: #e1e9ef;font-weight: bold } + .terminal-1891986877-r3 { fill: #c5c8c6 } + .terminal-1891986877-r4 { fill: #e4e5e6 } + .terminal-1891986877-r5 { fill: #4f5459 } + .terminal-1891986877-r6 { fill: #cc555a } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - OptionListApp + OptionListApp - - - - OneOneOne - TwoTwoTwo - ──────────────────────────────────────────────────────────────────────────────── - ThreeThreeThree - - - - - - - - - - - - - - - - - - - + + + + OneOneOne + TwoTwoTwo + ──────────────────────────────────────────────────────────────────────────────── + ThreeThreeThree + + + + + + + + + + + + + + + + + + + @@ -21300,135 +21305,135 @@ font-weight: 700; } - .terminal-1586716314-matrix { + .terminal-1484676870-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1586716314-title { + .terminal-1484676870-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1586716314-r1 { fill: #c5c8c6 } - .terminal-1586716314-r2 { fill: #737373 } - .terminal-1586716314-r3 { fill: #e1e1e1;font-weight: bold } - .terminal-1586716314-r4 { fill: #323232 } - .terminal-1586716314-r5 { fill: #0178d4 } - .terminal-1586716314-r6 { fill: #e1e1e1 } + .terminal-1484676870-r1 { fill: #c5c8c6 } + .terminal-1484676870-r2 { fill: #737373 } + .terminal-1484676870-r3 { fill: #e1e1e1;font-weight: bold } + .terminal-1484676870-r4 { fill: #474747 } + .terminal-1484676870-r5 { fill: #0178d4 } + .terminal-1484676870-r6 { fill: #e1e1e1 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - QuicklyChangeTabsApp + QuicklyChangeTabsApp - + - - - onetwothree - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - three - - - - - - - - - - - - - - - - - - + + + onetwothree + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + three + + + + + + + + + + + + + + + + + + @@ -22736,136 +22741,136 @@ font-weight: 700; } - .terminal-1422407852-matrix { + .terminal-1161182100-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1422407852-title { + .terminal-1161182100-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1422407852-r1 { fill: #c5c8c6 } - .terminal-1422407852-r2 { fill: #e3e3e3 } - .terminal-1422407852-r3 { fill: #e1e1e1 } - .terminal-1422407852-r4 { fill: #1e1e1e } - .terminal-1422407852-r5 { fill: #121212 } - .terminal-1422407852-r6 { fill: #787878 } - .terminal-1422407852-r7 { fill: #a8a8a8 } + .terminal-1161182100-r1 { fill: #c5c8c6 } + .terminal-1161182100-r2 { fill: #e3e3e3 } + .terminal-1161182100-r3 { fill: #e1e1e1 } + .terminal-1161182100-r4 { fill: #1e1e1e } + .terminal-1161182100-r5 { fill: #0178d4 } + .terminal-1161182100-r6 { fill: #787878 } + .terminal-1161182100-r7 { fill: #a8a8a8 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - SelectApp + SelectApp - - - - SelectApp - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - Select - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - - - - - - - - - - - - + + + + SelectApp + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Select + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + + + + + + + + + + + + @@ -23543,140 +23548,141 @@ font-weight: 700; } - .terminal-1328081937-matrix { + .terminal-3875007613-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1328081937-title { + .terminal-3875007613-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1328081937-r1 { fill: #c5c8c6 } - .terminal-1328081937-r2 { fill: #737373 } - .terminal-1328081937-r3 { fill: #e1e1e1;font-weight: bold } - .terminal-1328081937-r4 { fill: #323232 } - .terminal-1328081937-r5 { fill: #0178d4 } - .terminal-1328081937-r6 { fill: #121212 } - .terminal-1328081937-r7 { fill: #0053aa } - .terminal-1328081937-r8 { fill: #dde8f3;font-weight: bold } - .terminal-1328081937-r9 { fill: #e1e1e1 } - .terminal-1328081937-r10 { fill: #ddedf9 } + .terminal-3875007613-r1 { fill: #c5c8c6 } + .terminal-3875007613-r2 { fill: #737373 } + .terminal-3875007613-r3 { fill: #e1e1e1;font-weight: bold } + .terminal-3875007613-r4 { fill: #474747 } + .terminal-3875007613-r5 { fill: #0178d4 } + .terminal-3875007613-r6 { fill: #121212 } + .terminal-3875007613-r7 { fill: #0053aa } + .terminal-3875007613-r8 { fill: #dde8f3;font-weight: bold } + .terminal-3875007613-r9 { fill: #e1e1e1 } + .terminal-3875007613-r10 { fill: #323232 } + .terminal-3875007613-r11 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - TabbedApp + TabbedApp - + - - - LetoJessicaPaul - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - Lady Jessica - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - Bene Gesserit and concubine of Leto, and mother of Paul and Alia. - - - - PaulAlia - ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - First child - - - - - - -  L  Leto  J  Jessica  P  Paul  + + + LetoJessicaPaul + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + Lady Jessica + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Bene Gesserit and concubine of Leto, and mother of Paul and Alia. + + + + PaulAlia + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + First child + + + + + + +  L  Leto  J  Jessica  P  Paul  @@ -24336,133 +24342,133 @@ font-weight: 700; } - .terminal-1336653930-matrix { + .terminal-3137592172-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1336653930-title { + .terminal-3137592172-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1336653930-r1 { fill: #e2e3e3 } - .terminal-1336653930-r2 { fill: #1a1000;font-weight: bold } - .terminal-1336653930-r3 { fill: #c5c8c6 } - .terminal-1336653930-r4 { fill: #008139 } + .terminal-3137592172-r1 { fill: #e2e3e3 } + .terminal-3137592172-r2 { fill: #211505;font-weight: bold } + .terminal-3137592172-r3 { fill: #c5c8c6 } + .terminal-3137592172-r4 { fill: #fea62b;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - TreeApp + TreeApp - - - - ▼ Dune - └── ▼ Characters - ├── Paul - ├── Jessica - └── Chani - - - - - - - - - - - - - - - - - - + + + + ▼ Dune + ┗━━ ▼ Characters + ┣━━ Paul + ┣━━ Jessica + ┗━━ Chani + + + + + + + + + + + + + + + + + + diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 0dcd49b193..bdedbced39 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -1,5 +1,4 @@ from pathlib import Path -import sys import pytest @@ -78,8 +77,7 @@ def test_switches(snap_compare): def test_input_and_focus(snap_compare): press = [ - "tab", - *"Darren", # Focus first input, write "Darren" + *"Darren", # Write "Darren" "tab", *"Burns", # Focus second input, write "Burns" ] @@ -88,7 +86,7 @@ def test_input_and_focus(snap_compare): def test_buttons_render(snap_compare): # Testing button rendering. We press tab to focus the first button too. - assert snap_compare(WIDGET_EXAMPLES_DIR / "button.py", press=["tab", "tab"]) + assert snap_compare(WIDGET_EXAMPLES_DIR / "button.py", press=["tab"]) def test_placeholder_render(snap_compare): @@ -189,7 +187,7 @@ def test_content_switcher_example_initial(snap_compare): def test_content_switcher_example_switch(snap_compare): assert snap_compare( WIDGET_EXAMPLES_DIR / "content_switcher.py", - press=["tab", "tab", "enter", "wait:500"], + press=["tab", "enter", "wait:500"], terminal_size=(50, 50), ) @@ -315,7 +313,7 @@ def test_programmatic_scrollbar_gutter_change(snap_compare): def test_borders_preview(snap_compare): - assert snap_compare(CLI_PREVIEWS_DIR / "borders.py", press=["tab", "enter"]) + assert snap_compare(CLI_PREVIEWS_DIR / "borders.py", press=["enter"]) def test_colors_preview(snap_compare): @@ -379,9 +377,7 @@ def test_disabled_widgets(snap_compare): def test_focus_component_class(snap_compare): - assert snap_compare( - SNAPSHOT_APPS_DIR / "focus_component_class.py", press=["tab", "tab"] - ) + assert snap_compare(SNAPSHOT_APPS_DIR / "focus_component_class.py", press=["tab"]) def test_line_api_scrollbars(snap_compare): @@ -442,7 +438,7 @@ def test_modal_dialog_bindings_input(snap_compare): # Check https://github.com/Textualize/textual/issues/2194 assert snap_compare( SNAPSHOT_APPS_DIR / "modal_screen_bindings.py", - press=["enter", "tab", "h", "!", "left", "i", "tab"], + press=["enter", "h", "!", "left", "i", "tab"], ) @@ -518,6 +514,5 @@ def test_select_rebuild(snap_compare): # https://github.com/Textualize/textual/issues/2557 assert snap_compare( SNAPSHOT_APPS_DIR / "select_rebuild.py", - press=["tab", "space", "escape", "tab", "enter", "tab", "space"] + press=["space", "escape", "tab", "enter", "tab", "space"], ) - diff --git a/tests/test_app.py b/tests/test_app.py index 54bde8221f..9cbb82fd00 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,5 +1,5 @@ from textual.app import App, ComposeResult -from textual.widgets import Button +from textual.widgets import Button, Input def test_batch_update(): @@ -20,6 +20,7 @@ def test_batch_update(): class MyApp(App): def compose(self) -> ComposeResult: + yield Input() yield Button("Click me!") diff --git a/tests/test_on.py b/tests/test_on.py index 7812cd616e..740af6a944 100644 --- a/tests/test_on.py +++ b/tests/test_on.py @@ -36,7 +36,7 @@ def on_button_pressed(self): app = ButtonApp() async with app.run_test() as pilot: - await pilot.press("tab", "enter", "tab", "enter", "tab", "enter") + await pilot.press("enter", "tab", "enter", "tab", "enter") await pilot.pause() assert pressed == [ diff --git a/tests/test_paste.py b/tests/test_paste.py index 45be6d536c..6cfc3951fa 100644 --- a/tests/test_paste.py +++ b/tests/test_paste.py @@ -38,6 +38,7 @@ def key_p(self): app = PasteApp() async with app.run_test() as pilot: + app.set_focus(None) await pilot.press("p") assert app.query_one(MyInput).value == "" assert len(paste_events) == 1 diff --git a/tests/test_screens.py b/tests/test_screens.py index 5b29b1dd5c..bd9dfba3ce 100644 --- a/tests/test_screens.py +++ b/tests/test_screens.py @@ -6,7 +6,7 @@ from textual.app import App, ScreenStackError from textual.screen import Screen -from textual.widgets import Button, Input +from textual.widgets import Button, Input, Label skip_py310 = pytest.mark.skipif( sys.version_info.minor == 10 and sys.version_info.major == 3, @@ -155,8 +155,7 @@ async def test_screens(): async def test_auto_focus(): class MyScreen(Screen[None]): - def compose(self) -> None: - print("composing") + def compose(self): yield Button() yield Input(id="one") yield Input(id="two") @@ -194,6 +193,22 @@ class MyApp(App[None]): assert app.focused.id == "two" +async def test_auto_focus_skips_non_focusable_widgets(): + class MyScreen(Screen[None]): + def compose(self): + yield Label() + yield Button() + + class MyApp(App[None]): + def on_mount(self): + self.push_screen(MyScreen()) + + app = MyApp() + async with app.run_test(): + assert app.focused is not None + assert isinstance(app.focused, Button) + + async def test_dismiss_non_top_screen(): class MyApp(App[None]): async def key_p(self) -> None: diff --git a/tests/toggles/test_radioset.py b/tests/toggles/test_radioset.py index 95025bf37b..51765b99e5 100644 --- a/tests/toggles/test_radioset.py +++ b/tests/toggles/test_radioset.py @@ -39,6 +39,7 @@ async def test_radio_sets_initial_state(): async def test_click_sets_focus(): """Clicking within a radio set should set focus.""" async with RadioSetApp().run_test() as pilot: + pilot.app.set_focus(None) assert pilot.app.screen.focused is None await pilot.click("#clickme") assert pilot.app.screen.focused == pilot.app.query_one("#from_buttons") @@ -72,8 +73,6 @@ async def test_radioset_same_button_mash(): async def test_radioset_inner_navigation(): """Using the cursor keys should navigate between buttons in a set.""" async with RadioSetApp().run_test() as pilot: - assert pilot.app.screen.focused is None - await pilot.press("tab") for key, landing in ( ("down", 1), ("up", 0), @@ -88,8 +87,6 @@ async def test_radioset_inner_navigation(): == pilot.app.query_one("#from_buttons").children[landing] ) async with RadioSetApp().run_test() as pilot: - assert pilot.app.screen.focused is None - await pilot.press("tab") assert pilot.app.screen.focused is pilot.app.screen.query_one("#from_buttons") await pilot.press("tab") assert pilot.app.screen.focused is pilot.app.screen.query_one("#from_strings") @@ -101,8 +98,6 @@ async def test_radioset_inner_navigation(): async def test_radioset_breakout_navigation(): """Shift/Tabbing while in a radioset should move to the previous/next focsuable after the set itself.""" async with RadioSetApp().run_test() as pilot: - assert pilot.app.screen.focused is None - await pilot.press("tab") assert pilot.app.screen.focused is pilot.app.query_one("#from_buttons") await pilot.press("tab") assert pilot.app.screen.focused is pilot.app.query_one("#from_strings")