From 3da312192cded61052fa995af2be660c31e55845 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 9 Aug 2024 17:34:00 +0100 Subject: [PATCH 1/5] Add tooltip --- CHANGELOG.md | 6 ++++++ examples/markdown.py | 8 +++++++- src/textual/binding.py | 5 +++++ src/textual/screen.py | 8 ++++++-- src/textual/widgets/_classic_footer.py | 6 +++--- src/textual/widgets/_footer.py | 16 ++++++++++------ src/textual/widgets/_tooltip.py | 4 ++-- 7 files changed, 39 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1d794a8d7..e328426998 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 + +### Added + +- Added `tooltip` to Binding + ## [0.76.0] ### Changed diff --git a/examples/markdown.py b/examples/markdown.py index 2cf43e4399..25c0a83dfb 100644 --- a/examples/markdown.py +++ b/examples/markdown.py @@ -4,6 +4,7 @@ from sys import argv from textual.app import App, ComposeResult +from textual.binding import Binding from textual.reactive import var from textual.widgets import Footer, MarkdownViewer @@ -12,7 +13,12 @@ class MarkdownApp(App): """A simple Markdown viewer application.""" BINDINGS = [ - ("t", "toggle_table_of_contents", "TOC"), + Binding( + "t", + "toggle_table_of_contents", + "TOC", + tooltip="Toggle the Table of Contents panel", + ), ("b", "back", "Back"), ("f", "forward", "Forward"), ] diff --git a/src/textual/binding.py b/src/textual/binding.py index 9a396478a4..3b0825d8a2 100644 --- a/src/textual/binding.py +++ b/src/textual/binding.py @@ -50,6 +50,8 @@ class Binding: """How the key should be shown in footer.""" priority: bool = False """Enable priority binding for this key.""" + tooltip: str = "" + """Optional tooltip to show in footer.""" class ActiveBinding(NamedTuple): @@ -61,6 +63,8 @@ class ActiveBinding(NamedTuple): """The binding information.""" enabled: bool """Is the binding enabled? (enabled bindings are typically rendered dim)""" + tooltip: str = "" + """Optional tooltip shown in Footer.""" @rich.repr.auto @@ -112,6 +116,7 @@ def make_bindings(bindings: Iterable[BindingType]) -> Iterable[Binding]: show=bool(binding.description and binding.show), key_display=binding.key_display, priority=binding.priority, + tooltip=binding.tooltip, ) self.key_to_bindings: dict[str, list[Binding]] = {} diff --git a/src/textual/screen.py b/src/textual/screen.py index f03bbca593..0519ee585d 100644 --- a/src/textual/screen.py +++ b/src/textual/screen.py @@ -348,10 +348,14 @@ def active_bindings(self) -> dict[str, ActiveBinding]: binding.priority and not existing_key_and_binding.binding.priority ): - bindings_map[key] = ActiveBinding(namespace, binding, enabled) + bindings_map[key] = ActiveBinding( + namespace, binding, enabled, binding.tooltip + ) else: # New binding - bindings_map[key] = ActiveBinding(namespace, binding, enabled) + bindings_map[key] = ActiveBinding( + namespace, binding, enabled, binding.tooltip + ) return bindings_map diff --git a/src/textual/widgets/_classic_footer.py b/src/textual/widgets/_classic_footer.py index d8df547300..5b1b5cffae 100644 --- a/src/textual/widgets/_classic_footer.py +++ b/src/textual/widgets/_classic_footer.py @@ -108,15 +108,15 @@ def _make_key_text(self) -> Text: description_style = self.get_component_rich_style("footer--description") bindings = [ - (binding, enabled) - for (_, binding, enabled) in self.screen.active_bindings.values() + (binding, enabled, tooltip) + for (_, binding, enabled, tooltip) in self.screen.active_bindings.values() if binding.show ] action_to_bindings: defaultdict[str, list[tuple[Binding, bool]]] = defaultdict( list ) - for binding, enabled in bindings: + for binding, enabled, _ in bindings: action_to_bindings[binding.action].append((binding, enabled)) app_focus = self.app.app_focus diff --git a/src/textual/widgets/_footer.py b/src/textual/widgets/_footer.py index 0cd93ece70..04ac4abbc3 100644 --- a/src/textual/widgets/_footer.py +++ b/src/textual/widgets/_footer.py @@ -84,6 +84,7 @@ def __init__( description: str, action: str, disabled: bool = False, + tooltip: str = "", ) -> None: self.key = key self.key_display = key_display @@ -91,6 +92,8 @@ def __init__( self.action = action self._disabled = disabled super().__init__(classes="-disabled" if disabled else "") + if tooltip: + self.tooltip = tooltip def render(self) -> Text: key_style = self.get_component_rich_style("footer-key--key") @@ -160,24 +163,25 @@ def compose(self) -> ComposeResult: if not self._bindings_ready: return bindings = [ - (binding, enabled) - for (_, binding, enabled) in self.screen.active_bindings.values() + (binding, enabled, tooltip) + for (_, binding, enabled, tooltip) in self.screen.active_bindings.values() if binding.show ] - action_to_bindings: defaultdict[str, list[tuple[Binding, bool]]] + action_to_bindings: defaultdict[str, list[tuple[Binding, bool, str]]] action_to_bindings = defaultdict(list) - for binding, enabled in bindings: - action_to_bindings[binding.action].append((binding, enabled)) + for binding, enabled, tooltip in bindings: + action_to_bindings[binding.action].append((binding, enabled, tooltip)) self.styles.grid_size_columns = len(action_to_bindings) for multi_bindings in action_to_bindings.values(): - binding, enabled = multi_bindings[0] + binding, enabled, tooltip = multi_bindings[0] yield FooterKey( binding.key, binding.key_display or self.app.get_key_display(binding.key), binding.description, binding.action, disabled=not enabled, + tooltip=tooltip, ).data_bind( Footer.upper_case_keys, Footer.ctrl_to_caret, diff --git a/src/textual/widgets/_tooltip.py b/src/textual/widgets/_tooltip.py index afe64d11d4..77aa9fd953 100644 --- a/src/textual/widgets/_tooltip.py +++ b/src/textual/widgets/_tooltip.py @@ -8,13 +8,13 @@ class Tooltip(Static, inherit_css=False): Tooltip { layer: _tooltips; margin: 1 2; - padding: 1 2; + padding: 1 2 1 2; background: $panel; width: auto; height: auto; constrain: inflect; max-width: 40; - display: none; + display: none; } """ DEFAULT_CLASSES = "-textual-system" From ca39cabe8b960530fc8ee51e1b59aa138672785a Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 9 Aug 2024 17:35:21 +0100 Subject: [PATCH 2/5] remove tooltip from example --- examples/markdown.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/markdown.py b/examples/markdown.py index 25c0a83dfb..7ff9193d17 100644 --- a/examples/markdown.py +++ b/examples/markdown.py @@ -13,12 +13,7 @@ class MarkdownApp(App): """A simple Markdown viewer application.""" BINDINGS = [ - Binding( - "t", - "toggle_table_of_contents", - "TOC", - tooltip="Toggle the Table of Contents panel", - ), + Binding("t", "toggle_table_of_contents", "TOC"), ("b", "back", "Back"), ("f", "forward", "Forward"), ] From 04d8a7a252d18e26e8b8e0ed5bc7bf8bd4949bfe Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 9 Aug 2024 17:38:08 +0100 Subject: [PATCH 3/5] revert edit --- src/textual/widgets/_tooltip.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/textual/widgets/_tooltip.py b/src/textual/widgets/_tooltip.py index 77aa9fd953..afe64d11d4 100644 --- a/src/textual/widgets/_tooltip.py +++ b/src/textual/widgets/_tooltip.py @@ -8,13 +8,13 @@ class Tooltip(Static, inherit_css=False): Tooltip { layer: _tooltips; margin: 1 2; - padding: 1 2 1 2; + padding: 1 2; background: $panel; width: auto; height: auto; constrain: inflect; max-width: 40; - display: none; + display: none; } """ DEFAULT_CLASSES = "-textual-system" From 80afcf2539c54214402924681ac256069d0954f1 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 9 Aug 2024 17:39:54 +0100 Subject: [PATCH 4/5] revert edit --- examples/markdown.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/markdown.py b/examples/markdown.py index 7ff9193d17..2cf43e4399 100644 --- a/examples/markdown.py +++ b/examples/markdown.py @@ -4,7 +4,6 @@ from sys import argv from textual.app import App, ComposeResult -from textual.binding import Binding from textual.reactive import var from textual.widgets import Footer, MarkdownViewer @@ -13,7 +12,7 @@ class MarkdownApp(App): """A simple Markdown viewer application.""" BINDINGS = [ - Binding("t", "toggle_table_of_contents", "TOC"), + ("t", "toggle_table_of_contents", "TOC"), ("b", "back", "Back"), ("f", "forward", "Forward"), ] From 0135a20eb652b7b39bdc752a58d693d9a68cefb8 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Fri, 9 Aug 2024 18:12:11 +0100 Subject: [PATCH 5/5] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e328426998..45262df670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added -- Added `tooltip` to Binding +- Added `tooltip` to Binding https://github.com/Textualize/textual/pull/4859 ## [0.76.0]