Skip to main content

Overview

Sensors detect user input and translate it into drag and drop operations. The defaults work well out of the box — PointerSensor (mouse, touch, pen) and KeyboardSensor are both registered automatically on every DragDropProvider. You only need this guide when you want to customize when and how drags activate.
Sensors are part of @dnd-kit/dom and are imported from there:

Where to configure sensors

Sensors can be configured at three different levels: Per-draggable sensors take precedence over global sensors.

Customizing PointerSensor

PointerSensor handles mouse, touch, and pen input via the native Pointer Events API. It exposes three options: activationConstraints, activatorElements, and preventActivation.

Activation constraints

Activation constraints control when a drag starts. Provide either an array of constraint instances, or a function that returns constraints based on the event.
When multiple constraints are provided, the drag activates as soon as any one is satisfied.

Per-pointer-type behavior

Pass a function to activationConstraints to branch on event.pointerType ('mouse', 'touch', or 'pen'). This is the recommended way to give touch and mouse different activation behavior:
Returning undefined from the function means no activation constraints — the drag starts immediately on pointerdown. The default behavior is not restored; if you want the defaults for a given pointer type, return those constraints explicitly.

Drag handles via activator elements

By default, the sensor binds pointerdown to the draggable’s handle (if set on the hook) or its main element. Use activatorElements to designate a different element — useful when you want to render a separate “drag” affordance outside the draggable’s DOM subtree.
For the common case — a drag handle inside the draggable element — pass a handle ref directly to useDraggable or useSortable instead. activatorElements is for the less common case where the activator lives outside the source element.

Preventing accidental drags

The preventActivation callback returns true to skip a pointerdown event. By default, it returns true when the target is an interactive element (<button>, <input>, <a>, etc.) that isn’t part of the handle — so clicks on buttons inside a draggable card don’t start a drag.

Customizing KeyboardSensor

KeyboardSensor enables keyboard-driven drag and drop for accessibility. It activates when a focused draggable receives a configured “start” keydown event.

Custom key bindings

Key bindings follow KeyboardEvent.key values so they respect keyboard layouts and operating system key remaps. Use values such as w, Enter, and ArrowUp. The Space alias is also supported for the Space key. When migrating older KeyboardEvent.code configs, common Key* and Digit* values such as KeyW and Digit1 still normalize for compatibility. Other physical key codes, such as NumpadEnter, BracketLeft, or Slash, should be replaced with the key value they produce. Other named keys must match KeyboardEvent.key casing.

Keyboard movement offset

The offset option controls how many pixels each arrow key press moves the dragged element. Hold Shift to multiply the offset by 5.

Preventing keyboard activation

By default, the keyboard sensor only activates when the focused element is the draggable’s handle (or its element if no handle is set). Override preventActivation to customize:

Per-draggable sensors

Both useDraggable and useSortable accept a sensors option that applies only to that element. Per-draggable sensors override global ones.

Replacing vs. extending defaults

The sensors prop on DragDropProvider accepts either an array (replaces defaults entirely) or a function that receives the defaults (lets you extend them).
If you replace the defaults with an array, double-check you’re including KeyboardSensor — leaving it out removes keyboard accessibility.

Migrating from MouseSensor and TouchSensor

The legacy @dnd-kit/core package had separate MouseSensor and TouchSensor classes. They’re consolidated into one PointerSensor here. To replicate the old per-input-type behavior, branch on event.pointerType inside activationConstraints (see Per-pointer-type behavior above), or read the Migration guide for the full mapping.