Skip to main content
Sensor is the abstract base class for all sensor implementations in dnd-kit. Sensors are responsible for detecting and initiating drag operations by handling user interactions such as mouse, touch, keyboard, or custom input methods.

Sensor Class

Constructor

Creates a new sensor instance.
class MySensor extends Sensor<T, U> {
  constructor(manager: T, options?: U) {
    super(manager, options);
  }
}
manager
T extends DragDropManager
required
The drag and drop manager instance.
options
U extends SensorOptions
Optional sensor configuration.
T
extends DragDropManager<any, any>
default:"DragDropManager<Draggable, Droppable>"
Type parameter for the drag drop manager.
U
extends SensorOptions
default:"SensorOptions"
Type parameter for sensor options.

Properties

manager

manager
T
The drag drop manager instance that this sensor is bound to.
const manager = sensor.manager;

options

options
U | undefined
The configuration options for this sensor instance.
const options = sensor.options;

disabled

disabled
boolean
Whether the sensor instance is disabled.
sensor.disabled = true;
Inherited from Plugin.

Methods

bind() (abstract)

Binds the sensor to a draggable source. Must be implemented by subclasses.
public abstract bind(source: Draggable, options?: U): CleanupFunction;
source
Draggable
required
The draggable element to bind to.
options
U
Optional sensor options specific to this draggable.
return
CleanupFunction
A cleanup function that unbinds the sensor when called.
type CleanupFunction = () => void;

Inherited from Plugin

enable()

Enables a disabled sensor instance.
sensor.enable();

disable()

Disables an enabled sensor instance.
sensor.disable();

isDisabled()

Checks if the sensor instance is disabled.
const disabled = sensor.isDisabled();
return
boolean
true if the sensor is disabled.

configure()

Configures a sensor instance with new options.
sensor.configure({option: 'value'});
options
U
The new options to apply.

destroy()

Destroys a sensor instance and cleans up its resources.
sensor.destroy();

Static Methods

configure()

Configures a sensor constructor with default options.
const ConfiguredSensor = MySensor.configure({
  activationDistance: 10,
  activationDelay: 200
});
options
PluginOptions
required
The options to configure the constructor with.
return
SensorDescriptor
A configured sensor descriptor that can be passed to the manager.

Types

SensorOptions

Base type for sensor options.
type SensorOptions = PluginOptions;
type PluginOptions = Record<string, any>;

SensorConstructor

Constructor type for creating sensor instances.
type SensorConstructor<T extends DragDropManager<any, any>> = 
  PluginConstructor<T, Sensor<T>>;

interface PluginConstructor<T, U> {
  new (manager: T, options?: PluginOptions): U;
}

SensorDescriptor

Descriptor type for configuring sensors.
type SensorDescriptor<T extends DragDropManager<any, any>> = 
  PluginDescriptor<T, Sensor<T>, SensorConstructor<T>>;

type PluginDescriptor<T, U, V> = {
  plugin: V;
  options?: PluginOptions;
};

Sensors

Array type for multiple sensor configurations.
type Sensors<T extends DragDropManager<any, any>> = 
  (SensorConstructor<T> | SensorDescriptor<T>)[];

Activation Constraints

ActivationConstraint

Abstract base class for activation constraints.
abstract class ActivationConstraint<E extends Event, O extends ActivationConstraintOptions> {
  constructor(protected options: O);
  
  abstract onEvent(event: E): void;
  abstract abort(event?: E): void;
  
  protected activate(event: E): void;
}
Activation constraints allow you to control when a drag operation should start based on specific conditions.

ActivationController

Controller for managing activation constraints.
class ActivationController<E extends Event> extends AbortController {
  public activated: boolean;
  
  constructor(
    constraints: ActivationConstraints<E> | undefined,
    onActivate: (event: E) => void
  );
  
  onEvent(event: E): void;
  activate(event: E): void;
  abort(event?: E): void;
}

ActivationConstraints

Array type for activation constraints.
type ActivationConstraints<E extends Event> = ActivationConstraint<E>[];

Implementing a Custom Sensor

Basic Implementation

import {Sensor, type SensorOptions} from '@dnd-kit/abstract';
import type {Draggable} from '@dnd-kit/abstract';

interface MySensorOptions extends SensorOptions {
  threshold?: number;
}

class MySensor extends Sensor<DragDropManager, MySensorOptions> {
  constructor(manager: DragDropManager, options?: MySensorOptions) {
    super(manager, options);
  }

  public bind(source: Draggable, options?: MySensorOptions): CleanupFunction {
    const threshold = options?.threshold ?? this.options?.threshold ?? 5;
    
    const handleStart = (event: PointerEvent) => {
      if (this.isDisabled()) return;
      
      const controller = this.manager.actions.start({
        source,
        event,
        coordinates: {x: event.clientX, y: event.clientY}
      });
      
      // Handle move, end events...
    };
    
    // Attach event listeners
    source.element?.addEventListener('pointerdown', handleStart);
    
    // Return cleanup function
    return () => {
      source.element?.removeEventListener('pointerdown', handleStart);
    };
  }
}

With Activation Constraints

import {
  Sensor,
  ActivationController,
  ActivationConstraint,
  type ActivationConstraints
} from '@dnd-kit/abstract';

class DelayConstraint extends ActivationConstraint<PointerEvent> {
  private timeout?: number;
  
  onEvent(event: PointerEvent): void {
    this.timeout = window.setTimeout(() => {
      this.activate(event);
    }, this.options.delay);
  }
  
  abort(): void {
    if (this.timeout) {
      clearTimeout(this.timeout);
    }
  }
}

class MySensor extends Sensor {
  public bind(source: Draggable): CleanupFunction {
    const handlePointerDown = (event: PointerEvent) => {
      const constraints: ActivationConstraints<PointerEvent> = [
        new DelayConstraint({delay: 200})
      ];
      
      const controller = new ActivationController(
        constraints,
        (event) => {
          // Activation confirmed
          this.manager.actions.start({
            source,
            event,
            coordinates: {x: event.clientX, y: event.clientY}
          });
        }
      );
      
      const handleMove = (event: PointerEvent) => {
        controller.onEvent(event);
      };
      
      const handleUp = () => {
        controller.abort();
        cleanup();
      };
      
      document.addEventListener('pointermove', handleMove);
      document.addEventListener('pointerup', handleUp);
      
      const cleanup = () => {
        document.removeEventListener('pointermove', handleMove);
        document.removeEventListener('pointerup', handleUp);
      };
    };
    
    source.element?.addEventListener('pointerdown', handlePointerDown);
    
    return () => {
      source.element?.removeEventListener('pointerdown', handlePointerDown);
    };
  }
}

Usage Examples

Using Sensors with Manager

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

const manager = new DragDropManager({
  sensors: [PointerSensor, KeyboardSensor]
});

Configuring Sensors

const manager = new DragDropManager({
  sensors: [
    PointerSensor.configure({
      activationConstraint: {
        distance: 10 // Require 10px movement
      }
    }),
    KeyboardSensor
  ]
});

Per-Draggable Sensors

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

const draggable = new Draggable(
  {
    id: 'item-1',
    sensors: [PointerSensor] // Override manager's sensors
  },
  manager
);

Dynamic Sensor Management

const manager = new DragDropManager();

// Add sensors later
manager.sensors = [PointerSensor, KeyboardSensor];

// Disable a sensor temporarily
const pointerSensor = manager.sensors.find(s => s instanceof PointerSensor);
pointerSensor?.disable();

// Re-enable
pointerSensor?.enable();

Extending Defaults

const manager = new DragDropManager({
  sensors: (defaults) => [
    ...defaults,
    CustomSensor
  ]
});

Common Sensor Patterns

Pointer Sensor Pattern

class PointerSensor extends Sensor {
  public bind(source: Draggable): CleanupFunction {
    const handlePointerDown = (event: PointerEvent) => {
      event.preventDefault();
      
      const controller = this.manager.actions.start({
        source,
        event,
        coordinates: {x: event.clientX, y: event.clientY}
      });
      
      const handlePointerMove = (event: PointerEvent) => {
        this.manager.actions.move({
          to: {x: event.clientX, y: event.clientY},
          event
        });
      };
      
      const handlePointerUp = (event: PointerEvent) => {
        this.manager.actions.stop({event});
        cleanup();
      };
      
      document.addEventListener('pointermove', handlePointerMove);
      document.addEventListener('pointerup', handlePointerUp);
      
      controller.signal.addEventListener('abort', cleanup);
      
      const cleanup = () => {
        document.removeEventListener('pointermove', handlePointerMove);
        document.removeEventListener('pointerup', handlePointerUp);
      };
    };
    
    source.element?.addEventListener('pointerdown', handlePointerDown);
    
    return () => {
      source.element?.removeEventListener('pointerdown', handlePointerDown);
    };
  }
}

Keyboard Sensor Pattern

class KeyboardSensor extends Sensor {
  public bind(source: Draggable): CleanupFunction {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Enter' || event.key === ' ') {
        // Start drag
        this.manager.actions.start({
          source,
          event,
          coordinates: {x: 0, y: 0}
        });
      }
      
      if (event.key === 'ArrowUp') {
        this.manager.actions.move({by: {x: 0, y: -10}, event});
      }
      // Handle other arrow keys...
    };
    
    source.element?.addEventListener('keydown', handleKeyDown);
    
    return () => {
      source.element?.removeEventListener('keydown', handleKeyDown);
    };
  }
}

See Also

Build docs developers (and LLMs) love