Docs/API

Sensors

What turns input into drags — the built-in pointer and keyboard sensors, and the API to write your own.

import { defineSensor, useSensor, pointerSensor, keyboardSensor } from '@vue-dnd-kit/core';
Sensor

Mouse, touch and pen via Pointer Events. In sensors by default.

Sensor

Space/Enter, arrows and Escape (rebound with the provider's keyboard option). In sensors by default; it also cancels pointer and custom drags with Escape, even with keyboard: false.

(sensor: Sensor) => Sensor

Defines a sensor (see Sensor): it only helps with the types and returns its argument.

(sensor: Sensor) => void

Runs a sensor in the provider above for as long as the calling component (or effect scope) lives, next to the provider's sensors. Its drag is cancelled when it unmounts.

A sensor only says "drag this item from here", then where it moved and that it dropped or was cancelled; the provider checks the rest (what may be dragged, activation, one drag at a time). See Sensors and programmatic drags.

Below, a small custom sensor (run with useSensor) drags the board's pieces from its minimap, next to the provider's own sensors.

Live

Loading the demo…

<script setup lang="ts">
import { DnDProvider } from '@vue-dnd-kit/core';
import SensorDesk from './SensorDesk.vue';
</script>

<template>
  <DnDProvider>
    <SensorDesk />
  </DnDProvider>
</template>

Sensor

Input that starts drags: pointer, keyboard, or your own (a gamepad, an on-screen joystick, voice, scripted drags). setup runs once per provider, in the browser only, inside an effect scope that ends with the provider (or when the sensor leaves sensors, or the component that called useSensor unmounts). Register listeners with useEventListener or return a cleanup; a drag still running then is cancelled.

To wrap a sensor, run its setup with a context of your own. Object.create(context, { activate: { value: … } }) keeps the live getters (status, drag, props): a spread would freeze them.

string

For debugging.

(context: SensorContext) => void | (() => void)

Starts listening to the input, once per provider: call context.activate() when it wants to drag. May return a cleanup, run when the sensor stops.

What a sensor gets from the provider it runs in.

Readonly<DnDProviderProps>

The provider's props (e.g. activation, keyboard). Read them when needed: they may change.

DnDStatus

The provider's drag status, whichever sensor runs the drag.

SensorDrag | null

The provider's drag, pending or dragging, whichever sensor started it; null when there is none. Sensors may drive each other's drags: the keyboard sensor moves and drops every keyboard drag, e.g. one a "Move" button picked up (@vue-dnd-kit/actions).

(activation: SensorActivation) => SensorDrag | null

Asks to drag an item. The provider checks that it is idle (one drag at a time, none while a drop lands), that the target is a draggable of its own that isn't disabled, where the input landed (see target) and the draggable's canDrag, then waits for the activation constraint and starts the drag. Returns the drag (pending, or already dragging when there is nothing to wait for), or null when no drag may start.

() => void

Cancels the provider's drag or pending activation, whichever sensor runs it (Escape, a hidden tab).

Activation

What a sensor asks for when its input wants to drag (SensorContext.activate()).

Element | Key

Where the input landed: an element inside a draggable, or the id of a draggable. An element must belong to this provider; for 'pointer' drags it must be on the handle when there is one and not on an interactive child (a button, an input), for 'keyboard' drags it must be the draggable's focus target (the handle, else the draggable itself) and not an editable field. An id skips these checks: the drag starts from the item wherever the input was.

SensorType

How the drag moves. 'pointer' (default): it follows the points given to move(), targets are hit-tested there, containers auto-scroll at their edges and the page shows the grabbing cursor. 'keyboard': it moves by items with step() and place() as arrow keys do, targets are revealed instead of auto-scrolled, and the focus goes back to the item when it ends. Active.sensor tells which.

Coordinates

Where the drag starts, in viewport coordinates. Default: the center of the draggable.

PointerEvent | KeyboardEvent

The input event. It is handed to the draggable's canDrag: without one (a gamepad, a programmatic drag), canDrag isn't asked. A pointerType of 'touch' makes the drag a touch drag (haptics).

PointerKind | ActivationConstraint

What the drag waits for before it starts (useDnD().status is 'activating' until then, with its progress). A pointer kind reads the draggable's activation option for it, then the provider's, then the defaults (mouse 4px, at once on a handle; pen 4px; touch a 200ms long press with 5px tolerance). A constraint is used as it is. Default: none, the drag starts at once.

(drag: SensorDrag) => void

The drag started, after its activation: e.g. capture the pointer.

(drag: SensorDrag) => void

The drag is over: its activation was aborted, or it dropped or was cancelled (by anyone).

(drag: SensorDrag) => void

The drop the sensor asked for didn't happen and the drag goes on (onBeforeDrop answered 'continue'): move, drop and cancel apply again. A pointer sensor lets the item follow the pointer until the next release.

Per pointer kind. Defaults: mouse { distance: 4 } (immediate on a handle), pen { distance: 4 }, touch { delay: 200, tolerance: 5 }.

type ActivationOptions = Partial< Record<PointerKind, ActivationConstraint> >

What a press must do before it becomes a drag: travel distance, or be held for delay, whichever comes first. Nothing set: the drag starts at once.

number

Pixels the pointer must travel before the drag starts.

number

Milliseconds the pointer must be held before the drag starts.

number

With delay: movement in px that aborts activation, so the page can scroll.

The drag

One drag of a sensor, from activate() until it ends. Every call is ignored once it no longer applies: moves before the start or after the end, a second drop().

Key

Id of the dragged item.

SensorType

How the drag moves, as activate() asked (SensorActivation.type).

SensorDragState

Where the drag is: waiting for its activation, dragging, or ended.

boolean

The drag started, even if it has ended since (the pointer sensor swallows the click that follows it).

(point: Coordinates) => void

The input moved. While pending, the activation constraint is checked (moving past its tolerance aborts it); while dragging, the drag goes there. Pointer drags take one position per frame; keyboard drags move at once, after the steps before them.

(direction: SensorDirection, options?: SensorStepOptions) => Promise<void>

Keyboard drags: one arrow step, as the keyboard sensor's arrow keys do (the next item of a list, the next accepting target in 'droppables' mode, or keyboard.step pixels). Steps queue: each runs once the one before has rendered, and a repeated key (event.repeat) is skipped while one still resolves. Pointer drags ignore it.

(position: SortablePosition) => Promise<boolean>

Puts the item at a position of a sortable list, as keyboard moves do (other lists take it only if they accept it), and moves the drag to its new place. Resolves false when no list takes it there. Queued like step() in keyboard drags.

() => Promise<boolean>

Drops: a pending activation is aborted instead. Resolves once the drag has ended and landed: true when the drop went through, false when it was refused (a target, onBeforeDrop) or there was nothing to drop.

() => void

Cancels the drag (it flies back), or aborts a pending activation.

  • 'pending': waiting for the activation constraint;
  • 'dragging': from the start until the drop is decided or the drag is cancelled;
  • 'ended': the activation was aborted, or the drag dropped or was cancelled, by the sensor or by anything else (Escape, a hidden tab, useDnD().cancel(), the provider unmounting).
type SensorDragState = 'pending' | 'dragging' | 'ended'

Options of SensorDrag.step().

KeyboardEvent

The key press, handed to monitors' getKeyboardCoordinates. Default: a keydown of the arrow key.

boolean

A bigger step in free drags (as Shift). Default: event.shiftKey.

Arrow of a keyboard step.

type SensorDirection = 'up' | 'down' | 'left' | 'right'

A position in a sortable list, for SensorDrag.place() (and moveItem of @vue-dnd-kit/actions). Lists only: trees place items by their own keys.

Key

Id of the list (SortableListOptions.id). Default: the list the item is in.

number

Index the item ends up at, counted without the item itself (a multi-drag block counts once). Clamped to the list; default: the end.