Skip to content

use_mouse

use_mouse gives a component the state of the mouse wherever it is on the screen: where it is, how far it just moved, and which button is held. Each mouse move or press renders the component again with the new state.

@component
def pointer() -> Div:
    mouse = use_mouse()
    is_on_screen = mouse.absolute.x >= 0

    return Div(
        style=full,
        children=(
            Text(
                content=(
                    f"At {mouse.absolute.x},{mouse.absolute.y}"
                    f", moved {mouse.motion.x:+},{mouse.motion.y:+}"
                    f", button {mouse.button}"
                ),
                style=text_color("slate", 400),
            ),
            *(
                (
                    Text(
                        content="●" if mouse.button is not None else "◆",
                        style=position_absolute
                        | inset_left(mouse.absolute.x)
                        | inset_top(mouse.absolute.y)
                        | text_color("red" if mouse.button is not None else "amber", 400),
                    ),
                )
                if is_on_screen
                else ()
            ),
        ),
    )

The pointer at 12,4, having moved by +2,+1, with a diamond drawn under it

At 12,4, moved +2,+1, button None       



            ◆                           

The pointer at 13,5 with button 1 held, and a dot drawn under it

At 13,5, moved +3,+2, button 1          




             ●                          

The marker follows the pointer, and turns into a dot while a button is held:

absolute counts cells from the top-left corner of the screen, whatever component reads it. To find the mouse within an element, subtract the element's position from use_rects, as in mouse.absolute - rects.content.top_left. Until the mouse first moves over the app, absolute is Position(-1, -1), off the screen, which is why pointer checks is_on_screen before drawing the marker.

Every component that calls use_mouse renders again on every move of the mouse, wherever it is, so call it in the small component that shows the mouse, not in one that renders much else. To know only whether the mouse is over a component, use use_hovered.

use_mouse vs. on_input

use_mouse and an element's on_input handler both see the mouse, but use_mouse is a hook and on_input is an event handler. use_mouse is more efficient when a component depends only on the current state of the mouse (e.g., the current position, or whether a button is currently pressed), while on_input is more convenient when a component needs to respond to changes in the mouse state, (e.g., a button release (MouseUp). use_mouse sees every change, while a handler sees only the events routed to its element. See the draggable components recipe for a handler that follows the mouse.

API

counterweight.hooks.use_mouse

use_mouse() -> Mouse
RETURNS DESCRIPTION
Mouse

A record describing the current state of the mouse.

counterweight.hooks.Mouse dataclass

Mouse(
    absolute: Position, motion: Position, button: int | None
)

Where the mouse is and which button is held, as use_mouse returns it.

absolute instance-attribute

absolute: Position

The absolute position of the mouse on the screen (i.e., the top-left corner of the screen is Position(x=0, y=0)).

motion instance-attribute

motion: Position

The difference in the absolute position of the mouse since the last render cycle.

button instance-attribute

button: int | None

The button that is currently pressed, or None if no button is pressed.