Drag
Drag="true" is the entire opt-in. Everything after that is a refinement of the same gesture: which axes it may use, how far it may go, how it behaves at the edges, what happens to the momentum when you let go, and which part of the element is allowed to start it. Drag runs on the per-frame engine, so it is a Blazor WebAssembly feature; on Blazor Server the element simply does not move.
Axes and constraints
Drag="BmDrag.X" or BmDrag.Y locks the gesture to one axis, and
DragConstraints bounds how far it may travel.
DragElastic is what happens past that bound: 0 is a hard wall,
1 is no resistance at all, and the values in between let the element overshoot
against increasing resistance and spring back on release.
Constrain to a container
Numeric bounds mean re-deriving them every time the layout changes. Element bounds do not:
BmDragConstraints.Parent() keeps the element inside its parent and
BmDragConstraints.Within(".selector") inside any container you name. Either is
measured at each drag start - and re-measured live if the container resizes mid-drag - so a
responsive layout needs no extra work.
Momentum and fling
A drag that stops dead where your finger lifted feels like a bug. DragMomentum (on by default) carries the release velocity into an inertia animation that decelerates on its own; DragTransition replaces the spring it settles with. DragSnapToOrigin ignores the momentum entirely and springs the element home, which is the right answer for a card you swipe to dismiss. DragDirectionLock commits to whichever axis the gesture starts on and ignores the other for the rest of it - the behaviour a scrollable list wants from a two-axis drag.
Snapping on release
Momentum answers how fast the element stops; modifyTarget answers
where. A DragTransition written as an inertia hands the projected
resting position to your function and uses whatever comes back, which is the whole of
carousel paging and grid snapping. Bm.SnapTo(step) rounds to a grid,
Bm.SnapTo([…]) picks the nearest of a fixed set of stops. With one
set, even a slow release still travels to the nearest stop - and the snap is applied before
the constraints, so it can never land outside them.
Handles and drag controls
Making a whole row draggable costs you every click and text selection inside it.
DragHandle restricts the gesture to a grip within the element and leaves
the rest alone. BmDragControls inverts the relationship: some
other element starts the drag - pair it with DragListener="false" so
the controls are the only trigger, and pressing anywhere on a track grabs its thumb.
BmDragElastic.Edges tunes the give per edge, so a panel can be rigid where
it docks and springy where it does not.
Drag events
OnDragStart and OnDragEnd bracket the gesture, and
OnDrag fires throughout it - enough to persist a position, mark a form dirty,
or light up a drop target. For the pointer's actual coordinates and velocity, use the pan
callbacks on the gestures page.
Nested drag and propagation
A draggable inside a draggable is ambiguous, so Bmotion resolves it the way motion.dev does: the child stops propagation and only the child moves. Set DragPropagation="true" on the child when you want the gesture to reach the parent as well and both to travel together.