loading

Gestures

Gesture states are overlays, not replacements. WhileHover, WhileTap, WhileFocus, WhileDrag and WhileInView layer on top of whatever Animate is currently showing and revert themselves the moment the gesture ends - so you never write the "back to normal" animation, and overlapping gestures resolve without any state of your own.

Hover and tap

The two workhorses. Both take an ordinary target, so anything animatable is fair game - here a lift with a coloured shadow, and a press that scales down. Tap is keyboard-accessible out of the box: give the element focus and Enter or Space presses and releases it exactly like a pointer, WhileTap included. Natively focusable elements get this for free; anything else needs tabindex="0", as the first stage does.

Hover to lift · tab to it and press Space
A real button, unchanged
Razor

Focus

WhileFocus plays while the element or any of its descendants holds focus. It is the accessible half of a hover effect: keyboard users get the same affordance pointer users do, without a second code path.

Tab into the field
Razor

Pan

A pan is a pointer drag reported rather than applied: OnPan hands you a BmPanInfo - the pointer position, the delta since the last event, the total offset since the gesture began and the current velocity in pixels per second - and leaves the element where it is. That is the hook for building your own drag behaviour (a custom slider, a swipe-to-dismiss threshold) on top of the same gesture plumbing Drag uses.

Drag across the box - it does not move
offset  x 0 · y 0
velocity x 0 · y 0
idle
Razor

Gesture events

Every gesture also reports itself as a callback, so an animation can be paired with real work. Note the ordering below: TapCancel fires instead of Tap when the pointer leaves the element before release - which is what makes a press cancellable, and why you should act on OnTap rather than OnTapStart.

Press, then release off the box to cancel
No events yet.
Razor

Nested gestures

Pointer gestures bubble, so a tappable button inside a tappable card presses both. That is usually right - a card that reacts to being pressed anywhere feels alive - but not when the inner control has its own meaning. GesturePropagation="false" on the child stops its tap and pan from reaching gesture-enabled ancestors, exactly as DragPropagation does for drag. Press each button and watch the card behind it.

Hover is unaffected either way: pointerenter and pointerleave do not bubble, so a child's hover was never its parent's problem.

propagates (default)
GesturePropagation="false"
Razor

Owning the transform string

Bmotion composes one transform from every animated component, in a fixed order. TransformTemplate hands that string back to you before it is written - useful when the element already needs a transform of its own that the animation must not clobber. The classic case is an element centred on its own anchor with translate(-50%, -50%): leave it in the CSS and the animation overwrites it, so put it in the template instead and it survives every frame.

without a template - the pin slips
template keeps it centred
Razor
Bmotion 0 el · 0 active
An unhandled error has occurred. Reload 🗙