Drag & Drop
Sortable and reorderable interactions for lists, cards, and simple boards.
Overview
Drag & Drop provides accessible sortable/reorderable UI for dashboards and task lists. It is not a file-upload drop zone — use file-upload for that.
The implementation wraps @dnd-kit for pointer, touch, and keyboard sensors, sortable strategies, and live region announcements. Prefer DragDropHandle so nested buttons, links, and inputs stay interactive.
Keyboard: focus the handle, press Space/Enter to pick up, use arrow keys to move, Space/Enter to drop, Escape to cancel. Install with vinyaas add drag-and-drop or via vinyaas add --catalog dashboard.
Preview
Customize
Installation
Add the component with the CLI. It copies the files in and installs anything they depend on.
npx vinyaas add drag-and-dropUsage
import { useState } from "react";
import {
DragDrop,
DragDropHandle,
DragDropItem,
DragDropList,
} from "@/components/ui/drag-and-drop";
export function TaskList() {
const [items, setItems] = useState(["Task A", "Task B", "Task C", "Task D"]);
return (
<DragDrop items={items} onReorder={setItems}>
<DragDropList>
{items.map((item) => (
<DragDropItem key={item} id={item} className="flex items-center gap-2 p-2">
<DragDropHandle aria-label={`Reorder ${item}`} />
<span>{item}</span>
</DragDropItem>
))}
</DragDropList>
</DragDrop>
);
}Examples
Basic sortable list
Reorder items with a drag handle. Not a file-upload drop zone.
Drag handle and disabled items
Handles stay keyboard-focusable. Disabled items cannot start a drag.
Whole-item drag
Omit DragDropHandle to make the entire row the drag activator.
Inbox triage
Drag anywhere on the row — no separate handle.
Design review
Drag anywhere on the row — no separate handle.
Ship checklist
Drag anywhere on the row — no separate handle.
Horizontal chips
Use orientation="horizontal" for pill or chip reorder rows.
Priority queue
Numbered ranks update as items move — useful for triage and backlogs.
Attachment order
Reorder files before upload or submit. Pair with file-upload for picking files.
brief.pdf
Attachment order
moodboard.png
Attachment order
spec.docx
Attachment order
recording.mp4
Attachment order
Playlist / queue
Compose a bordered shell around DragDropList for media queues.
Episode queue
Drag to change playback order.
Multiple containers
Move items between Todo and Done lists with a shared root.
Todo
Done
In practice
A Kanban-style sprint board: three columns, card composition with Badge and Button, and size-stable drag overlays across containers.
Sprint board
Multi-container DragDrop — cards keep their size while dragging.
Backlog
Wire Stripe webhooks and receipt emails.
Collapsed labels + rounded demo shells.
Align chart colors with primary.
In progress
Verify catalog installs before write.
Keyboard, focus, and reduced motion.
Done
Ship v1.3.0 changelog bullets.
API
Other attributes for the underlying element are passed through.
| Name | Type | Default | Description |
|---|---|---|---|
items / onReorder | UniqueIdentifier[] | Record<string, UniqueIdentifier[]> | — | DragDrop: controlled item order. Use an array for one list, or a record of arrays for multiple containers. |
id | string | — | DragDrop: stable id for accessibility markup. Defaults to React useId() so server and client match. |
orientation | "vertical" | "horizontal" | "vertical" | DragDrop: sorting axis and drop indicator direction. |
disabledIds | UniqueIdentifier[] | — | DragDrop: item ids that cannot be dragged. |
id / items | string / UniqueIdentifier[] | — | DragDropList: container id and that container’s ids (required for multiple containers). |
id / disabled | UniqueIdentifier / boolean | — | DragDropItem: sortable identity and optional disabled state. |
aria-label | string | "Reorder" | DragDropHandle: accessible name for the activator control. |
Accessibility
Drag handles are native buttons with accessible names. @dnd-kit provides sortable keyboard interaction and live-region announcements for drag start, over, end, and cancel.
- Tab reaches the handle. Space/Enter picks up; arrows move; Escape cancels.
- Focus-visible rings use
--ringtokens on the handle. - Drop targets show an insertion indicator line in addition to item movement.
- Disabled items expose
disabledhandles anddata-disabledon the item. - Touch activation uses a short delay so page scroll remains usable.
- Item transitions respect
prefers-reduced-motion. - Multiple containers accept
itemsas a record of id arrays (Kanban-style boards). The drag overlay snapshots the active item and locks its width/height so cards do not shrink while dragging. Keep application state in the parent — this component does not persist order.