Quick Start
This guide will help you create your first drag and drop interface with Vue DnD Kit. We'll build a simple draggable element that can be moved around the screen.
Prerequisites
Before you begin, make sure you have:
- Installed Vue DnD Kit as described in the Installation guide
- Registered the Vue DnD Kit plugin in your main application file
Basic Draggable Element
Let's start by creating a simple draggable element:
vue
<script setup>
import { useDraggable } from '@vue-dnd-kit/core';
const { elementRef, isDragging, handleDragStart } = useDraggable({
id: 'my-draggable',
});
</script>
<template>
<div
ref="elementRef"
:class="{ dragging: isDragging }"
@pointerdown="handleDragStart"
>
Drag me!
</div>
</template>
<style scoped>
div {
padding: 20px;
background-color: #4caf50;
color: white;
border-radius: 4px;
cursor: grab;
user-select: none;
width: 150px;
text-align: center;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.dragging {
opacity: 0.8;
cursor: grabbing;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
</style>
This creates a green box that you can drag around the screen. When dragging, it becomes slightly transparent and the shadow changes to indicate the dragging state.
Creating a Drop Zone
Now, let's create a drop zone where our draggable element can be dropped:
vue
<script setup>
import { useDraggable, useDroppable } from '@vue-dnd-kit/core';
const {
elementRef: draggableRef,
isDragging,
handleDragStart,
} = useDraggable({
id: 'my-draggable',
});
const { elementRef: dropzoneRef, isOver } = useDroppable({
id: 'my-dropzone',
});
</script>
<template>
<div class="container">
<div
ref="draggableRef"
:class="{ dragging: isDragging }"
@pointerdown="handleDragStart"
>
Drag me to the drop zone!
</div>
<div
ref="dropzoneRef"
:class="{ over: isOver }"
class="dropzone"
>
Drop here
</div>
</div>
</template>
<style scoped>
.container {
display: flex;
gap: 20px;
padding: 20px;
}
div {
padding: 20px;
border-radius: 4px;
user-select: none;
text-align: center;
}
div[ref='draggableRef'] {
background-color: #4caf50;
color: white;
cursor: grab;
width: 150px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
}
.dragging {
opacity: 0.8;
cursor: grabbing;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.dropzone {
background-color: #f5f5f5;
border: 2px dashed #ccc;
width: 200px;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
}
.over {
background-color: #e0f7fa;
border-color: #00bcd4;
}
</style>
Now we have a draggable element and a drop zone. The drop zone changes its appearance when the draggable element is over it.
Handling Drop Events
Let's enhance our example to handle drop events:
vue
<script setup>
import { ref } from 'vue';
import { useDraggable, useDroppable } from '@vue-dnd-kit/core';
const message = ref('Drag the item to the drop zone');
const isDropped = ref(false);
const {
elementRef: draggableRef,
isDragging,
handleDragStart,
} = useDraggable({
id: 'my-draggable',
});
const { elementRef: dropzoneRef, isOver } = useDroppable({
id: 'my-dropzone',
events: {
onDrop: () => {
message.value = 'Item dropped successfully!';
isDropped.value = true;
setTimeout(() => {
message.value = 'Drag the item to the drop zone again';
isDropped.value = false;
}, 2000);
},
},
});
</script>
<template>
<div class="container">
<p>{{ message }}</p>
<div class="content">
<div
ref="draggableRef"
class="draggable"
:class="{ dragging: isDragging, dropped: isDropped }"
@pointerdown="handleDragStart"
>
{{ isDropped ? '✓' : 'Drag me!' }}
</div>
<div
ref="dropzoneRef"
:class="{ over: isOver, dropped: isDropped }"
class="dropzone"
>
Drop here
</div>
</div>
</div>
</template>
<style scoped>
.container {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
}
.content {
display: flex;
gap: 30px;
margin-top: 20px;
}
p {
font-size: 16px;
color: #333;
margin-bottom: 20px;
}
.draggable {
padding: 20px;
background-color: #4caf50;
color: white;
border-radius: 4px;
cursor: grab;
user-select: none;
width: 100px;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}
.dragging {
opacity: 0.8;
cursor: grabbing;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.dropzone {
padding: 20px;
background-color: #f5f5f5;
border: 2px dashed #ccc;
border-radius: 4px;
width: 150px;
height: 150px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.over {
background-color: #e0f7fa;
border-color: #00bcd4;
}
.dropped {
background-color: #e8f5e9;
border-color: #4caf50;
color: #4caf50;
font-weight: bold;
}
.dropped {
background-color: #4caf50;
color: white;
font-size: 24px;
}
</style>
This example adds:
- A message that updates based on the interaction state
- Visual feedback when an item is successfully dropped
- A reset mechanism to allow repeated interactions