Documentation menu
Concepts

Draggable

A draggable is any element that can be picked up and moved. Wrap it in DndDraggable, give it a stable DndId, and the engine handles the pointer, keyboard, and transform.

You'll learn
  • How to make an element draggable.
  • How to restrict the drag surface to a handle.
  • How to require intent before a drag begins.
  • Which events fire over a drag lifecycle.

Usage

Every draggable needs a unique DndId within its scope. The id is how collision results and drag events refer back to it.

draggable.dart
DndDraggable(
  id: const DndId('card-1'),
  data: card, // optional payload carried through the drag
  child: CardTile(card),
)

Drag handles

Wrap part of the child in a DndDragHandle to make only that part the drag surface — useful when the rest of the element stays interactive (links, buttons, text selection).

handle.dart
DndDraggable(
  id: const DndId('card-1'),
  child: Row(
    children: [
      DndDragHandle(
        label: 'Reorder card',
        child: const Icon(Icons.drag_indicator),
      ),
      const Expanded(child: Text('Card title')),
    ],
  ),
)

Activation

Pass a DndSensorActivationConstraint so a drag only starts after deliberate intent — a small distance or a press delay — instead of on the first pixel of movement. This keeps taps and clicks responsive.

activation.dart
DndDraggable(
  id: const DndId('card-1'),
  constraint: const DndSensorActivationConstraint(distance: 6),
  child: CardTile(card),
)

Drag events

A draggable reports its lifecycle through callbacks:

  • onDragStart — the drag was activated and picked up.
  • onDragUpdate — the pointer moved; the active transform changed.
  • onDragEnd — the drag finished; read event.overId for the target it landed on, or handle a cancel.