Documentation/API
DnDProvider
Le composant qui gère le glissement — les entrées, l'overlay, la sélection, le défilement automatique et la région live — pour tout ce qui est rendu à l'intérieur.
Cette page a été traduite par IA et peut contenir des inexactitudes. Lire l'original en anglais
const DnDProvider: Component<DnDProviderProps>;Gère les glissements de tout ce qui est rendu à l'intérieur : les entrées, l'overlay, la sélection, le défilement automatique et les annonces pour lecteurs d'écran (voir DnDProviderProps).
<script setup lang="ts">
import { DnDProvider } from '@vue-dnd-kit/core';
</script>
<template>
<DnDProvider :animation="{ duration: 200 }" @drag-end="save">
<RouterView />
<template #overlay="{ items, over, accepted }">
<!-- optional: a custom overlay for every drag -->
</template>
</DnDProvider>
</template>
Chaque composable doit s'exécuter dans un composant rendu à l'intérieur d'un provider. L'objectif
est un seul provider pour toute l'application : des parties de la page reçoivent leurs propres
règles avec makeDragArea. Voir le guide du provider.
La plupart des props sont lues au moment où le provider en a besoin : changez-en une, et le glissement suivant l'utilise.
Chargement de la démo…
<script setup lang="ts">
import { computed, ref } from 'vue';
import { DnDProvider, type ActivationOptions } from '@vue-dnd-kit/core';
import PropRow from './PropRow.vue';
import DensityList from './DensityList.vue';
const ACTIVATIONS: Record<string, ActivationOptions | undefined> = {
default: undefined,
'{ mouse: { delay: 300 } }': { mouse: { delay: 300, tolerance: 5 } },
};
const overlayFit = ref<'slot' | 'source'>('slot');
const activation = ref('default');
const keyboard = ref<'true' | 'false'>('true');
const copyModifier = ref<'Alt' | 'Shift' | 'null'>('Alt');
// The provider reads its props when it needs them: a change applies to the next drag.
const props = computed(() => ({
overlayFit: overlayFit.value,
activation: ACTIVATIONS[activation.value],
// `false` turns keyboard drags off; an object sets their keys and steps.
keyboard: keyboard.value === 'true' ? undefined : (false as const),
copyModifier: copyModifier.value === 'null' ? null : copyModifier.value,
}));
const compact = ref([
{ id: 'copy', title: 'Write copy' },
{ id: 'login', title: 'Fix login' },
]);
const roomy = ref([
{ id: 'sprint', title: 'Plan the sprint' },
{ id: 'review', title: 'Review the PR' },
]);
</script>
<template>
<DnDProvider v-bind="props">
<div class="demo">
<div class="props" role="group" aria-label="DnDProvider props">
<PropRow v-model="overlayFit" name="overlay-fit" :options="['slot', 'source']" />
<PropRow v-model="activation" name=":activation" :options="Object.keys(ACTIVATIONS)" />
<PropRow v-model="keyboard" name=":keyboard" :options="['true', 'false']" />
<PropRow v-model="copyModifier" name="copy-modifier" :options="['Alt', 'Shift', 'null']" />
</div>
<div class="lists">
<DensityList v-model="compact" title="Compact" compact />
<DensityList v-model="roomy" title="Roomy" />
</div>
</div>
</DnDProvider>
</template>
<style scoped>
/* Room for every row in one list: the lists grow downward and nothing moves under the pointer. */
.demo {
display: flex;
flex-direction: column;
align-items: center;
gap: 18px;
min-height: 430px;
}
.props {
display: grid;
grid-template-columns: auto auto;
align-items: center;
gap: 6px 14px;
max-width: 100%;
padding: 12px 14px;
border: 1px solid color-mix(in srgb, currentColor 12%, transparent);
border-radius: 12px;
background: color-mix(in srgb, currentColor 3%, Canvas);
}
.lists {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: center;
gap: 14px;
}
@media (max-width: 480px) {
.props {
grid-template-columns: minmax(0, 1fr);
}
}
</style>Où l'overlay est rendu
overlayTo sort l'overlay de body : dans un <dialog> modal, qui se trouve au-dessus de tout le
reste de la page. Désactivez l'interrupteur, et les lignes que vous faites glisser disparaissent
sous le dialog. Le guide de l'overlay explique
quand c'est nécessaire.
Chargement de la démo…
<script setup lang="ts">
import { computed, ref, useTemplateRef } from 'vue';
import { DnDProvider } from '@vue-dnd-kit/core';
import ColumnList from './ColumnList.vue';
const columns = ref(['Name', 'Status', 'Owner', 'Due date', 'Priority']);
const dialog = useTemplateRef<HTMLDialogElement>('dialog');
const open = ref(false);
const intoDialog = ref(true);
// A modal <dialog> sits on the top layer, above everything in <body>, the overlay
// included. While it is open, the overlay renders inside it.
const overlayTo = computed(() => (open.value && intoDialog.value ? '#columns-dialog' : 'body'));
const show = () => {
dialog.value?.showModal();
open.value = true;
};
</script>
<template>
<DnDProvider :overlay-to="overlayTo">
<div class="sheet">
<table>
<thead>
<tr>
<th v-for="column in columns" :key="column">{{ column }}</th>
</tr>
</thead>
<tbody>
<tr v-for="row in 2" :key="row">
<td v-for="column in columns" :key="column"><span class="skeleton" /></td>
</tr>
</tbody>
</table>
<button type="button" class="primary" @click="show">Edit columns</button>
</div>
<dialog id="columns-dialog" ref="dialog" @close="open = false">
<h3>Columns</h3>
<p>Drag to change their order.</p>
<ColumnList v-model:columns="columns" />
<footer>
<label class="switch">
<input v-model="intoDialog" type="checkbox" />
Overlay inside the dialog
</label>
<button type="button" class="primary" @click="dialog?.close()">Done</button>
</footer>
</dialog>
</DnDProvider>
</template>
<style scoped>
.sheet {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
width: 100%;
}
table {
width: min(100%, 520px);
border-collapse: collapse;
font-size: 12px;
}
th {
padding: 8px;
border-bottom: 1px solid color-mix(in srgb, currentColor 15%, transparent);
font-weight: 600;
text-align: left;
white-space: nowrap;
}
td {
padding: 10px 8px;
border-bottom: 1px solid color-mix(in srgb, currentColor 8%, transparent);
}
.skeleton {
display: block;
height: 8px;
border-radius: 4px;
background: color-mix(in srgb, currentColor 10%, transparent);
}
button {
padding: 7px 14px;
border: 0;
border-radius: 8px;
font: 600 12px/1.2 system-ui, sans-serif;
cursor: pointer;
}
.primary {
background: #42b883;
color: #04130c;
}
button:focus-visible {
outline: 2px solid #42b883;
outline-offset: 2px;
}
/* No transform on the dialog: it would move the overlay's fixed position. */
dialog {
width: min(340px, calc(100vw - 32px));
box-sizing: border-box;
margin: auto;
padding: 18px;
border: 1px solid color-mix(in srgb, currentColor 14%, transparent);
border-radius: 16px;
background: Canvas;
color: CanvasText;
box-shadow: 0 30px 60px -20px rgb(0 0 0 / 0.6);
}
dialog::backdrop {
background: rgb(0 0 0 / 0.45);
}
h3 {
margin: 0;
font-size: 15px;
}
p {
margin: 4px 0 14px;
font-size: 12px;
opacity: 0.6;
}
footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-top: 16px;
}
.switch {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
}
.switch input {
accent-color: #42b883;
}
</style>Props
Les props de DnDProvider. La plupart sont lues quand le provider en a besoin : changez-en une, et le glissement suivant l'utilise.
CollisionDetectionComment la cible sous le glissement est choisie. Par défaut pointerFirst ; une autre détection intégrée (closestCorners) ou la vôtre.
Modifier[]Les modificateurs de chaque glissement, appliqués en premier : ceux des zones de glissement, des éléments déplaçables et des listes viennent après.
LayoutAnimationAnimation FLIP par défaut des listes triables.
DropAnimationComment l'overlay atterrit au dépôt et revient à sa place en cas d'annulation, quand rien de plus proche n'en définit une : l'overDropAnimation de la cible de dépôt passe en premier, puis celle propre à l'item glissé (ou celle de sa liste), puis celle-ci.
AutoAnimationanimateChanges par défaut des listes et des arbres triables : les changements de leurs items qui ne viennent pas d'un glissement. Désactivé par défaut.
boolean | AutoScrollOptionsFait défiler les conteneurs et la page quand un glissement approche de leurs bords. Par défaut true ; des options le règlent, false le désactive. Les listes, les arbres et les zones de glissement peuvent le redéfinir.
ActivationOptionsCe qu'un appui doit faire avant de devenir un glissement, par type de pointeur (voir ActivationOptions pour les valeurs par défaut). Les zones de glissement, les listes, les arbres, les items et les éléments déplaçables peuvent le redéfinir.
KeyboardOptions | falseLes glissements au clavier : leurs touches et leur pas. false les désactive ; Échap annule toujours n'importe quel glissement.
Sensor[]Ce qui transforme les entrées en glissements. Par défaut [pointerSensor, keyboardSensor] : retirez-en un, enveloppez-le ou remplacez-le, ou ajoutez le vôtre (defineSensor). Le capteur clavier annule aussi n'importe quel glissement avec Escape ; keyboard: false désactive ses glissements mais conserve ce comportement. La liste peut changer à tout moment : les capteurs qui en sortent s'arrêtent, en annulant leur glissement.
boolean | HapticsOptionsVibration des glissements tactiles. Par défaut : une vibration courte quand un glissement commence après l'appui long ; un objet en ajoute d'autres (enter, drop, refuse) ; false les désactive toutes.
string | nullLa touche (KeyboardEvent.key) qui transforme un déplacement en copie. 'Alt' par défaut ; null désactive.
string | HTMLElementOù l'overlay est rendu : un sélecteur ou un élément. 'body' par défaut. Un <dialog> modal se place au-dessus du reste de la page : les glissements à l'intérieur en ont besoin là.
'slot' | 'source'Taille de l'overlay pendant le glissement. 'slot' (par défaut) : il suit l'emplacement où l'item va atterrir ; au-dessus d'une autre liste, il prend donc la taille des items de cette liste, et le dépôt n'a pas besoin de redimensionnement. Il se redimensionne autour du pointeur, qui reste à la même proportion de la boîte. 'source' : il garde la taille de l'élément glissé. La mise en page du contenu de l'overlay par défaut est recalculée à la nouvelle taille ; il n'est jamais mis à l'échelle.
number | 'all'Multi-drag : combien d'items glissés reçoivent un clone à la saisie, celui qui a été saisi et les autres à côté de lui dans l'ordre du dépôt. 5 par défaut ; 'all' clone tous ceux qui sont rendus. L'overlay par défaut affiche les clones et compte le reste (+N) ; dans une mise en page à vous, DragPreview rend son slot pour un item sans clone. Chaque clone vole : de retour vers son item lors d'une annulation, vers son emplacement lors d'un dépôt, dans la zone où entre un dépôt, l'un après l'autre. Les clones sont pris ensemble, avec une seule mise en page par passe de snapshot pour tous, mais chacun coûte la lecture de ses styles : attention aux items longs sur les téléphones lents.
boolean | TransitionPropsComment l'overlay passe d'un composant à un autre pendant un glissement (l'overOverlay d'une cible de dépôt prend le relais, une ref d'overlay est changée) : true (par défaut) les enchaîne en fondu en 150 ms, false les échange aussitôt, et un objet donne les props d'une <Transition> Vue autour de la racine du contenu (name, mode, hooks JS pour GSAP ou motion). Sans mode: 'out-in', les deux s'affichent en même temps : donnez à celui qui part position: absolute (.<name>-leave-active) pour qu'ils s'empilent dans la boîte.
string | Record<string, boolean> | Array<string | Record<string, boolean>>Classes pour le contenu de l'overlay ([data-dnd-overlay-content]), l'élément qui remplit la boîte de l'overlay : celui à animer d'un bloc pendant que la bibliothèque déplace et dimensionne la boîte. Une transition sur lui part de @starting-style à la saisie, et revient à l'atterrissage ([data-dnd-overlay='dropping']) : le dépôt l'attend. Le CSS simple l'atteint en dehors de <style scoped> (ou avec :global(...)), Tailwind avec starting: et in-data-[dnd-overlay=dragging]:.
Partial<Announcements> | falseVos propres textes pour certains événements (voir Announcements) ; false rend la région live muette.
stringComment glisser au clavier, lu par les lecteurs d'écran pour chaque élément déplaçable (son aria-describedby). Par défaut : des instructions en anglais pour Espace, Entrée, les flèches et Échap.
booleanInjecte l'apparence par défaut : du CSS en couches, de spécificité nulle, qui estompe les placeholders et les items qu'un multi-drag laisse en place (opacity: 0.4). Par défaut true ; false vous laisse l'apparence. Ce dont les glissements ont besoin est injecté dans tous les cas : pas de sélection de texte ni d'ancrage du défilement pendant le glissement (les listes virtuelles en dépendent), le curseur de glissement (--dnd-cursor), et pas de menu de lien lors d'un appui long sur iOS.
Événements
| Événement | Payload | Quand |
|---|---|---|
drag-start | DnDEvent | Un glissement a commencé (après son activation). |
drag-move | DnDEvent | Le pointeur a bougé pendant un glissement (au plus une fois par frame). |
drag-over | DnDEvent | La cible sous le glissement a changé. |
drag-end | DnDEndEvent | Un dépôt a abouti et a été écrit. |
drag-cancel | DnDEvent | Le glissement a été annulé ou le dépôt refusé. |
drag-resume | DnDEvent | onBeforeDrop a répondu 'continue' : il n'y a pas eu de dépôt, et le glissement continue. |
drag-settle | DnDEndEvent ou DnDEvent | L'overlay du glissement a atterri : ce qu'a reçu drag-end ou drag-cancel. |
Les mêmes événements, plus onBeforeDrop, sont disponibles n'importe où sous le
provider avec useDnDMonitor. Leurs payloads sont décrits sur
la page des événements.
Slot #overlay
Rend ce qui suit le pointeur, pour chaque glissement qui n'a pas son propre composant d'overlay (voir le guide de l'overlay). S'il ne rend rien, le glissement se rabat sur le clone.
Ce que montre l'overlay : les props du slot #overlay du provider et des composants d'overlay (option overlay des éléments déplaçables, des items triables, des listes et des arbres).
ActiveLe glissement.
DragItem[]Tous les items glissés, en commençant par l'item principal : un seul overlay pour tout le multi-drag.
Over | nullLa cible de dépôt sous le glissement. Pendant qu'un dépôt décidé s'anime, la cible sur laquelle il atterrit (telle qu'elle était au dépôt) ; null pendant qu'un glissement annulé revient à sa place.
booleanSi over accepte les items glissés ; false au-dessus de rien.
DnDStatus'dragging', puis 'dropping' pendant que l'overlay atterrit (ou revient à sa place).
DragModeCe que ferait un dépôt maintenant (voir DnDEvent.mode) : par exemple afficher un plus pendant une copie.
DropDestination | nullL'endroit où un dépôt mettrait maintenant les items glissés, dans une liste ou un arbre triable : par exemple pour teinter l'overlay selon le dossier dans lequel irait un glissement dans un arbre. En dehors de toute cible, c'est la place de l'emplacement, où dropOutside: 'placeholder' (la valeur par défaut) les garde. null quand le dépôt ne les mettrait dans aucune liste : au-dessus d'une cible de dépôt simple, au-dessus d'une liste qui les refuse, à l'extérieur avec dropOutside: 'cancel' ou 'remove'. Pendant l'animation d'un dépôt décidé, la place où il atterrit.
Clavier
Les glissements au clavier (keyboard du provider) : leurs touches, et le pas des glissements libres.
{ start?: string[]; drop?: string[]; cancel?: string[] }Les touches qui saisissent (start), déposent et annulent, sous forme de KeyboardEvent.code ('Space', 'KeyW') ou de .key ('Enter', 'w'). Par défaut : Espace et Entrée saisissent et déposent, Échap annule. Les flèches déplacent toujours.
numberPixels par appui sur une flèche pour les glissements libres (non triables). 25 par défaut.
Défilement automatique
Comment les conteneurs défilent quand un glissement approche de leurs bords (autoScroll du provider).
numberZone de bord, en fraction de la taille du conteneur. 0.2 par défaut (limitée à 24–96 px).
numberVitesse maximale en px par frame de 16 ms.
numberLa vitesse en px par image quand le pointeur est au bord du conteneur : plus lente dans la zone du bord, plus rapide au-delà du bord, jusqu'à maxSpeed. 10 par défaut.
Vibrations
Quand les glissements tactiles vibrent. Seuls les glissements lancés au toucher vibrent ; là où le navigateur ne peut pas vibrer (Safari sur iOS) ou le bloque (pas encore de tap sur la page), rien ne se passe.
HapticPatternLe glissement commence, après l'appui long. true par défaut.
HapticPatternLe glissement entre dans une cible de dépôt (une liste, une zone) qui l'accepte. false par défaut.
HapticPatternLe dépôt a lieu. false par défaut.
HapticPatternLe dépôt est refusé (par une cible ou par onBeforeDrop) et les items reviennent à leur place. false par défaut.
Une vibration (navigator.vibrate) : sa durée en ms ou un motif marche/arrêt. true correspond à la vibration par défaut (10 ms ; [20, 40, 20] pour refuse), false ou 0 à aucune.
type HapticPattern = boolean | number | number[]Annonces
Les textes pour les lecteurs d'écran, par événement. Renvoyez undefined pour le texte intégré, '' pour aucun texte. context contient les positions qu'énoncent les textes intégrés des listes triables.
Un texte est lu par la région live du provider (les déplacements, une fois que le glissement reste immobile 500 ms) ; undefined laisse l'événement à la source suivante (les textes des intégrations, comme les positions triables, puis ceux par défaut). Aucun déplacement n'est annoncé pour la cible trouvée à la saisie : rien n'a encore bougé.
(event: DnDEvent, context: AnnouncementContext) => string | undefinedUn glissement a commencé.
(event: DnDEvent, context: AnnouncementContext) => string | undefinedLe glissement est passé sur une autre cible, ou à une autre place dans une liste (une fois immobile pendant 500 ms).
(event: DnDEndEvent, context: AnnouncementContext) => string | undefinedLe dépôt a abouti, ou le glissement s'est terminé hors de toute cible.
(event: DnDEvent, context: AnnouncementContext) => string | undefinedLe glissement a été annulé, ou son dépôt refusé.
(event: DnDEvent, context: AnnouncementContext) => string | undefinedonBeforeDrop a répondu 'continue' : le glissement continue.
Ce dont parle une annonce, au-delà de l'événement : pour vos propres textes (une autre langue, d'autres mots) qui disent ce que disent les textes intégrés.
AnnouncedPositionDans une liste ou un arbre triable : où se trouvent les items glissés. Au début, là où ils ont été saisis ; pendant le déplacement, là où ils atterriraient (aucune position en dehors des listes) ; à la fin, là où ils ont atterri, ou là où ils sont revenus.
{ key: Key; label?: string; position: AnnouncedPosition }Un échange : l'item échangé avec l'item glissé, et où il se trouve maintenant.
numberCombien d'items le glissement transporte.
booleanLe glissement copie (group.pull: 'clone', la touche de copie).
Une place dans une liste ou un arbre triable (ses lignes visibles) : index compte à partir de 0, sur un total de length.