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.
# Install dependencies
bun install
# Build all packages
bun run build
# Run dev mode
bun run devLicense
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:
npm install @dnd-kit/reactGetting 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:
npm install @dnd-kit/reactGetting 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:
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.
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.
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.
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:
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.
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.
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.
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})andDistance({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.
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:
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:
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.
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.
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
npm i mintlifyRun the following command at the root of your documentation (where mint.json is)
mintlify devPublishing 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 installit'll re-install dependencies. - Page loads as a 404 - Make sure you are running in a folder with
mint.json