Vue Drag & Drop Library - Core Package

Core package of the Vue Drag & Drop library with essential hooks and functionality.
Inspired by the popular React DnD Kit library, adapted for Vue.js
Lightweight & High Performance
Vue DnD Kit is designed to be extremely lightweight while delivering exceptional performance. The library has been optimized for:
- 🚀 Minimal bundle size - keep your application fast and responsive
- ⚡ Efficient DOM operations - optimized for handling large lists and complex interactions
- 🔄 Smart rendering - prevents unnecessary re-renders during drag operations
- 📱 Smooth experience - even on mobile and low-powered devices
Unlimited Flexibility
The library is built with flexibility as a core principle, allowing you to implement virtually any drag and drop scenario:
- 🎯 Any UI pattern - sortable lists, kanban boards, calendars, file uploads, and more
- 🎨 Any design system - works with any UI library or custom components
- 📐 Any layout - grid, flex, or custom positioning systems
- 🔄 Any interaction model - simple drag and drop, multi-select, nested containers
Features
Core Capabilities
-
🎯 Simple Composables API
- Intuitive hooks-based approach
- Clean and declarative syntax
- Minimal boilerplate code
-
🎨 Full Customization
- Custom drag overlays
- Flexible styling system
- Animation support
- Custom drag handles
-
📱 Advanced Input Support
- Touch devices support
- Mouse events
- Multi-touch gestures
- Full keyboard navigation - complete drag and drop operations using only keyboard
Accessibility
-
♿ Keyboard Navigation
- Start and control drag operations with keyboard
- Arrow keys for movement
- Space/Enter for selection and dropping
- Escape to cancel drag operations
- Tab navigation between draggable elements
-
🔍 Screen Reader Support
- ARIA attributes for drag and drop operations
- Descriptive announcements during interactions
- Semantic HTML structure
Performance
-
⚡ Optimized Rendering
- Virtual DOM friendly
- Minimal re-renders
- Efficient DOM updates
- Memory leak prevention
-
🔄 Smart Auto-scrolling
- Smooth scroll animations
- Configurable thresholds
- Performance-optimized
- Works with nested scrollable containers
Developer Experience
-
🔍 TypeScript Ready
- Full type coverage
- Type inference
- IDE autocompletion
- Type-safe events
-
📐 Layout Features
- Grid system support
- Flex layout compatible
- Responsive design ready
- Dynamic constraints
Advanced Features
-
🎯 Smart Grouping
- Element groups
- Zone filtering
- Nested groups
- Dynamic group validation
-
📊 Rich Events System
- Comprehensive lifecycle events
- Custom event handlers
- Drag state tracking
- Position coordinates
-
🛡️ Built-in Utilities
- Geometry calculations
- Bounding box tracking
- Position management
- Intersection detection
Integration
- 🔌 Framework Integration
- Vue 3 Composition API
- Nuxt.js compatible
- Works with SSR
- Plugin ecosystem ready
Installation
Choose your preferred package manager:
npm install @vue-dnd-kit/core @vueuse/core
yarn add @vue-dnd-kit/core @vueuse/core
pnpm install @vue-dnd-kit/core @vueuse/core
Setup as a Plugin
You can register the library as a Vue plugin in your main.ts/js file:
import { createApp } from 'vue';
import App from './App.vue';
import VueDnDKitPlugin from '@vue-dnd-kit/core';
const app = createApp(App);
// Register the plugin
app.use(VueDnDKitPlugin);
app.mount('#app');
This will make all the components and composables globally available in your application.
Basic Usage
App.vue
📄 Root Application Component
<script setup lang="ts">
import { ref } from 'vue';
import Draggable from './components/Draggable.vue';
import Droppable from './components/Droppable.vue';
const handleDrop = () => (elementInDropZone.value = true);
const handleEnd = () => (elementInDropZone.value = false);
const elementInDropZone = ref<boolean>(false);
</script>
<template>
<div>
<Draggable v-if="!elementInDropZone"> drag me </Draggable>
<Droppable @drop="handleDrop">
<Draggable
v-if="elementInDropZone"
@end="handleEnd"
>
im in drop zone
</Draggable>
</Droppable>
</div>
</template>
Draggable.vue
🧩 components/Draggable.vue
<script setup lang="ts">
import { useDraggable } from '@vue-dnd-kit/core';
const emit = defineEmits<{
(e: 'end'): void;
}>();
const { elementRef, handleDragStart, isDragging } = useDraggable({
events: { onEnd: () => emit('end') },
});
</script>
<template>
<div
ref="elementRef"
@pointerdown="handleDragStart"
:class="{ dragging: isDragging }"
tabindex="0"
role="button"
aria-grabbed="false"
:aria-pressed="isDragging"
>
<slot />
</div>
</template>
<style scoped>
.dragging {
opacity: 0.5;
}
</style>
Droppable.vue
🧩 components/Droppable.vue
<script setup lang="ts">
import { useDroppable } from '@vue-dnd-kit/core';
const emit = defineEmits<{
(e: 'drop'): void;
}>();
const { elementRef, isOvered } = useDroppable({
events: { onDrop: () => emit('drop') },
});
</script>
<template>
<div
ref="elementRef"
:class="{
droppable: true,
'is-overed': isOvered,
}"
role="region"
aria-dropeffect="move"
>
drop here
<slot />
</div>
</template>
<style scoped>
.droppable {
width: 100px;
height: 100px;
border: 1px solid black;
}
.is-overed {
background-color: #f0f0f0;
border: 1px dashed red;
}
</style>
📄 License
MIT © ZiZiGY
🎉 Congratulations on the official release! 🎉
Made with ❤️ for the Vue.js community