Skip to main content

Overview

Sensors detect and handle input events to initiate and control drag operations. The @dnd-kit/dom package includes two built-in sensors:
  • PointerSensor - Handles mouse, touch, and pen interactions
  • KeyboardSensor - Handles keyboard-based dragging
Both sensors are included in the default preset.

PointerSensor

Handles pointer events including mouse, touch, and pen input.

Options

import { PointerSensor } from '@dnd-kit/dom';

const manager = new DragDropManager({
  sensors: [
    PointerSensor.configure({
      activationConstraints: ...,
      activatorElements: ...,
      preventActivation: ...
    })
  ]
});
options
PointerSensorOptions

Default Behavior

The PointerSensor has intelligent defaults:
PointerSensor.defaults = {
  activationConstraints(event, source) {
    const { pointerType, target } = event;

    // Mouse on handle: activate immediately
    if (pointerType === 'mouse' && (source.handle === target || source.handle?.contains(target))) {
      return undefined;
    }

    // Touch: 250ms delay with 5px tolerance
    if (pointerType === 'touch') {
      return [new PointerActivationConstraints.Delay({ value: 250, tolerance: 5 })];
    }

    // Text input: 200ms delay with no movement
    if (isTextInput(target)) {
      return [new PointerActivationConstraints.Delay({ value: 200, tolerance: 0 })];
    }

    // Default: 200ms delay or 5px distance
    return [
      new PointerActivationConstraints.Delay({ value: 200, tolerance: 10 }),
      new PointerActivationConstraints.Distance({ value: 5 })
    ];
  },
  
  preventActivation(event, source) {
    const { target } = event;
    if (target === source.element || target === source.handle) return false;
    if (source.handle?.contains(target)) return false;
    return isInteractiveElement(target); // Button, link, input, etc.
  }
};

Activation Constraints

Activation constraints control when a drag operation starts.

PointerActivationConstraints.Delay

Requires the pointer to be held down for a duration before activating.
import { PointerActivationConstraints } from '@dnd-kit/dom';

new PointerActivationConstraints.Delay({
  value: 250,    // Milliseconds to wait
  tolerance: 5   // Max pixels of movement allowed
});
options
DelayConstraintOptions

PointerActivationConstraints.Distance

Requires the pointer to move a minimum distance before activating.
import { PointerActivationConstraints } from '@dnd-kit/dom';

new PointerActivationConstraints.Distance({
  value: 5,      // Pixels to move
  tolerance: 10  // Max pixels before failing (optional)
});
options
DistanceConstraintOptions

Combining Constraints

Multiple constraints can be combined. The drag activates when any constraint is satisfied:
PointerSensor.configure({
  activationConstraints: [
    // Activate after 200ms OR after moving 8px
    new PointerActivationConstraints.Delay({ value: 200, tolerance: 10 }),
    new PointerActivationConstraints.Distance({ value: 8 })
  ]
});

KeyboardSensor

Handles keyboard-based dragging with arrow keys.

Options

import { KeyboardSensor } from '@dnd-kit/dom';

const manager = new DragDropManager({
  sensors: [
    KeyboardSensor.configure({
      offset: 10,
      keyboardCodes: {
        start: ['Space', 'Enter'],
        cancel: ['Escape'],
        end: ['Space', 'Enter', 'Tab'],
        up: ['ArrowUp'],
        down: ['ArrowDown'],
        left: ['ArrowLeft'],
        right: ['ArrowRight']
      },
      preventActivation: (event, source) => {
        return event.target !== source.handle;
      }
    })
  ]
});
options
KeyboardSensorOptions

Default Behavior

KeyboardSensor.defaults = {
  offset: 10,
  keyboardCodes: {
    start: ['Space', 'Enter'],
    cancel: ['Escape'],
    end: ['Space', 'Enter', 'Tab'],
    up: ['ArrowUp'],
    down: ['ArrowDown'],
    left: ['ArrowLeft'],
    right: ['ArrowRight']
  },
  preventActivation(event, source) {
    const target = source.handle ?? source.element;
    return event.target !== target;
  }
};

Keyboard Movement

The KeyboardSensor supports accelerated movement:
  • Normal: Press arrow key to move by offset pixels
  • Fast: Hold Shift + arrow key to move by offset * 5 pixels
// Move 10px per keypress, or 50px with Shift
KeyboardSensor.configure({ offset: 10 });

// Different speeds per axis
KeyboardSensor.configure({
  offset: { x: 15, y: 10 } // 75px horizontal, 50px vertical with Shift
});

Example: Custom Sensor Configuration

import {
  DragDropManager,
  PointerSensor,
  KeyboardSensor,
  PointerActivationConstraints
} from '@dnd-kit/dom';

const manager = new DragDropManager({
  sensors: [
    // Pointer with custom constraints
    PointerSensor.configure({
      activationConstraints(event, source) {
        // Touch: longer delay on mobile
        if (event.pointerType === 'touch') {
          return [
            new PointerActivationConstraints.Delay({
              value: 300,
              tolerance: 8
            })
          ];
        }
        
        // Mouse: require 5px movement
        return [
          new PointerActivationConstraints.Distance({ value: 5 })
        ];
      },
      
      // Only drag from elements with .drag-handle class
      activatorElements(source) {
        const handle = source.element.querySelector('.drag-handle');
        return handle ? [handle] : [];
      },
      
      // Don't drag from buttons or links
      preventActivation(event, source) {
        const target = event.target as Element;
        return target.tagName === 'BUTTON' || target.tagName === 'A';
      }
    }),
    
    // Keyboard with larger movement
    KeyboardSensor.configure({
      offset: 20, // Move 20px at a time (100px with Shift)
      keyboardCodes: {
        start: ['Space'],        // Only Space to start
        cancel: ['Escape'],
        end: ['Enter'],          // Only Enter to drop
        up: ['ArrowUp', 'w'],   // Support WASD
        down: ['ArrowDown', 's'],
        left: ['ArrowLeft', 'a'],
        right: ['ArrowRight', 'd']
      }
    })
  ]
});

Example: Touch-Optimized

import {
  DragDropManager,
  PointerSensor,
  PointerActivationConstraints
} from '@dnd-kit/dom';

const manager = new DragDropManager({
  sensors: [
    PointerSensor.configure({
      activationConstraints: [
        // Short delay for all pointer types
        new PointerActivationConstraints.Delay({
          value: 150,
          tolerance: 5
        })
      ]
    })
  ]
});

Example: Mouse Only, Immediate Activation

import { DragDropManager, PointerSensor } from '@dnd-kit/dom';

const manager = new DragDropManager({
  sensors: [
    PointerSensor.configure({
      // No constraints = immediate activation
      activationConstraints: undefined,
      
      // Only allow mouse
      preventActivation(event, source) {
        return event.pointerType !== 'mouse';
      }
    })
  ]
});

Type Definitions

interface PointerSensorOptions {
  activationConstraints?:
    | ActivationConstraints<PointerEvent>
    | ((event: PointerEvent, source: Draggable) => 
        ActivationConstraints<PointerEvent> | undefined);
  activatorElements?: 
    | Element[]
    | ((source: Draggable) => Element[]);
  preventActivation?: (event: PointerEvent, source: Draggable) => boolean;
}

interface KeyboardSensorOptions {
  offset?: number | { x: number; y: number };
  keyboardCodes?: KeyboardCodes;
  preventActivation?: (event: KeyboardEvent, source: Draggable) => boolean;
}

interface KeyboardCodes {
  start: KeyCode[];
  cancel: KeyCode[];
  end: KeyCode[];
  up: KeyCode[];
  down: KeyCode[];
  left: KeyCode[];
  right: KeyCode[];
}

class PointerActivationConstraints {
  static Delay: typeof DelayConstraint;
  static Distance: typeof DistanceConstraint;
}

Build docs developers (and LLMs) love