Documentation/Changelog
3.0.0-beta.2
Files and other apps, drop targets that shape the overlay, drags that don't wait for landings, an overlay that lifts and settles, and filtered lists.
npm i @vue-dnd-kit/core@3.0.0-beta.2
Files and other apps
The browser's own drag and drop now runs through the provider, as drags like any other. A
drop target, a list or a tree with external takes files, links and text from other apps:
a list makes room for them while they are held, and createItem turns them into items,
several at once. A native item is dragged out of the page by the mouse: into another app,
or into a second window of yours, where the lists of its group take it.
Chargement de la démo…
<script setup lang="ts">
import { DnDProvider } from '@vue-dnd-kit/core';
import Board from './Board.vue';
</script>
<template>
<DnDProvider>
<Board />
</DnDProvider>
</template>makeSortableList(grid, {
items: cards,
group: 'moodboard',
external: { files: 'image/*', links: true, text: true },
// Asked while the drag is held (a tile that says what is coming), then at the drop.
createItem: fromOutside,
});
makeSortableItem(el, {
item: () => props.card,
// What other apps get: a link, a file to save, a text.
native: { data: () => toOutside(props.card) },
});
Plain drop zones take files too: makeDroppable(el, { external: { files: 'application/pdf' } }).
The end event says what the other app did with a drag out (droppedOutside). See
files and other apps.
Drop targets shape the overlay
A drop target can change what the drag looks like over it: overOverlay and
overDropAnimation on makeDroppable, lists and trees. Its component gets
the drag's own overlay as its default slot, to wrap it or leave it out. Overlay components
also get to: where a drop would put the items now.
Chargement de la démo…
<script setup lang="ts">
import { DnDProvider } from '@vue-dnd-kit/core';
import Mailbox from './Mailbox.vue';
</script>
<template>
<!-- The mailbox reads the selection with `useDnD()`: it renders inside the provider. -->
<DnDProvider>
<Mailbox />
</DnDProvider>
</template>makeDroppable(el, {
id: props.folder.id,
overOverlay: MovePill, // "Move 2 to Archive" while over it
overDropAnimation: intoFolder,
});
See targets that change the overlay and where the drop would go.
Drags don't wait for landings
A decided drop hands its overlay to a flight of its own, and the next drag starts at once. A
press on a landing box catches it mid-flight, and the drag goes on from there.
onDragSettle tells when an overlay is home: the trash below shuts its lid then.
Chargement de la démo…
<script setup lang="ts">
import { DnDProvider } from '@vue-dnd-kit/core';
import Gallery from './Gallery.vue';
</script>
<template>
<DnDProvider>
<Gallery />
</DnDProvider>
</template>- In a multi-drag every clone flies: back home on a cancel, to its slot on a drop, into the
zone one after another.
overlayPreviewssets how many items get a clone (5 by default, or'all'). - The drop waits for the CSS animations and transitions running in the overlay as it lands: the photo above crumples on its own.
- Each draggable, item and list may bring its own
dropAnimation; the target'soverDropAnimationwins.
An overlay that lifts and settles
The overlay box now holds a content element, [data-dnd-overlay-content]: the library moves
and sizes the box, you animate the content. The provider's overlay-class puts your classes
on it, and a transition from @starting-style lifts it as the drag picks up.
Chargement de la démo…
<script setup lang="ts">
import { ref } from 'vue';
import { DnDProvider } from '@vue-dnd-kit/core';
import Lane from './Lane.vue';
const lanes = ref([
{
id: 'applied',
title: 'Applied',
people: [
{ id: 'ava', name: 'Ava Stone', role: 'Designer', hue: 20 },
{ id: 'ben', name: 'Ben Ito', role: 'Engineer', hue: 200 },
{ id: 'cleo', name: 'Cleo Diaz', role: 'Writer', hue: 300 },
],
},
{ id: 'interview', title: 'Interview', people: [{ id: 'dan', name: 'Dan Ruiz', role: 'Engineer', hue: 140 }] },
{ id: 'hired', title: 'Hired', people: [] },
]);
</script>
<template>
<!-- `overlay-class`: the overlay's content, the whole of what follows the pointer, lifts as one. -->
<DnDProvider overlay-class="pipeline-hand">
<div class="pipeline">
<Lane v-for="lane in lanes" :key="lane.id" :lane="lane" />
</div>
</DnDProvider>
</template>
<style scoped>
.pipeline {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 12px;
width: 100%;
max-width: 600px;
margin: 0 auto;
}
</style>
<!-- Not scoped: the overlay's content element is the library's, rendered outside this component. -->
<style>
@media (prefers-reduced-motion: no-preference) {
/* Picked up, the whole overlay lifts and tilts; let go, it lies flat again as it lands. */
.pipeline-hand {
transition:
rotate 0.25s cubic-bezier(0.2, 0.8, 0.2, 1),
scale 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
}
[data-dnd-overlay='dragging'] > .pipeline-hand {
rotate: 3deg;
scale: 1.05;
}
/* Where the lift starts: the box appears already `dragging`, a transition needs a before. */
@starting-style {
[data-dnd-overlay='dragging'] > .pipeline-hand {
rotate: 0deg;
scale: 1;
}
}
}
</style>[data-dnd-overlay='dragging'] > .pipeline-hand {
rotate: 3deg;
scale: 1.05;
}
@starting-style {
[data-dnd-overlay='dragging'] > .pipeline-hand {
rotate: 0deg;
scale: 1;
}
}
When the box turns dropping, the transition runs back and the drop waits for it. A change
of overlay component crossfades (overlayTransition). See
the overlay: lift, tilt, settle.
Filtered lists
filter shows some of a list's items, and a drag sorts among those. The drop writes the whole
array, with the hidden items in their places.
Chargement de la démo…
<script setup lang="ts">
import { ref } from 'vue';
import { DnDProvider } from '@vue-dnd-kit/core';
import Backlog from './Backlog.vue';
import type { Task } from './TaskRow.vue';
// In priority order: the array is the backlog.
const tasks = ref<Task[]>([
{ id: 1, title: 'Login fails on Safari', tag: 'bug' },
{ id: 2, title: 'Dark mode for settings', tag: 'feature' },
{ id: 3, title: 'Document the export API', tag: 'docs' },
{ id: 4, title: 'Crash when the list is empty', tag: 'bug' },
{ id: 5, title: 'Keyboard shortcuts', tag: 'feature' },
{ id: 6, title: 'Typo in the pricing page', tag: 'docs' },
{ id: 7, title: 'Slow search with 10k rows', tag: 'bug' },
{ id: 8, title: 'Share a board by link', tag: 'feature' },
]);
</script>
<template>
<DnDProvider>
<Backlog v-model="tasks" />
</DnDProvider>
</template>const { items } = makeSortableList(list, {
items: tasks,
filter: (task) => (!tag.value || task.tag === tag.value) && task.title.includes(query.value),
});
And also
- Lists resize smoothly. A list or a tree grows and shrinks to its new size as items come
in and leave, at the drop and for
animateChangeschanges (animateSize, on by default). labelon items, lists, trees and drop targets: what screen readers call them ("Sunset.svg dropped at position 2 of 5 in Moodboard.").- Several lists in one component: items find their list by the DOM.
snapToGridsnaps one axis when only its size is given.- The cursor of the grabbed element stays during the drag (
--dnd-cursor). data-dnd-placeholder="into"while a drop goes into a target inside an item: style the folder the files go into.- Scrolling during a drag: axis locks keep the drag on its row (
containerShiftfor modifiers), and an overlay landing while the page scrolls still finds its slot. - Partial accepts on drop targets: when
onBeforeDroptakes only some of the dragged items, the target'sonDropsays which (accepted, and the newrejected). - Lists and trees take
activation, their items' default, anddata, whatover.datasays over them;group.puttakes types, as a drop target'sacceptdoes. drag-resumeon the provider, foronBeforeDropanswering'continue'.- Development warnings for two draggables or targets sharing an id, for a drag asked
for while
onBeforeDropdecides, and forexternalwithoutcreateItem. Production builds drop them. - Less work at pickup, per frame and on tree drops.
New examples: whole apps, the way you would build them, each in a full-screen demo.
Upgrading from beta.1
- Renamed options:
animate→animateChangeson lists, trees and the provider (<DnDProvider animate-changes>);keyboard→keyboardModeonmakeDraggable(the provider'skeyboardstays).
makeSelectionAreahas noselectionoption: the band always selects into the provider's selection (useDnD().selection).- The overlay box has a content element. What the overlay shows sits in
[data-dnd-overlay] > [data-dnd-overlay-content], and the default clone in a box inside it (the box carries the item's inherited custom properties). A child selector such as[data-dnd-overlay] > .cardno longer matches: write[data-dnd-overlay] .card. Descendant selectors and[data-dnd-overlay='dragging']work as before. - A new drag starts while the last one lands.
activereadsnullas soon as a drop is decided, as before, but the overlay may still be flying when the next drag begins. Code that ran whenstatuswent back to'idle'after a drop: useonDragSettle. - The drop waits for the overlay's own animations, two seconds at most. An overlay
component with a long CSS transition on
status: 'dropping'now delays the end of the drop until it finishes. - Lists animate their size (
animateSize). A list whose container has a fixed size isn't affected; to keep the old jump, passanimateSize: false. - A press on a handle that doesn't move is a click: a button used as a handle gets its
click. - Overlay components get only the props they declare: the overlay's props no longer fall through to their root element as attributes.
defaultStyles: falseremoves only the looks (the dimmed placeholders). What drags rely on stays: no text selection and no scroll anchoring while dragging, the drag cursor, no link callout on a long press on iOS.- A drop target's
onDropgets the end event (DnDEndEvent): the same fields, plusdropped,acceptedandrejected. A partial accept used to show only inonDragEnd.
All changes
Features
- Native drag and drop:
externalon drop targets, lists and trees;nativeon draggables and items; drags between windows of the app by group;droppedOutsideon the end event.createItemmay return several items and is asked again at the drop. labelon items, lists, trees and drop targets, for the announcements.filteron sortable lists.- Several lists and trees in one component.
snapToGridsnaps one axis when only its size is given.- The drag keeps the grabbed element's cursor (
--dnd-cursor). data-dnd-placeholder="into"while the drop goes into a target in an item.- The overlay content element and the provider's
overlayClass;animateSize. - Drop targets shape the overlay:
overOverlayandoverDropAnimationonmakeDroppable, lists and trees;dropAnimationon draggables, items and lists;overin the drop animation's context. - Renamed:
animate→animateChanges, the draggable'skeyboard→keyboardMode.makeSelectionArealost itsselectionoption. - The provider's
overlayTransitionanimates a change of overlay component. - Overlay components get
to, where a drop would put the items. - Drags don't wait for landings; a press catches a landing box;
onDragSettle(provider:drag-settle);overlayPreviews. - Multi-drag: plain draggables show a pile; every clone flies home on a cancel; into a zone the clones go in one after another.
- Development warnings for shared ids and for input while a drop is decided.
- A drop target's
onDropgetsacceptedandrejected(also onDnDEndEvent). activationanddataon lists and trees;group.puttakes types.- The provider emits
drag-resume. - The behaviour styles are always injected;
defaultStyles: falsedrops only the looks.
Fixes
- The keyboard sends the slot home over plain targets, crosses lists stacked along their axis, and keeps the overlay on the line past the end of an indicator list.
- A handle press without movement is a click; the selection area captures the pointer only once it moves.
- The clone carries the item's custom properties on a box around it, not inline.
- Indicator lines when nesting in place; insert mode over indicator trees; lists with
createItemignore the items of other groups. e.source.remove()takes the items only out of the lists they came from.- Landing overlays no longer jump when drags follow each other quickly, with the default drop animation, GSAP or motion, nor for a frame when the next drag reorders their list.
- A
nativemouse drag askscanDrag; the selection area's cancel key matcheskeyas well ascode. - A pointer past the edge of a scrolled list points at the item at that edge: while auto-scroll brings items past it, the slot goes along, and a drop out there lands where the slot is. It used to stay where the pointer last was over an item (virtual lists).
- Auto-scroll measures the way toward an edge from where the drag started: a pointer that is at the edge by its first frame (a busy machine, coalesced input) scrolls too.
- Multi-drag items without a clone show as the drop starts and fade in; a
'group'block over a plain target outside the lists comes apart; a drop lands with the overlay its target showed when let go. - On a cancel, the other dragged items stay placeholders until their clones are home.
- Keyboard pickups during a landing; an end announced as
''silences the pending move text; a provider unmounting whileonBeforeDropdecides cancels the drag. - A dropped overlay lands on its slot when the page scrolls mid-flight; axis locks keep the drag on its row when the page scrolls; an element dragged without an overlay stays under the pointer when the page scrolls.
Performance
- A drag starting or ending updates the attributes of the dragged items only.
- A drop target inside a sortable item asks its list once per detection, not once per target.
- A tree drop finds the moved nodes and their new parent in one walk.
- The clones of a
'stack'multi-drag are taken in one style snapshot.
The commits: core-v3.0.0-beta.1...core-v3.0.0-beta.2.