apps/docs/extend/plugins/accessibility.mdx
The Accessibility plugin provides screen reader support for drag and drop operations. It automatically manages ARIA attributes on draggable elements, provides screen reader instructions, and announces drag events via a live region.
This plugin is included by default when creating a new DragDropManager.
Use Accessibility.configure() to customize announcements, screen reader instructions, and other options:
const manager = new DragDropManager({
plugins: (defaults) => [
...defaults,
Accessibility.configure({
announcements: {
dragstart({operation: {source}}) {
if (!source) return;
return Started dragging ${source.id};
},
dragover({operation: {source, target}}) {
if (!source || !target) return;
return ${source.id} is over ${target.id};
},
dragend({operation: {source, target}, canceled}) {
if (!source) return;
if (canceled) return Dragging canceled;
return Dropped ${source.id} on ${target?.id ?? 'nothing'};
},
},
}),
],
});
```tsx React
import {DragDropProvider} from '@dnd-kit/react';
import {Accessibility} from '@dnd-kit/dom';
function App() {
return (
<DragDropProvider
plugins={(defaults) => [
...defaults,
Accessibility.configure({
announcements: {
dragstart({operation: {source}}) {
if (!source) return;
return `Started dragging ${source.id}`;
},
dragover({operation: {source, target}}) {
if (!source || !target) return;
return `${source.id} is over ${target.id}`;
},
dragend({operation: {source, target}, canceled}) {
if (!source) return;
if (canceled) return `Dragging canceled`;
return `Dropped ${source.id} on ${target?.id ?? 'nothing'}`;
},
},
}),
]}
>
</DragDropProvider>
);
}
<script setup>
import {DragDropProvider} from '@dnd-kit/vue';
import {Accessibility} from '@dnd-kit/dom';
const plugins = (defaults) => [
...defaults,
Accessibility.configure({
announcements: {
dragstart({operation: {source}}) {
if (!source) return;
return `Started dragging ${source.id}`;
},
dragover({operation: {source, target}}) {
if (!source || !target) return;
return `${source.id} is over ${target.id}`;
},
dragend({operation: {source, target}, canceled}) {
if (!source) return;
if (canceled) return `Dragging canceled`;
return `Dropped ${source.id} on ${target?.id ?? 'nothing'}`;
},
},
}),
];
</script>
<template>
<DragDropProvider :plugins="plugins">
<!-- ... -->
</DragDropProvider>
</template>
<script>
import {DragDropProvider} from '@dnd-kit/svelte';
import {Accessibility} from '@dnd-kit/dom';
const plugins = (defaults) => [
...defaults,
Accessibility.configure({
announcements: {
dragstart({operation: {source}}) {
if (!source) return;
return `Started dragging ${source.id}`;
},
dragover({operation: {source, target}}) {
if (!source || !target) return;
return `${source.id} is over ${target.id}`;
},
dragend({operation: {source, target}, canceled}) {
if (!source) return;
if (canceled) return `Dragging canceled`;
return `Dropped ${source.id} on ${target?.id ?? 'nothing'}`;
},
},
}),
];
</script>
<DragDropProvider {plugins}>
<!-- ... -->
</DragDropProvider>
import {DragDropProvider} from '@dnd-kit/solid';
import {Accessibility} from '@dnd-kit/dom';
function App() {
return (
<DragDropProvider
plugins={(defaults) => [
...defaults,
Accessibility.configure({
announcements: {
dragstart({operation: {source}}) {
if (!source) return;
return `Started dragging ${source.id}`;
},
dragover({operation: {source, target}}) {
if (!source || !target) return;
return `${source.id} is over ${target.id}`;
},
dragend({operation: {source, target}, canceled}) {
if (!source) return;
if (canceled) return `Dragging canceled`;
return `Dropped ${source.id} on ${target?.id ?? 'nothing'}`;
},
},
}),
]}
>
</DragDropProvider>
);
}
The plugin automatically sets the following attributes on draggable activator elements (the handle or, if no handle is set, the draggable element itself):
role="button" — unless the element is already a <button> or has an explicit rolearia-roledescription="draggable"aria-describedby — points to a hidden element containing screen reader instructionsaria-pressed and aria-grabbed — reflect the current dragging statearia-disabled — reflects the disabled state of the draggabletabindex="0" — ensures the element is focusable (added when the element is not natively focusable)The plugin ships with default announcements for the dragstart, dragover, and dragend events:
"Picked up draggable item {id}.""Draggable item {id} was moved over droppable target {targetId}.""Draggable item {id} is no longer over a droppable target.""Draggable item {id} was dropped over droppable target {targetId}""Dragging was cancelled. Draggable item {id} was dropped.""Draggable item {id} was dropped."The default instructions read:
To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item in a given direction. Press space again to drop the item in its new position, or press escape to cancel.
interface Announcements {
dragstart: (event, manager) => string | undefined;
dragmove?: (event, manager) => string | undefined;
dragover?: (event, manager) => string | undefined;
dragend: (event, manager) => string | undefined;
}
interface ScreenReaderInstructions {
draggable: string;
}
Defaults to {description: 'dnd-kit-description', announcement: 'dnd-kit-announcement'}.
</ParamField>