Droppable represents an entity that can receive draggable items in a drag and drop operation. It extends the base Entity class with droppable-specific functionality including type-based acceptance rules, collision detection, and drop target status tracking.
Constructor
Creates a new droppable entity.
const droppable = new Droppable < T , U >( input , manager );
input
DroppableInput<T>
required
Configuration object for the droppable. Show DroppableInput properties
Unique identifier for this droppable entity. id : 'zone-1'
// or
id : 456
collisionDetector
CollisionDetector
required
Function for determining collisions with draggables. collisionDetector : rectangleIntersection
accept
Type | Type[] | ((source: Draggable) => boolean)
Types of draggables that can be dropped here, or a function to determine compatibility. // Accept specific type
accept : 'card'
// Accept multiple types
accept : [ 'card' , 'widget' ]
// Custom acceptance logic
accept : ( draggable ) => draggable . data . category === 'allowed'
If undefined, all draggables are accepted. collisionPriority
CollisionPriority | number
Priority for collision detection. Higher priority collisions take precedence. collisionPriority : CollisionPriority . High
// or custom numeric priority
collisionPriority : 100
Type/category for this droppable. Arbitrary data associated with this entity. data : {
label : 'Drop here' ,
accepts : [ 'card' , 'item' ],
capacity : 10
}
Whether the entity should initially be disabled.
Whether to automatically register with the manager when created.
Array of effects that are set up when registered and cleaned up when unregistered.
The drag and drop manager instance, or undefined for unmanaged entities.
T
extends Data
default: "Data"
Type parameter for the data associated with this droppable.
U
extends DragDropManager<any, any>
default: "DragDropManager<any, any>"
Type parameter for the manager type.
Properties
Inherited from Entity
The unique identifier of the entity. Can be updated dynamically. droppable . id = 'new-zone-id' ;
The data associated with the entity. droppable . data = { label: 'Updated label' , capacity: 20 };
The drag and drop manager instance. droppable . manager = newManager ;
Whether the entity is disabled. droppable . disabled = true ;
Droppable-Specific
accept
Type | Type[] | ((draggable: Draggable) => boolean) | undefined
Types of draggables that can be dropped here, or a function to determine compatibility. // Accept only 'card' type
droppable . accept = 'card' ;
// Accept multiple types
droppable . accept = [ 'card' , 'widget' ];
// Custom logic
droppable . accept = ( draggable ) => draggable . data . size <= 10 ;
The type/category of the droppable entity. droppable . type = 'container' ;
The collision detector for this droppable. droppable . collisionDetector = closestCenter ;
collisionPriority
CollisionPriority | number | undefined
The collision priority for this droppable. droppable . collisionPriority = CollisionPriority . Highest ;
The current shape of this droppable. Typically set automatically based on DOM measurements. droppable . shape = new Rectangle ({
x: 0 ,
y: 0 ,
width: 200 ,
height: 100
});
Computed Properties
isDropTarget
Checks if this droppable is the current drop target. if ( droppable . isDropTarget ) {
console . log ( 'Draggable is over this zone' );
}
Returns true if this droppable’s ID matches the current drag operation’s target ID.
Methods
accepts()
Checks whether this droppable accepts a given draggable.
const canDrop = droppable . accepts ( draggable );
The draggable to check compatibility for.
true if the draggable can be dropped here, false otherwise.
Logic:
If accept is undefined, returns true (accepts all)
If accept is a function, calls it with the draggable
If draggable has no type, returns false
If accept is an array, checks if it includes the draggable’s type
If accept is a single type, checks for exact match
Inherited from Entity
register()
Registers the entity with its manager.
const cleanup = droppable . register ();
A cleanup function to unregister the entity, or void if no manager is set.
unregister()
Unregisters the entity from its manager.
destroy()
Cleans up the entity when it’s no longer needed.
Usage Examples
Basic Droppable
import { Droppable , DragDropManager } from '@dnd-kit/abstract' ;
import { rectangleIntersection } from '@dnd-kit/collision' ;
const manager = new DragDropManager ();
const droppable = new Droppable (
{
id: 'zone-1' ,
collisionDetector: rectangleIntersection ,
data: { label: 'Drop here' }
},
manager
);
With Type Acceptance
// Accept only 'card' type draggables
const droppable = new Droppable (
{
id: 'card-zone' ,
accept: 'card' ,
collisionDetector: rectangleIntersection
},
manager
);
// Accept multiple types
const multiDroppable = new Droppable (
{
id: 'multi-zone' ,
accept: [ 'card' , 'widget' , 'item' ],
collisionDetector: rectangleIntersection
},
manager
);
With Custom Acceptance Logic
const droppable = new Droppable (
{
id: 'smart-zone' ,
accept : ( draggable ) => {
// Only accept if priority is high
if ( draggable . data . priority !== 'high' ) {
return false ;
}
// Check capacity
const currentItems = droppable . data . items ?. length ?? 0 ;
return currentItems < droppable . data . capacity ;
},
collisionDetector: rectangleIntersection ,
data: { capacity: 5 , items: []}
},
manager
);
With Collision Priority
import { CollisionPriority } from '@dnd-kit/abstract' ;
const highPriorityZone = new Droppable (
{
id: 'priority-zone' ,
collisionPriority: CollisionPriority . Highest ,
collisionDetector: rectangleIntersection
},
manager
);
// Custom numeric priority
const customPriorityZone = new Droppable (
{
id: 'custom-zone' ,
collisionPriority: 999 ,
collisionDetector: rectangleIntersection
},
manager
);
Checking Acceptance
const droppable = new Droppable (
{
id: 'zone-1' ,
accept: 'card' ,
collisionDetector: rectangleIntersection
},
manager
);
const cardDraggable = new Draggable ({ id: 'item-1' , type: 'card' }, manager );
const widgetDraggable = new Draggable ({ id: 'item-2' , type: 'widget' }, manager );
console . log ( droppable . accepts ( cardDraggable )); // true
console . log ( droppable . accepts ( widgetDraggable )); // false
Checking Drop Target Status
const droppable = new Droppable (
{
id: 'zone-1' ,
collisionDetector: rectangleIntersection
},
manager
);
// During a drag operation
if ( droppable . isDropTarget ) {
console . log ( 'A draggable is hovering over this zone' );
// Update UI, show highlight, etc.
}
Dynamic Updates
const droppable = new Droppable (
{
id: 'zone-1' ,
accept: 'card' ,
collisionDetector: rectangleIntersection
},
manager
);
// Change accepted types
droppable . accept = [ 'card' , 'widget' ];
// Disable temporarily
droppable . disabled = true ;
// Update collision priority
droppable . collisionPriority = CollisionPriority . High ;
// Update data
droppable . data = {
... droppable . data ,
capacity: 20
};
TypeScript Types
interface DropZoneData {
label : string ;
category : string ;
capacity : number ;
items : string [];
}
const droppable = new Droppable < DropZoneData >(
{
id: 'zone-1' ,
collisionDetector: rectangleIntersection ,
data: {
label: 'Todo' ,
category: 'tasks' ,
capacity: 10 ,
items: []
}
},
manager
);
// TypeScript knows the shape of data
const capacity = droppable . data . capacity ; // number
const items = droppable . data . items ; // string[]
With Custom Collision Detector
import type { CollisionDetector } from '@dnd-kit/abstract' ;
const customCollisionDetector : CollisionDetector = ({ droppable , dragOperation }) => {
const { source } = dragOperation ;
if ( ! source ?. shape || ! droppable . shape ) return null ;
// Custom collision logic
const overlap = calculateOverlap ( source . shape , droppable . shape );
if ( overlap > 0 ) {
return {
id: droppable . id ,
type: CollisionType . ShapeIntersection ,
priority: CollisionPriority . Normal ,
value: overlap ,
data: { overlap }
};
}
return null ;
};
const droppable = new Droppable (
{
id: 'zone-1' ,
collisionDetector: customCollisionDetector
},
manager
);
Monitoring Drop Events
const droppable = new Droppable (
{
id: 'zone-1' ,
collisionDetector: rectangleIntersection ,
data: { items: []}
},
manager
);
manager . monitor . addEventListener ( 'dragend' , ( event ) => {
if ( event . operation . target ?. id === droppable . id ) {
const draggedItem = event . operation . source ;
console . log ( `Item ${ draggedItem ?. id } was dropped on zone ${ droppable . id } ` );
// Update data
droppable . data . items . push ( draggedItem ?. id );
}
});
Nested Droppables
// Parent container with low priority
const parentZone = new Droppable (
{
id: 'parent' ,
collisionPriority: CollisionPriority . Low ,
collisionDetector: rectangleIntersection
},
manager
);
// Child zone with higher priority
const childZone = new Droppable (
{
id: 'child' ,
collisionPriority: CollisionPriority . High ,
collisionDetector: rectangleIntersection
},
manager
);
// Child will be preferred when both overlap
CollisionPriority Enum
enum CollisionPriority {
Lowest = 0 ,
Low = 1 ,
Normal = 2 ,
High = 3 ,
Highest = 4 ,
}
Higher priority droppables take precedence when multiple collisions are detected.
See Also