CSS focus-within

This commit is contained in:
Darren Burns
2022-05-05 14:46:20 +01:00
parent e382fc14b1
commit d0ed7ef826
5 changed files with 38 additions and 6 deletions

View File

@@ -1,3 +1,7 @@
App.-show-focus *:focus {
tint: #8bc34a 50%;
}
#uber1 {
layout: vertical;
background: green;
@@ -5,8 +9,12 @@
border: heavy white;
}
#uber1:focus-within {
background: darkslateblue;
}
.list-item {
height: 8;
height: 10;
color: #12a0;
background: #ffffff00;
}

View File

@@ -15,15 +15,16 @@ class BasicApp(App):
self.bind("d", "dump")
self.bind("t", "log_tree")
self.bind("p", "print")
self.bind("o", "toggle_visibility")
self.bind("p", "toggle_display")
self.bind("v", "toggle_visibility")
self.bind("x", "toggle_display")
self.bind("f", "modify_focussed")
self.bind("b", "toggle_border")
async def on_mount(self):
"""Build layout here."""
first_child = Placeholder(id="child1", classes="list-item")
uber1 = Widget(
first_child,
Placeholder(id="child1", classes="list-item"),
Placeholder(id="child2", classes="list-item"),
Placeholder(id="child3", classes="list-item"),
@@ -32,6 +33,8 @@ class BasicApp(App):
Placeholder(classes="list-item"),
)
self.mount(uber1=uber1)
self.first_child = first_child
self.uber = uber1
async def on_key(self, event: events.Key) -> None:
await self.dispatch_key(event)
@@ -51,8 +54,7 @@ class BasicApp(App):
self.screen.tree,
sep=" - ",
)
print(1234, 5678)
sys.stdout.write("abcdef")
self.app.set_focus(None)
def action_modify_focussed(self):
"""Increment height of focussed child, randomise border and bg color"""

View File

@@ -536,16 +536,19 @@ class App(Generic[ReturnType], DOMNode):
# No focus, so blur currently focused widget if it exists
if self.focused is not None:
self.focused.post_message_no_wait(events.Blur(self))
self.focused.emit_no_wait(events.DescendantBlur(self))
self.focused = None
elif widget.can_focus:
if self.focused != widget:
if self.focused is not None:
# Blur currently focused widget
self.focused.post_message_no_wait(events.Blur(self))
self.focused.emit_no_wait(events.DescendantBlur(self))
# Change focus
self.focused = widget
# Send focus event
widget.post_message_no_wait(events.Focus(self))
widget.emit_no_wait(events.DescendantFocus(self))
async def _set_mouse_over(self, widget: Widget | None) -> None:
"""Called when the mouse is over another widget.

View File

@@ -393,3 +393,11 @@ class Focus(Event, bubble=False):
class Blur(Event, bubble=False):
pass
class DescendantFocus(Event, bubble=True):
pass
class DescendantBlur(Event, bubble=True):
pass

View File

@@ -98,6 +98,7 @@ class Widget(DOMNode):
auto_width = Reactive(True)
auto_height = Reactive(True)
has_focus = Reactive(False)
descendant_has_focus = Reactive(False)
mouse_over = Reactive(False)
scroll_x = Reactive(0.0, repaint=False)
scroll_y = Reactive(0.0, repaint=False)
@@ -424,6 +425,8 @@ class Widget(DOMNode):
yield "hover"
if self.has_focus:
yield "focus"
if self.descendant_has_focus:
yield "focus-within"
def watch(self, attribute_name, callback: Callable[[Any], Awaitable[None]]) -> None:
watch(self, attribute_name, callback)
@@ -721,11 +724,19 @@ class Widget(DOMNode):
self.mouse_over = True
def on_focus(self, event: events.Focus) -> None:
self.emit_no_wait(events.DescendantFocus(self))
self.has_focus = True
def on_blur(self, event: events.Blur) -> None:
self.emit_no_wait(events.DescendantBlur(self))
self.has_focus = False
def on_descendant_focus(self, event: events.DescendantFocus) -> None:
self.descendant_has_focus = True
def on_descendant_blur(self, event: events.DescendantBlur) -> None:
self.descendant_has_focus = False
def on_mouse_scroll_down(self, event) -> None:
if self.is_container:
self.scroll_down(animate=False)