# vue-draggable-next wraps Sortable.js in a Vue 3 component, and picks up every option

> vue-draggable-next is a Vue 3 drag-and-drop component built on Sortable.js, with Composition API and Options API examples, TypeScript definitions, and a props and events surface that passes Sortable.js options straight through. It weighs about 7kb gzipped and needs no CSS framework.

**anish2690/vue-draggable-next** — Vue 3 drag-and-drop component

- Repository: https://github.com/anish2690/vue-draggable-next
- Website: https://vue-draggable-next.vercel.app
- Stars: 556 · Forks: 52
- Language: TypeScript
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/anish2690-vue-draggable-next

## A Sortable.js binding, not a reimplementation of dragging

vue-draggable-next is described as a Vue 3 drag-and-drop component based on Sortable.js, and the feature list says all Sortable.js options are supported.

That is the important structural fact. The component is a Vue-shaped wrapper around the Sortable.js library, so the behaviour you get is Sortable.js behaviour, and the options are Sortable.js options. The Vue 3 component adds the part a library like that cannot do on its own, which is the connection to a reactive array in your component, with v-model or a list prop.

The claimed size is about 7kb gzipped, and the other claims in the list are Vue 3 Composition API support, touch-friendly behaviour for mobile, TypeScript definitions included, and no CSS framework dependency. That last one matters more than it sounds: a drag-and-drop component that forces a specific styling system into your app is a much harder thing to adopt than one that leaves your markup and CSS alone.

The repository is a TypeScript project, the package is MIT licensed, and the homepage is a live demo and playground at vue-draggable-next.vercel.app. The topics list includes vite, vue3, vue-next and drag-drop, and the build tooling in the tree reflects a modern setup with Vite, Rollup, Tailwind and Jest.

## Installing it and the two ways to use it

The installation section gives the three package managers.

```bash
npm install vue-draggable-next
```

The same package is available through yarn and pnpm, with the commands given in the README.

Then there is the choice that determines how your code is shaped, and the README documents both forms. The Composition API example uses script setup with lang="ts", defines the item type as an interface, holds the list in a ref, and imports the component as VueDraggableNext.

```vue
import { ref } from 'vue'
import { VueDraggableNext } from 'vue-draggable-next'

// Define the item type
interface Person {
  id: number
  name: string
}

// Reactive list
const list = ref<Person[]>([
  { id: 1, name: 'John' },
  { id: 2, name: 'Jane' },
  { id: 3, name: 'Bob' }
])

// Handle changes
const onListChange = (event: any) => {
  console.log('List changed:', event)
}
```

The Options API example registers the component under the name draggable and returns the list from data().

```vue
import { defineComponent } from 'vue'
import { VueDraggableNext } from 'vue-draggable-next'

export default defineComponent({
  components: {
    draggable: VueDraggableNext
  },
  data() {
    return {
      list: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        { id: 3, name: 'Item 3' }
      ]
    }
  },
  methods: {
    handleChange(event: any) {
      console.log('Changed:', event)
    }
  }
})
```

Note that in the Options API form the component is registered locally under a local name, while in the Composition API examples elsewhere in the README it is aliased at import time, as VueDraggableNext as draggable. That difference is the kind of thing that trips people up when they move between the two examples, and it is worth checking which form the migration guide uses.

## The props table, and why itemKey is the one that matters

The API reference is a props table and an events table, and reading the props table tells you how the component thinks.

There are two ways to give it data. modelValue is the Array to be synchronized with drag-and-drop, used with v-model, and list is the alternative, an Array that the component directly mutates. The distinction matters for a Vue 3 codebase because v-model and direct mutation are two different data flow models, and the component supports both so it can sit in either style of application.

Then there is the rendering surface. tag is the HTML tag for the root element and defaults to 'div'. component names a Vue component to use as the root element instead. componentData passes props and attributes to that component. So the root of a draggable region can be a plain div, a transition-group, or any component of your own, and that is what makes the transitions example in the README possible.

itemKey is the prop to pay attention to. Its type is String or Function, its default is undefined, and the description says it is the key to use for tracking items and recommends it for better performance. That is the one prop that changes how the component identifies your objects, and leaving it unset means the component is tracking items by something other than a key you chose.

The behavioural props are the Sortable.js set: clone and move as functions, group as a String or Object for group options, sort, disabled, animation in milliseconds, and the three CSS class hooks ghostClass, chosenClass and dragClass, which default to empty strings and are how you style the placeholder, the picked item and the item being dragged.

## Events, and the one that is not a Sortable event

The events table lists nine of them, and eight of the nine are Sortable.js lifecycle events with a SortableEvent payload: @start when dragging started, @end when dragging ended, @add when an item was added from another list, @remove when an item was removed to another list, @update when the item order changed, @sort for any change to the list, @choose when an item is chosen and @unchoose when it is unchosen.

The exception is @change, which fires when the list changes and carries a payload of added, removed and moved, each optional. That is the one to use when you want to know what actually happened to your data rather than that a drag gesture ended.

The distinction is worth internalising because it is where the two models meet. The Sortable events are about the interaction, and they fire on gestures. The change event is about the array, and it tells you what the array now contains. A board application that needs to persist a reorder will usually care about @change, and one that needs to drive a visual affordance during the drag will care about @choose and @unchoose.

The cross-list cases are covered by the group prop, and the README's example of two lists sharing a group name is the canonical use: one list for todo, one for done, and an item dragged from one to the other arrives with @remove in the source and @add in the target.

## Building it: Rollup for the package, Vite for the playground

The package scripts show a project with two build systems, which is normal for a Vue component that ships as a library and also runs a live playground.

The library build is Rollup, run through a rollup.config.js at the repository root, and the type declarations are produced separately by api-extractor, which runs the api-extractor configuration present in the tree. The test script chains the unit tests, the build and the declaration build, so a release cannot be produced with a broken bundle or stale types.

The playground is Vite, with playground:dev running the dev server and playground:start running it in production mode. The demo/ directory at the top level holds a Vite application, and the repository also has a vuex-shim.d.ts, which tells you the demo uses a Vuex style store, along with a router.ts and an index.ts entry point.

Unit tests run on Jest with coverage, and there is a separate test:types script that runs tsc with noEmit and skipLibCheck over the source. Linting is prettier with the typescript parser across the source, test and end to end directories. Changelog entries are generated with conventional-changelog using the angular preset.

The published files list is small and deliberate: the dist JavaScript bundles, the type declarations, the licence and the readme. There is no CSS file to import, which is the concrete form of the no CSS framework dependency claim.

## Where vue-draggable-next is the wrong choice

Three cases, and the middle one is the most likely to catch someone.

The first is Vue 2. The package exists as the Vue 3 line, and the README links a migration guide for moving from Vue 2. If you are on Vue 2 today, the honest answer is that this package is for after the upgrade, not for now, and the migration guide is a document you would need to read before deciding.

The second is very large lists. The component renders its children through the DOM, and the itemKey prop is recommended for better performance, which tells you the tracking strategy matters. A sortable list of hundreds of items is comfortable. A list of tens of thousands, where the cost is not the drag but the number of elements in the document, needs a virtualised list, and a virtualised list and a drag-and-drop component that manages real DOM nodes are in tension.

The third is accessibility and alternative input. The README documents touch support for mobile, and the examples show a custom handle with a drag-handle class and a cursor change. What the documentation does not describe is a keyboard-based reordering mode, which is what a fully accessible implementation would need, since a mouse-only drag is not usable without a pointer. If your product has an accessibility requirement, that is the gap to check before committing.

A smaller practical note: the component mutates or synchronises an array of your objects, and with the list prop that mutation is direct. In a strict codebase, modelValue with v-model gives you a clearer data flow than handing the component an array to mutate.

## Conclusion

Adopt vue-draggable-next if you are on Vue 3, need sortable lists and cross-list dragging, and want Sortable.js behaviour without wiring the library to the DOM yourself. Do not adopt it if you need virtualised lists of tens of thousands of items, or if you are still on Vue 2, since the migration path is the reason this package exists. Before you build on it, read the migration guide section of the README and check the itemKey prop, because the component tracks items by key and the default is undefined.

## FAQ

### How do I install vue-draggable-next?

Run npm install vue-draggable-next, or the equivalent yarn add or pnpm add command. The README also links a live demo and playground and a migration guide for projects coming from Vue 2.

### What is the difference between modelValue and list in vue-draggable-next?

modelValue is the array synchronized with drag and drop, used with v-model, while list is the alternative that the component directly mutates. The README describes both props with an Array type and an empty array default.

### Which event should I use to know what changed in a vue-draggable-next list?

The @change event, which fires when the list changes and carries added, removed and moved entries, each optional. The other events, such as @start, @end, @add, @remove, @update, @sort, @choose and @unchoose, are Sortable.js lifecycle events that report the interaction rather than the resulting array.

### What is the itemKey prop for in vue-draggable-next?

itemKey is the key used for tracking items, with a type of String or Function and a default of undefined, and the README recommends it for better performance.

## Sources

- [anish2690/vue-draggable-next on GitHub](https://github.com/anish2690/vue-draggable-next)
- [License: MIT](https://github.com/anish2690/vue-draggable-next/blob/master/LICENSE)
- [Project website](https://vue-draggable-next.vercel.app)
- [README](https://github.com/anish2690/vue-draggable-next/blob/master/README.md)
- [Releases](https://github.com/anish2690/vue-draggable-next/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/anish2690-vue-draggable-next
