Docs/API
Animations
The options and hooks of the animations — sorting, the drop, and changes no drag made.
The provider's animation (layout moves while sorting), dropAnimation (the overlay landing)
and animateChanges (data changes no drag made) take false, options, or your own function — for
GSAP or motion. Lists and trees can override animation and animateChanges; draggables, items
and lists can bring their own dropAnimation, and drop targets an overDropAnimation. See
Animations.
<DnDProvider :animation="{ duration: 180, easing: 'ease-out' }" :drop-animation="false" />
Each lane below is a provider of its own that gives animation, dropAnimation and animateChanges
the same kind of value (animateChanges takes a function in move).
Loading the demo…
<script setup lang="ts">
import { ref } from 'vue';
import { DnDProvider, type AutoAnimation, type DropAnimation, type LayoutAnimation } from '@vue-dnd-kit/core';
import AnimLane from './AnimLane.vue';
import { tiltDrop, tiltMove } from './tilt';
const SLOW = { duration: 700, easing: 'ease-in-out' };
// One shape per lane, for all three options: sorting, the drop, and changes no drag made.
const lanes: { label: string; animation: LayoutAnimation; dropAnimation: DropAnimation; animateChanges: AutoAnimation }[] = [
{ label: 'true', animation: true, dropAnimation: true, animateChanges: true },
{ label: 'false', animation: false, dropAnimation: false, animateChanges: false },
{ label: '{ duration: 700 }', animation: SLOW, dropAnimation: SLOW, animateChanges: SLOW },
// `animateChanges` takes no function itself: its parts (`move`, `enter`, `leave`) do.
{ label: 'ƒ tilt', animation: tiltMove, dropAnimation: tiltDrop, animateChanges: { move: tiltMove } },
];
const letters = ['A', 'B', 'C', 'D'];
const rows = ref(lanes.map(() => letters.map((id, i) => ({ id, hue: 150 + i * 40 }))));
/** The same new order in every lane (Fisher–Yates: every order as likely): `animateChanges` plays it four ways. */
const shuffle = () => {
const order = [...letters];
for (let i = order.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[order[i], order[j]] = [order[j]!, order[i]!];
}
rows.value = rows.value.map((lane) => order.map((id) => lane.find((row) => row.id === id)!));
};
</script>
<template>
<div class="demo">
<code><DnDProvider :animation="shape" :drop-animation="shape" :animate-changes="shape"></code>
<div class="lanes">
<!-- A provider per lane: each one has its own animations. -->
<DnDProvider
v-for="(lane, index) in lanes"
:key="lane.label"
:animation="lane.animation"
:drop-animation="lane.dropAnimation"
:animate-changes="lane.animateChanges"
>
<AnimLane v-model="rows[index]!" :label="lane.label" />
</DnDProvider>
</div>
<button type="button" @click="shuffle">Shuffle all</button>
</div>
</template>
<style scoped>
.demo {
display: flex;
flex-direction: column;
align-items: center;
gap: 14px;
}
code {
max-width: 100%;
font: 11px/1.4 ui-monospace, Menlo, Consolas, monospace;
text-align: center;
opacity: 0.7;
}
button {
padding: 6px 12px;
border: 0;
border-radius: 8px;
background: #42b883;
color: #fff;
font: 600 12px/1 system-ui, sans-serif;
cursor: pointer;
}
button:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
.lanes {
display: grid;
grid-template-columns: repeat(4, 128px);
gap: 8px;
}
@media (max-width: 560px) {
.lanes {
grid-template-columns: repeat(2, 128px);
}
}
</style>Options
The timing of an animation. What is left out keeps the default of that animation.
Sorting
How items move to their new places: true (default timing), options, false (they jump), or a function that animates one item from from to to and returns its Animation, a promise that settles when it ends, or nothing.
type LayoutAnimation = | boolean | AnimationOptions | ((context: LayoutAnimationContext) => Animation | Promise<unknown> | void)What a layout animation function gets, for one item that moves to its new place.
KeyKey of the item.
HTMLElementThe item's element, already in its new place.
RectVisual rect before the change (where a running animation showed the item).
RectLayout rect after the change.
Required<AnimationOptions>The timing the options give, defaults filled in.
'drag' | 'change'What moved the item: a drag ('drag': sorting, the drop, a cancel), or a change of your data that no drag made ('change', with the list's animateChanges on).
AbortSignalAborted when the library interrupts the animation: the item moves again before it ends (the next animation starts where it is shown), or animations are turned off. A returned Animation is cancelled for you. Stop anything else here and undo the styles it set, at once: the layout is measured right after.
booleanprefers-reduced-motion: reduce is set. The library's own animations don't run then; functions of yours always do, and decide with this (skip, or keep a fade).
The drop
How the overlay lands on a drop and flies back on a cancel: true (default timing), options, false (no flight: it ends where it was let go), or a function that animates overlay from from to to and returns its Animation, a promise that settles when it ends, or nothing.
type DropAnimation = | boolean | AnimationOptions | ((context: DropAnimationContext) => Animation | Promise<unknown> | void)What a drop animation function gets: the overlay, where it is and where it lands.
HTMLElementThe overlay box; it lands on the active item's slot. In a multi-drag the clones of the other items riding inside it (the default overlay's, the DragPreviews of a custom one) land on their own slots by themselves (with the default timing when this is a custom function).
RectWhere the overlay is when the drag ends.
Rect | nullFinal rect of the dropped item; null when it isn't rendered or visible (the overlay fades out).
Rect | nullThe item isn't shown after a drop on a zone (not a sortable list), e.g. it was dropped into another item (a folder) or a trash zone: the zone's visible rect. The default animation shrinks the overlay into it as it fades out, instead of fading in place.
'drop' | 'cancel''drop': the overlay lands where the drop put the item. 'cancel': it flies back to where the item was.
ActiveThe drag that ended.
Over | nullThe target the drop lands on (a list, a zone); null on a cancel.
Required<AnimationOptions>The timing the options give, defaults filled in.
booleanprefers-reduced-motion: reduce is set. The library's own animations don't run then; functions of yours always do, and decide with this (skip, or keep a fade).
Data changes
Animates changes of a list's (or tree's) items that no drag made: items added, removed, moved (a sort, a shuffle, a move between lists of one group) or filtered. Off by default (false); true animates moves, entering and leaving items with the default timing. Drags keep their own animations (animation, dropAnimation). With prefers-reduced-motion: reduce the default animations don't run; functions of yours still do (with reducedMotion: true). Only items near the visible area animate (unmounted rows of a virtual list are skipped).
type AutoAnimation = boolean | AutoAnimationOptionsanimateChanges with its parts: duration and easing for all of them, and per kind of change true, options (over the shared ones), false, or a function of your own.
true, options, false (the item just appears), or a function that animates it in.
type EnterAnimation = | boolean | AnimationOptions | ((context: EnterAnimationContext) => Animation | Promise<unknown> | void)An item that appeared in a list with animateChanges on: added, or shown again (a filter, an expanded tree node).
KeyKey of the item.
HTMLElementThe item's element, already in its place.
RectWhere it appeared (layout rect).
Required<AnimationOptions>The timing the options give, defaults filled in.
booleanprefers-reduced-motion: reduce is set. The library's own animations don't run then; functions of yours always do, and decide with this (skip, or keep a fade).
true, options, false (the item just disappears), or a function that animates out the copy left in its place: return its Animation or a promise, and the copy is removed when it ends (at once when the function returns nothing).
type LeaveAnimation = | boolean | AnimationOptions | ((context: LeaveAnimationContext) => Animation | Promise<unknown> | void)An item that left a list with animateChanges on: removed, or hidden (a filter, a collapsed tree node).
KeyKey of the item.
HTMLElementA copy of the item's element, shown where the item was (the item itself is gone): positioned absolutely in its old parent, ignoring the pointer, marked data-dnd-leaving. The library removes it when your animation ends.
RectWhere the item was.
Required<AnimationOptions>The timing the options give, defaults filled in.
booleanprefers-reduced-motion: reduce is set. The library's own animations don't run then; functions of yours always do, and decide with this (skip, or keep a fade).