dnd-kit Documentation

The modern toolkit for building drag and drop interfaces

17,393 stars TypeScript TypeScript 1 file ยท ~5,015 tokens #drag#drag-and-drop#draggable#droppable#react#sortable
RAW Doc

1. Project Overview & Quickstart (clauderic/dnd-kit)

File: README.md

Features

  • Framework agnostic core: The architecture is built in layers โ€” a framework-agnostic core (@dnd-kit/abstract), a DOM implementation (@dnd-kit/dom), and thin adapters for your framework of choice.
  • Supports a wide range of use cases: lists, grids, multiple containers, nested contexts, variable sized items, virtualized lists, 2D games, and more.
  • Built-in support for multiple input methods: Pointer, mouse, touch and keyboard sensors.
  • Fully customizable & extensible: Customize every detail โ€” animations, transitions, behaviours, styles. Build your own sensors, collision detection algorithms, customize key bindings and more.
  • Accessibility: Keyboard support, sensible default ARIA attributes, customizable screen reader instructions and live regions built-in.
  • Performance: Built with performance in mind to support silky smooth animations.
  • Sortable: Need to build a sortable interface? Check out @dnd-kit/dom/sortable, a thin layer built on top of the core.

Getting started

Choose your preferred framework to get started:

| Vanilla

Build drag and drop interfaces using plain JavaScript | React

Build drag and drop interfaces using React components and hooks |
| --- | --- |
| Vue

Build drag and drop interfaces using Vue composables and components | Svelte

Build drag and drop interfaces using Svelte primitives and components |
| Solid

Build drag and drop interfaces using SolidJS hooks and components | |

Documentation

Visit dndkit.com for full documentation, API reference, guides, and interactive examples.

Packages

Package Version Description
@dnd-kit/abstract Abstract core
@dnd-kit/collision Collision detection
@dnd-kit/dom Framework-agnostic DOM layer
@dnd-kit/geometry Geometry utilities
@dnd-kit/helpers Helper functions
@dnd-kit/react React adapter
@dnd-kit/solid SolidJS adapter
@dnd-kit/state Reactive state management
@dnd-kit/svelte Svelte adapter
@dnd-kit/vue Vue adapter

Contributing

This is a monorepo managed with Turborepo and bun.

bash
# Install dependencies
bun install

# Build all packages
bun run build

# Run dev mode
bun run dev

License

MIT


File: apps/stories/stories/react/Sortable/MultipleLists/docs/MultipleLists.mdx

import {Code, Preview} from '../../../../components';

import {MultipleLists} from '../MultipleLists.tsx';
import {Hero} from '../MultipleLists.stories.tsx';
import {Example} from './examples/QuickStart';
import ExampleSource from './examples/QuickStart?raw';
import ColumnSource from './examples/Column?raw';
import ItemSource from './examples/Item?raw';

Multiple lists

Reorder sortable elements across multiple lists.

Installation

Before getting started, make sure to install the @dnd-kit/react package:

bash
npm install @dnd-kit/react

Getting started


File: apps/stories/stories/react/Sortable/docs/SortableDocs.mdx

import {Code, Preview} from '../../../components';
import {Example as Hero} from '../Sortable.stories';
import BasicSetupSource from '../SortableExample?raw';
import {Example} from './examples/Example';
import {Example as UncontrolledExample} from './examples/UncontrolledExample';
import UncontrolledExampleSource from './examples/UncontrolledExample?raw';
import ControlledExampleSource from './examples/ControlledExample?raw';
import image from './assets/useSortable.png';

Sortable

Reorder elements in a list or across multiple lists.

Installation

Before getting started, make sure to install the @dnd-kit/react package:

bash
npm install @dnd-kit/react

Getting started

The fastest way to get started is to the useSortable hook and provide it an id and an index:

This will create an uncontrolled sortable list that will automatically update the order of the items in the DOM when they are dragged and dropped.

To create a controlled sortable list and update the order of the items in React, we can listen to the onDragEnd event emitted by the <DragDropProvider> component:

To create a vertical list, we can update the of the flex-direction style property to column, without any other configuration changes.

<Example style={{display: 'inline-flex', flexDirection: 'column', gap: 20}} />

To create a grid list, we can update the of the display style property to grid, and set the grid-template-columns property to the desired number of columns.

<Example
style={{
display: 'grid',
gridTemplateColumns: 'repeat(2, 150px)',
gridAutoRows: '150px',
gap: 20,
}}
/>

Architecture

The sortable plugin composes the Draggable and Droppable items to provide a simple API for building sortable interfaces.

The useSortable hook is an abstraction that composes the useDroppable and useDraggable hooks:

As a result, the useSortable hook accepts all of the props that the useDraggable and useDroppable hooks accept.

Modifiers

Because the useSortable hook invokes the useDraggable hook under the hood, we can pass local modifiers to the useSortable hook just as we would with the useDraggable hook:

jsx
const sortable = useSortable({
  id,
  modifiers: [RestrictToVerticalAxis],
});

File: apps/stories/stories/react/Droppable/docs/DroppableDocs.mdx

import {Preview} from '../../../components';
import {Example as Hero} from '../Droppable.stories';
import {Example} from './examples/QuickStart';
import ExampleSource from './examples/QuickStart?raw';
import DraggableSource from './examples/Draggable?raw';
import DroppableSource from './examples/Droppable?raw';
import {Example as MultipleDroppableExample} from './examples/MultipleDroppable';
import MultipleDroppableExampleSource from './examples/MultipleDroppable?raw';

Droppable

Create droppable targets for draggable elements.

Usage

Use the useDroppable hook to create droppable targets that draggable elements can be dropped over.

jsx
import {useDroppable} from '@dnd-kit/react';

function Droppable(props) {
  const {ref} = useDroppable({
    id: props.id,
  });

  return {props.children};
}

On its own, the useDroppable hook does not provide a lot of functionality. It is meant to be used in conjunction with the useDraggable hook, along with a parent <DragDropProvider> component to listen for and respond to drag and drop events.

You can set up as many droppable targets as needed, either by calling the useDroppable hook multiple times within the same component, or by setting up a generic component that calls useDroppable and rendering that component multiple times. Just remember to make sure they all have a unique id so that they can be differentiated.

Getting started

To get started, we will create three files, App.js, Droppable.js, and Draggable.js.

To render multiple droppable targets, we can simply render the <Droppable> component multiple times:


File: apps/stories/stories/react/Draggable/docs/DraggableDocs.mdx

import {Preview} from '../../../components';
import {Example as Hero} from '../Draggable.stories';
import {Example} from './examples/QuickStart';
import ExampleSource from './examples/QuickStart?raw';
import DraggableSource from './examples/Draggable?raw';
import {Example as MultipleDraggableExample} from './examples/MultipleDraggable';
import MultipleDraggableExampleSource from './examples/MultipleDraggable?raw';

Draggable

Make elements draggable and drop them over targets.

Usage

Use the useDraggable hook to create draggable elements that draggable elements can be dropped over droppable targets.

jsx
import {useDraggable} from '@dnd-kit/react';

function Draggable(props) {
  const {ref} = useDraggable({
    id: props.id,
  });

  return {props.children};
}

Getting started

To get started, we will create two files, App.js and Draggable.js.

To render multiple draggable elements, we can simply render the <Draggable> component multiple times:


File: apps/stories/stories/react/Draggable/DragHandles/docs/DragHandles.mdx

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

import {Info, Preview} from '../../../../components';
import {DragHandle} from '../DragHandles.stories.tsx';

Drag handles

Restrict dragging to a specific element within a draggable element.

Usage

To create a drag handle, provide a handle element to the useDraggable hook by consuming the handleRef from the output object of the useDraggable hook.

jsx
import {useDraggable} from '@dnd-kit/react';

function Draggable(props) {
  const {handleRef, ref} = useDraggable({
    id: props.id,
  });

  return (
    
      {props.children}
      Drag handle
    
  );
}

Alternatively, you can also pass an Element or ref to an element as an argument to the handle option of useDraggable:

jsx
import {useDraggable} from '@dnd-kit/react';

function Draggable(props) {
  const handleRef = useRef(null);
  const {ref} = useDraggable({
    id: props.id,
    handle: handleRef,
  });

  return (
    
      {props.children}
      Drag handle
    
  );
}

File: apps/stories/stories/react/Draggable/Modifiers/docs/ModifierDocs.mdx

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

import {Info, Preview} from '../../../../components';
import {DraggableExample} from '../../DraggableExample';

Modifiers

Modify or restrict the behavior of draggable elements.

<DraggableExample
modifiers={[
RestrictToElement.configure({
element() {
return document.getElementById('modifier-hero');
},
}),
]}
/>

Modifiers let you dynamically modify the movement coordinates that are detected by sensors. They can be used for a wide range of use cases, for example:

  • Restricting motion to a single axis
  • Restricting motion to the draggable node container's bounding rectangle
  • Restricting motion to the draggable node's scroll container bounding rectangle
  • Applying resistance or clamping the motion

Usage

Modifiers can be applied globally or to individual draggable elements.

Global modifiers

Modifiers can be applied globally by passing them to the <DragDropProvider> component.

jsx
import {DragDropProvider} from '@dnd-kit/react';
import {RestrictToVerticalAxis} from '@dnd-kit/abstract/modifiers';
import {RestrictToWindow} from '@dnd-kit/dom/modifiers';

function App() {
  return (
    <DragDropProvider modifiers={[RestrictToWindow, RestrictToVerticalAxis]}>
      {...}
    </DragDropProvider>
  )
}

Local modifiers

Local modifiers take precedence over global modifiers.

Modifiers can also be applied to individual draggable elements by passing them to the modifiers prop.

jsx
import {useDraggable} from '@dnd-kit/react';
import {RestrictToVerticalAxis} from '@dnd-kit/abstract/modifiers';
import {RestrictToWindow} from '@dnd-kit/dom/modifiers';

function Draggable({id}) {
  const {ref} = useDraggable({
    id,
    modifiers: [RestrictToVerticalAxis, RestrictToWindow],
  });
}

File: apps/stories/stories/react/Draggable/Sensors/docs/SensorDocs.mdx

import {Info, Preview} from '../../../../components';
import {DraggableExample} from '../../DraggableExample';

Sensors

Detect user input and translate them into drag operations.

Overview

Sensors are an abstraction to detect different input methods in order to initiate drag operations, respond to movement and end or cancel the operation.

Built-in sensors

The @dnd-kit/dom package provides built-in sensors that can be used to detect user input in the browser.

Pointer sensor

The Pointer sensor responds to Pointer events. This sensor is enabled by default.

Pointer events are DOM events that are fired for a pointing device. They are designed to create a single DOM event model to handle pointing input devices such as a mouse, pen/stylus or touch (such as one or more fingers).
The pointer is a hardware-agnostic device that can target a specific set of screen coordinates.

โ€“ Source: MDN

Activation constraints

The Pointer sensor has two types of activation constraints:

  • Distance constraint
  • Delay constraint

These activation constraints are not mutually exclusive, they can be used simultaneously. In case both constraints are used, the Pointer sensor will activate as soon as one of the constraints is met.

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

const sensors = [
  PointerSensor.configure({
    activationConstraints: [
      new PointerActivationConstraints.Delay({value: 200, tolerance: 10}),
      new PointerActivationConstraints.Distance({value: 5}),
    ],
  }),
];

The distance value property represents the distance, in pixels, that a pointer needs to be moved by before a drag operation is initiated.

The delay value property represents the duration, in milliseconds, that a draggable item needs to be held by the primary pointer for before a drag start event is emitted.

The tolerance property represents the distance, in pixels, of motion that is tolerated before the drag operation is aborted. If the pointer is moved during the delay duration and the tolerance is set to zero, the drag operation will be immediately aborted. If a higher tolerance is set, for example, a tolerance of 5 pixels, the operation will only be aborted if the pointer is moved by more than 5 pixels during the delay.

This property is particularly useful for touch input, where some tolerance should be accounted for when using a delay constraint, as touch input is less precise than mouse input.

Default behavior

By default, the PointerSensor applies sensible activation constraints depending on the context:

  • Mouse on handle: activates immediately.
  • Touch: Delay({value: 250, tolerance: 5}).
  • Text inputs: Delay({value: 200, tolerance: 0}).
  • Other cases: Delay({value: 200, tolerance: 10}) and Distance({value: 5}).

You can override this with activationConstraints, which may be an array of constraints or a function (event, source) => ActivationConstraints | undefined to compute them per interaction.

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

PointerSensor.configure({
  activationConstraints(event, source) {
    if (event.pointerType === 'touch') {
      return [
        new PointerActivationConstraints.Delay({value: 300, tolerance: 8}),
      ];
    }
    return [new PointerActivationConstraints.Distance({value: 6})];
  },
});

Activator elements

You may specify additional elements that can start a pointer interaction via activatorElements:

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

PointerSensor.configure({
  activatorElements(source) {
    return [
      source.handle,
      document.querySelector('[data-dnd-activator]'),
    ];
  },
});

Keyboard sensor

The Keyboard sensor responds to Keyboard events. This sensor is enabled by default.

The keyboard sensor activates when the handle or element of a draggable source is focused and the Space or Enter key is pressed.

Configuration

The Keyboard sensor can be configured to respond to different keyboard keys:

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

const sensors = [
  KeyboardSensor.configure({
    keyboardCodes: {
      start: ['Space', 'Enter'],
      cancel: ['Escape'],
      end: ['Space', 'Enter'],
      up: ['ArrowUp'],
      down: ['ArrowDown'],
      left: ['ArrowLeft'],
      right: ['ArrowRight'],
    },
  }),
];

Keyboard sensor bindings use KeyboardEvent.key values such as w, Enter, and ArrowUp. Common legacy Key* and Digit* code values normalize for compatibility, but physical key codes such as NumpadEnter should be replaced with the key value they produce. Other named keys must match KeyboardEvent.key casing.

You may customize these values, but do keep in mind that the third rule of ARIA requires that a user must be able to activate the action associated with a draggable widget using both the enter (on Windows) or return (on macOS) and the space key. To learn more, read the in-depth accessibility guide.

Usage

Sensors can be applied globally or to individual draggable elements.

Global sensors

Sensors can be applied globally by passing them to the <DragDropProvider> component.

jsx
import {DragDropProvider} from '@dnd-kit/react';
import {PointerSensor, KeyboardSensor} from '@dnd-kit/dom';

function App() {
  return (
    <DragDropProvider sensors={[PointerSensor, KeyboardSensor]}>
      {...}
    </DragDropProvider>
  )
}

Local sensors

Local sensors take precedence over global sensors.

Sensors can also be applied to individual draggable elements by passing them to the sensors prop.

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

function Draggable({id}) {
  const {ref} = useDraggable({
    id,
    sensors: [KeyboardSensor],
  });
}

2. Official Technical Reference & Guides (clauderic/docs)

Mintlify Starter Kit

Click on Use this template to copy the Mintlify starter kit. The starter kit contains examples including

  • Guide pages
  • Navigation
  • Customizations
  • API Reference pages
  • Use of popular components

Development

Install the Mintlify CLI to preview the documentation changes locally. To install, use the following command

text
npm i mintlify

Run the following command at the root of your documentation (where mint.json is)

text
mintlify dev

Publishing Changes

Install our Github App to auto propagate changes from your repo to your deployment. Changes will be deployed to production automatically after pushing to the default branch. Find the link to install on your dashboard.

Troubleshooting

  • Mintlify dev isn't running - Run mintlify install it'll re-install dependencies.
  • Page loads as a 404 - Make sure you are running in a folder with mint.json