google / mesop

Rapidly build AI apps in Python
https://google.github.io/mesop/
Apache License 2.0
5.29k stars 252 forks source link

Mouseover/out support #409

Open richard-to opened 3 months ago

richard-to commented 3 months ago

I may have use case where I want to use a mouseover trigger. I realize that the mouseover has the potential to be too spammy with its requests though. Haven't really considered how this could be implemented effectively.

richard-to commented 3 months ago

I think in some scenarios, the mouse over could be triggered just once. Then once the mouse out is called, then the mouse over would be allowed to trigger again.

So mouseover -> send API request Then if the mouse is still over the same element, then no additional requests will be sent (though perhaps can add an interval option) Then on mouseout, that could unlock the mouseover for that element.

But that may not work for all potential use cases. But it does work for the case where someone wants to display something when something is being hovered over.

I guess another issue is that we'd have to determine what components are allowed to have mouse over. Definitely box. But anything else?

wwwillchen commented 1 month ago

Since web components have been subsequently added, I'd probably just use that and avoid adding mouseover/out support to Mesop itself

cartographer1 commented 1 week ago

please, I think this belongs to some of the basic functionality needed to build ui that's as least somewhat... 'interactive'

wwwillchen commented 6 days ago

Is there a specific interaction that you're trying to build? Based on your other issue, it sounds like you went down the web component route which is what I'd recommend.

The problem with supporting this in Mesop natively is that it would result in a network roundtrip to handle each mouseover/out interaction which would add some latency and not be ideal UX-wise so we've been on the fence about supporting this.

cartographer1 commented 6 days ago

For those in need of similar functionalities, here is a basic div with event handlers for mouseover:

./web_components/hover_box.py

from typing import Callable, Any

import mesop.labs as mel

@mel.web_component(path="./js/hover_box.js")
def render(
    *,
    on_hover: Callable[[mel.WebEvent], Any],
    on_leave: Callable[[mel.WebEvent], Any],
    key: str | None = None
):
    return mel.insert_web_component(
        name="hover-box",
        key=key,
        events={"hoverEvent": on_hover, "leaveEvent": on_leave},
    )

./web_components/js/hover_box.js

import {html, LitElement} from 'https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-core.min.js';

export class HoverBox extends LitElement {
    static properties = {
        hoverEvent: {type: String},
        leaveEvent: {type: String},
    };

    constructor() {
        super();
    }

    render() {
        return html`
                <div class="hover container" @mouseover="${this._onHover}" @mouseleave="${this._onLeave}">
                <slot></slot>
            </div>
        `;
    }

    _onHover() {
        this.dispatchEvent(new MesopEvent(this.hoverEvent, {
            value: null,
        }))
    }

    _onLeave() {
        this.dispatchEvent(new MesopEvent(this.leaveEvent, {
            value: null,
        }))
    }
}

customElements.define('hover-box', HoverBox)