Easy & flexible drag & drop library for Vue.js
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Moritz Marquardt 0edf0d0839 Fix text selection inside v-dragon elements 2 months ago
README.md Change name to v-dragon 3 months ago
dragon.js Fix text selection inside v-dragon elements 2 months ago
example.html Fix breaking issues, inplement dragon-handle 3 months ago
package.json Fix text selection inside v-dragon elements 2 months ago
todo.md Add example & todo 3 months ago


Vue.js Dragon

Easy & flexible unopinionated drag & drop library for Vue.js.


Using modules

import Dragon from "v-dragon"; // Install this using `npm install vuedragon`

Using browser-based JavaScript

<script src="https://cdn.jsdelivr.net/npm/v-dragon/dragon.js"></script>



An item (v-dragon) is an element that can be dragged and/or dropped, and can be a dragon-sink and/or a dragon-source.
A dragon-sink can be used to drop stuff onto, a dragon-source can be dragged onto other items. Not specifiying any of them is the same as specifiying both.


The dragon-payload is the object sent to the dragon-drop event, and should contain all necessary information so you know which thing (payload of the dragged item) has been dragged where (payload of the drop target).

The dragon-drop Event

This event is called on the drop target after a drag & drop has occurred, and its $event object contains the payload of the dragged item as from, and the payload of the drop target as to. It can then be used to run your own logic to process the event.
The $event object also contains the boolean values keyCtrl, keyAlt, keyShift, mouseLeft, mouseMiddle and mouseRight to work with modifiers. The modifiers are determined on the start of the drag process.

There’s also a dragon-drag event which is called on the dragged item instead of the drop target; to avoid confusion though, its usage is discouraged unless you need to access something only available from the source.


A dragon-class specifies the type of the object - think of it like the name property of radio buttons. You can only drag a dragon onto a dragon of the same class.


A dragon-handle is an element that can initiate a drag process (the thing where you can “grab” your item with the mouse). You can use more than one handle, and if an item contains no handle at all, it will be draggable everywhere.

Area of Effect

The dragon-aoe specifies how far away from a target something can be dropped while still considering that target. If multiple targets come into question, the closest target will be taken.
It should only be used on elements that can have a ::before pseudo-element, and don’t already have one.

CSS Classes

dragon-aim is assigned to an item (that could become a target if the mouse button is released) while hovering above it with an eligible dragged element.
dragon-use is assigned to a dragged element during a drag process.

Usage Example

        <!-- I'm a sink, so I can not be dragged, but you can drop stuff on me -->
        <!-- I also have an AoE of 25 pixels, so you don't have to aim that much -->
          v-dragon dragon-sink :dragon-payload="{dragon: null, index: -1}"

        <!-- I'm a normal dragon, you can drop stuff onto me -->
          v-for="(d, i) in dragons" v-bind:key="d"
          dragon-item :dragon-payload="{dragon: d, index: i}"
            <i dragon-handle class="fa fa-dragon"></i>
            {{ d }}
        <!-- I'm a source, so I can only be dragged -->
          v-dragon dragon- :dragon-payload="{dragon: newDragon, index: -1}"
            <i dragon-handle class="fa fa-dragon"></i>
            <input type="text" placeholder="The new dragon" v-model="newDragon">
export default {
    data() {
        return {
            dragons: ['Drogon','Rhaegal','Viserion','Balerion','Vhagar','Meraxes','Sunfyre','Syrax','Caraxes','Meleys','Vermax','Arrax','Stormcloud','Sheepstealer','Seasmoke','Silverwing','Vermithor','Shrykos','Tyraxes','Dreamfyre','Vermithrax','Ghiscar','Valryon','Essovius','Archonei','The last dragon'],
            newDragon: ""
    methods: {
        drag() {
            if (window.event.data.from.index >= 0) this.dragons.splice(window.event.data.from.index, 1); // Remove the old dragon
            this.dragons.splice(window.event.data.to.index + (window.event.data.to.index > window.event.data.from.index ? 0 : 1), 0, window.event.data.from.dragon); // Insert it at the new position
            if (window.event.data.from.index == -1) this.newDragon = ""; // Clear the newDragon field
    li { transition: box-shadow 0.5s; }
    [dragon-handle] { cursor: grabbing; }
    .dragon-aim { box-shadow: 0 0 10px #089E71; }
    .dragon-use { opacity: 0.8; }