Documentation Index Fetch the complete documentation index at: https://mintlify.com/clauderic/dnd-kit/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The vanilla JavaScript adapter provides framework-agnostic drag and drop functionality through the core @dnd-kit/dom package. Use this when you’re building without a framework or want direct control over the DOM.
Installation
Install the core packages:
npm install @dnd-kit/dom @dnd-kit/abstract
Getting Started
Create a DragDropManager
Initialize the drag and drop manager that coordinates all interactions: import { DragDropManager } from '@dnd-kit/dom' ;
const manager = new DragDropManager ();
Create draggable elements
Register elements as draggable: import { Draggable } from '@dnd-kit/dom' ;
const draggableElement = document . getElementById ( 'draggable-1' );
const draggable = new Draggable (
{
id: 'draggable-1' ,
element: draggableElement ,
},
manager
);
Create droppable zones
Register elements as drop targets: import { Droppable } from '@dnd-kit/dom' ;
const droppableElement = document . getElementById ( 'droppable-1' );
const droppable = new Droppable (
{
id: 'droppable-1' ,
element: droppableElement ,
},
manager
);
Listen to drag events
Subscribe to drag and drop events: manager . monitor . addEventListener ( 'dragstart' , ( event ) => {
console . log ( 'Drag started:' , event . operation . source . id );
});
manager . monitor . addEventListener ( 'dragend' , ( event ) => {
const { source , target } = event . operation ;
console . log ( 'Dropped' , source . id , 'on' , target ?. id );
});
Complete Example
Here’s a full working example:
import { DragDropManager , Draggable , Droppable } from '@dnd-kit/dom' ;
// Initialize the manager
const manager = new DragDropManager ();
// Create draggable items
const draggableElements = document . querySelectorAll ( '[data-draggable]' );
draggableElements . forEach (( element ) => {
new Draggable (
{
id: element . id ,
element: element as HTMLElement ,
data: {
label: element . textContent ,
},
},
manager
);
});
// Create droppable zones
const droppableElements = document . querySelectorAll ( '[data-droppable]' );
droppableElements . forEach (( element ) => {
new Droppable (
{
id: element . id ,
element: element as HTMLElement ,
},
manager
);
});
// Handle drag events
manager . monitor . addEventListener ( 'dragstart' , ( event ) => {
event . operation . source . element ?. classList . add ( 'dragging' );
});
manager . monitor . addEventListener ( 'dragover' , ( event ) => {
event . operation . target ?. element ?. classList . add ( 'drag-over' );
});
manager . monitor . addEventListener ( 'dragend' , ( event ) => {
event . operation . source . element ?. classList . remove ( 'dragging' );
event . operation . target ?. element ?. classList . remove ( 'drag-over' );
});
// Cleanup when done
window . addEventListener ( 'beforeunload' , () => {
manager . destroy ();
});
Sortable Lists
Create sortable lists using the Sortable class:
import { DragDropManager } from '@dnd-kit/dom' ;
import { Sortable } from '@dnd-kit/dom/sortable' ;
const manager = new DragDropManager ();
const items = [ 'Item 1' , 'Item 2' , 'Item 3' ];
const listElement = document . getElementById ( 'sortable-list' );
items . forEach (( item , index ) => {
const element = document . createElement ( 'div' );
element . textContent = item ;
element . id = `item- ${ index } ` ;
listElement . appendChild ( element );
new Sortable (
{
id: element . id ,
element: element ,
group: 'list' ,
index: index ,
},
manager
);
});
manager . monitor . addEventListener ( 'dragend' , ( event ) => {
const source = event . operation . source ;
const target = event . operation . target ;
if ( source && target ) {
// Update your state/data based on the new order
console . log ( `Moved ${ source . id } to position ${ target . index } ` );
}
});
Advanced Features
Custom Drag Handles
Specify a different element as the drag handle:
const draggableElement = document . getElementById ( 'card' );
const handleElement = document . getElementById ( 'drag-handle' );
new Draggable (
{
id: 'card' ,
element: draggableElement ,
handle: handleElement ,
},
manager
);
Modifiers
Apply modifiers to constrain or modify drag behavior:
import { DragDropManager } from '@dnd-kit/dom' ;
import { restrictToHorizontalAxis } from '@dnd-kit/abstract/modifiers' ;
const manager = new DragDropManager ({
modifiers: [ restrictToHorizontalAxis ],
});
Sensors
Customize how drag operations are initiated:
import { DragDropManager } from '@dnd-kit/dom' ;
import { PointerSensor } from '@dnd-kit/dom' ;
const manager = new DragDropManager ({
sensors: [
new PointerSensor ({
activationConstraint: {
distance: 10 , // Require 10px movement before dragging
},
}),
],
});
Type Safety
Add type safety to your drag and drop data:
interface CardData {
id : string ;
title : string ;
status : 'todo' | 'in-progress' | 'done' ;
}
const draggable = new Draggable < CardData >(
{
id: 'card-1' ,
element: cardElement ,
data: {
id: 'card-1' ,
title: 'Implement feature' ,
status: 'todo' ,
},
},
manager
);
manager . monitor . addEventListener ( 'dragend' , ( event ) => {
const data = event . operation . source . data ;
console . log ( data . title ); // Type-safe access
});
Cleanup
Always destroy the manager when you’re done:
// Destroy individual entities
draggable . destroy ();
droppable . destroy ();
// Or destroy the entire manager (destroys all registered entities)
manager . destroy ();
Best Practices
Initialize once : Create your DragDropManager instance once and reuse it
Clean up : Always call destroy() to prevent memory leaks
Use data property : Store metadata on draggables for easier event handling
Batch updates : Apply multiple changes together for better performance
Element references : Keep element references up to date when DOM changes
Next Steps
Sensors Configure how drag operations are initiated
Modifiers Constrain and modify drag behavior
Collision Detection Control how droppable targets are detected
Events Listen to all available drag and drop events