DEV Community

Alexander
Alexander

Posted on

Introducing Vue DnD Kit: A New Library for Creating Drag and Drop Interfaces in Vue 3

Introducing Vue DnD Kit: A New Library for Creating Drag and Drop Interfaces in Vue 3 ๐Ÿš€

Hello, DEV Community! Today I want to introduce my new project โ€” Vue DnD Kit, a lightweight and performant library for creating drag and drop interfaces for Vue 3.

Why did I create another drag and drop library? ๐Ÿค”

There are already several solutions for implementing drag and drop in the Vue ecosystem, but most of them are either outdated or have limitations in performance and flexibility. Inspired by the popular dnd-kit library for React, I decided to create a similar solution for Vue 3 that would be:

  1. Lightweight โ˜๏ธ โ€” minimal impact on bundle size
  2. Performant โšก โ€” optimized to work even with large lists
  3. Flexible ๐Ÿ”„ โ€” allows implementing virtually any drag and drop scenario
  4. Accessible โ™ฟ โ€” full support for keyboard navigation and screen readers

Key Features of Vue DnD Kit โœจ

1. Simple API based on composable functions ๐Ÿ“

The library provides an intuitive API based on Vue 3 composable functions:

import { useDraggable, useDroppable } from '@vue-dnd-kit/core';
// For draggable element
const { elementRef, handleDragStart, isDragging } = useDraggable();
// For droppable area
const { elementRef: dropRef, isOvered } = useDroppable({
  events: {
    onDrop: () => console.log('Element dropped!')
  }
});
Enter fullscreen mode Exit fullscreen mode

2. Full keyboard navigation support โŒจ๏ธ

One of the unique features of the library is full keyboard control support:

  1. W A S D for moving elements
  2. Space/Enter for selecting and dropping
  3. Escape to cancel drag operation
  4. Tab for navigating between elements

This makes your interfaces accessible to all users, including those who cannot use a mouse.

3. High performance ๐ŸŽ๏ธ

Vue DnD Kit is optimized to work even with large lists and complex interfaces:

  1. Minimal component re-renders
  2. Efficient DOM operations
  3. Prevention of memory leaks

4. Full customization ๐ŸŽจ

  1. Ability to change the container appearance
  2. Ability to change the appearance of the dragged element(s)
  3. Group support
  4. Ability to completely write your own element detection sensor where automatic element priority detection and its availability works under the hood (a zone may have groups into which the element(s) cannot enter)
  5. Throttle support with custom sensor
  6. Support for animations with both CSS and JS animation libraries like GSAP, Anime.js, etc.
  7. Ability to completely write your own drop logic

Usage Examples ๐Ÿ’ป

<script setup>
  import { ref } from 'vue';
  import Draggable from './components/Draggable.vue';
  import Droppable from './components/Droppable.vue';

  const elementInDropZone = ref(false);

  const handleDrop = () => (elementInDropZone.value = true);
  const handleEnd = () => (elementInDropZone.value = false);
</script>

<template>
  <div class="container">
    <Draggable v-if="!elementInDropZone"> Drag me! </Draggable>
    <Droppable @drop="handleDrop">
      <Draggable
        v-if="elementInDropZone"
        @end="handleEnd"
      >
        I'm in the drop zone!
      </Draggable>
    </Droppable>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

SortableList ๐Ÿ“‹

Drag.vue

<script setup lang="ts">
  import { useDraggable } from '@vue-dnd-kit/core';
  import { computed } from 'vue';
  const props = defineProps<{
    source?: any[];
    index?: number;
  }>();
  const { elementRef, handleDragStart, isOvered } = useDraggable({
    data: computed(() => ({
      source: props.source,
      index: props.index,
    })),
  });
</script>
<template>
  <div
    ref="elementRef"
    @pointerdown="handleDragStart"
  >
    <slot />
    <hr v-if="isOvered" />
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

List

<script setup lang="ts">
  import { DnDOperations, useDroppable } from '@vue-dnd-kit/core';
  import Drag from 'src/components/Drag.vue';
  import { ref } from 'vue';
  const items = ref([
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' },
    { id: 3, name: 'Item 3' },
  ]);
  const { elementRef } = useDroppable({
    events: {
      onDrop: (store) => {
        DnDOperations.applyTransfer(store);
      },
    },
  });
</script>
<template>
  <div ref="elementRef">
    <TransitionGroup name="sortable-list">
      <Drag
        v-for="(item, index) in items"
        :key="item.id"
        :source="items"
        :index="index"
      >
        {{ item.name }}
      </Drag>
    </TransitionGroup>
  </div>
</template>
<style>
  .sortable-list-move,
  .sortable-list-enter-active,
  .sortable-list-leave-active {
    transition: all 0.5s ease;
  }
  .sortable-list-enter-from,
  .sortable-list-leave-to {
    opacity: 0;
    transform: translateX(30px);
  }
</style>
Enter fullscreen mode Exit fullscreen mode

How to start using ๐Ÿš€

Installation ๐Ÿ“ฆ

#npm
npm install @vue-dnd-kit/core @vueuse/core
#yarn
yarn add @vue-dnd-kit/core @vueuse/core
#pnpm
pnpm add @vue-dnd-kit/core @vueuse/core
Enter fullscreen mode Exit fullscreen mode

Adding as a plugin ๐Ÿ”Œ

import { createApp } from 'vue';
import App from './App.vue';
import VueDnDKitPlugin from '@vue-dnd-kit/core';

const app = createApp(App);

app.use(VueDnDKitPlugin);
app.mount('#app');
Enter fullscreen mode Exit fullscreen mode

Vue DnD Kit Ecosystem ๐ŸŒ

It's important to note that @vue-dnd-kit/core is just the main package of the library, which provides basic functionality for drag and drop. Additional packages are in development:

  1. @vue-dnd-kit/utils ๐Ÿ› ๏ธ โ€” a set of utilities to simplify typical scenarios
  2. @vue-dnd-kit/components ๐Ÿงฉ โ€” ready-made components for quick integration (sortable lists, kanban boards, etc.)
  3. @vue-dnd-kit/devtools ๐Ÿ” โ€” a plugin for Vue DevTools that will allow debugging the state of drag and drop in the application

These additional packages will significantly simplify the development of complex drag and drop interfaces and will be released in the near future.

Future Plans ๐Ÿ”ฎ

This is just the beginning! Plans include:

  1. Creating additional packages with ready-made components for typical scenarios
  2. Improving documentation and examples
  3. Expanding capabilities for working with nested lists
  4. Optimizing for even higher performance

Conclusion ๐ŸŽ‰

Vue DnD Kit is my contribution to the Vue ecosystem, which I hope will help developers create more interactive and accessible interfaces. It currently has a stable API and will be improved in the future. Documentation has already been added but will be improved. The library is open source, and I welcome any contributions from the community!

Repository: github.com/zizigy/vue-dnd-kit

Documentation: zizigy.github.io/vue-dnd-kit

I look forward to your feedback and suggestions in the comments!

Top comments (0)