Open JovanVeljanoski opened 6 months ago
Hey Jovan!
You're right, it isn't natively possible to link key presses to interactions with an element. I suppose you could in principle accomplish it via a component_vue
to inject some code that does this on the front-end with javascript. You would have to identify the elements you're trying to link to manually, which would most likely be a bother though... In case it helps with your use-case, you can bind keystrokes to functions using the use_change
-hook, defined here: https://github.com/widgetti/solara/blob/86fd5dd27da24e0faa739024c296a2359be7dca8/solara/components/input.py#L14-L36
You can see how we use it (sorry to quote chat.py
to you twice in a day :) ) to hook up events to ChatInput
here: https://github.com/widgetti/solara/blob/86fd5dd27da24e0faa739024c296a2359be7dca8/solara/lab/components/chat.py#L86-L90
What about putting something like this in solara.lab?
from typing import Callable
import solara
show_dialog = solara.reactive(False)
@solara.component_vue("hotkey.vue")
def HotKey(
key: str,
ctrl: bool = False,
shift: bool = False,
meta: bool = False,
prevent_default: bool = False,
event_pressed: Callable[[], None] = None,
): ...
@solara.component
def Page():
with solara.Column() as main:
solara.InputText("No focus")
solara.InputText("No focus")
solara.Button("Show dialog", on_click=lambda: show_dialog.set(True))
with solara.v.Dialog(
v_model=show_dialog.value,
on_v_model=show_dialog.set,
persistent=True,
max_width="500px",
):
with solara.v.Sheet(class_="pa-4") as sheet:
solara.InputText("No focus")
solara.InputText("No focus")
close = solara.Button("Close", on_click=lambda: show_dialog.set(False))
def close_dialog_on_q(widget, event, data):
print("event", event)
# if event.key == "Escape":
show_dialog.set(False)
HotKey(key="q", ctrl=True, event_pressed=lambda ignore: show_dialog.set(False))
HotKey(key="o", event_pressed=lambda ignore: show_dialog.set(True))
// hotkey.vue
<template>
<span style="display: none;">key {{key}}</span>
</template>
<script>
module.exports = {
mounted() {
console.log("mounted", this.key)
document.addEventListener('keydown', this.hotkeyPress);
},
destroyed() {
document.removeEventListener('keydown', this.hotkeyPress);
},
methods: {
hotkeyPress: function(e) {
if (e.key === this.key) {
console.log("key", this.key, e.key, e)
if(this.metaKey && !e.metaKey) {
return
}
if(this.ctrl && !e.ctrlKey) {
return
}
if(this.shift && !e.shiftKey) {
return
}
if(this.alt && !e.altKey) {
return
}
if(this.meta && !e.metaKey) {
return
}
if(this. prevent_default) {
e.preventDefault()
}
console.log("pressed", this.key)
this.pressed()
}
}
}
};
</script>
@JovanVeljanoski you can use this now in your app, and see if a pattern like this works for you, we can iterate on it and see if we want it in lab based on your feedback.
Hi,
Thanks for these examples!
@iisakkirotko - with a simple example (actually trying to modify the example provided by @maartenbreddels ), i could not get the use_chage
to work. I understand what should be happening but I am doing something wrong perhaps..
@maartenbreddels that is a nice idea indeed. Works well, and if it was already in solara.lab
it would be even better.
One comment I would add -> an adjustment so one can use the enter/return key (without any other key, i guess like in the chat component) would be great!
Otherwise I like this approach!
Some other small feedback (can be ignored ofc)
In the HotKey
function above, it would be nice if the event_pressed
has the same behaviour as on_click
from a button component for consistency.
Made some minor improvements, and made the event handler on_pressed
take no arguments (assuming you meant that):
https://py.cafe/maartenbreddels/solara-hotkeys
It also shows you can use the escape or enter keycode.
Great! This works very nice!
Although, at least for me, only the changes in hotkey.vue
where needed, the rest work very well with the python code from earlier.
Thanks - feel free to close this. Would be great if something like this is one day in solara(.lab).
Cheers!
Would it be possible to make keys / key-bindings / correspond to button clicks. I.e. one button can be linked to
Return
, another to arrow-key, etc..