Drag & Drop

Featurednd-kit

Accessible drag and drop with dnd-kit — sortable lists, kanban boards, and custom drag interactions.

Read this when adding drag and drop features.
Useful for kanban boards, sortable lists, or reorderable items.

Why dnd-kit

dnd-kit is built for modern React with accessibility first. It uses hooks and context, supports keyboard navigation, and works with screen readers out of the box.

The modular architecture means you only import what you need. It handles sortable lists, drag between containers, and custom collision detection — all with excellent performance.

Key Features

What dnd-kit provides:

Sortable

Reorder items. Vertical, horizontal, or grid layouts with smooth animations.

Multi-Container

Drag between lists. Move items between columns, like kanban boards.

Accessible

Keyboard & screen reader. Full keyboard navigation and ARIA announcements.

Catalyst Integration

Catalyst wraps dnd-kit in reusable components:

components/vendor/dnd-kit/

Sortable components ready to use

app/(examples)/examples/kanban/

Kanban board example with drag and drop

Quick Start

Basic sortable list

"use client"
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
} from "@dnd-kit/core"
import {
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable"
import { useState } from "react"

export function SortableList() {
  const [items, setItems] = useState(["Item 1", "Item 2", "Item 3"])

  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  )

  function handleDragEnd(event) {
    const { active, over } = event
    if (active.id !== over?.id) {
      setItems((items) => {
        const oldIndex = items.indexOf(active.id)
        const newIndex = items.indexOf(over.id)
        return arrayMove(items, oldIndex, newIndex)
      })
    }
  }

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <SortableContext items={items} strategy={verticalListSortingStrategy}>
        {items.map((item) => (
          <SortableItem key={item} id={item} />
        ))}
      </SortableContext>
    </DndContext>
  )
}

Sortable item component

import { useSortable } from "@dnd-kit/sortable"
import { CSS } from "@dnd-kit/utilities"

function SortableItem({ id }) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
  }

  return (
    <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
      <GripIcon className="h-4 w-4 cursor-grab" />
      {id}
    </div>
  )
}

Using Catalyst Wrappers

Catalyst provides pre-built sortable components:

import { Sortable, SortableItem } from "@/components/vendor/dnd-kit"

export function TaskList() {
  const [tasks, setTasks] = useState([
    { id: "1", title: "Task 1" },
    { id: "2", title: "Task 2" },
  ])

  return (
    <Sortable
      items={tasks}
      onReorder={setTasks}
      renderItem={(task) => (
        <SortableItem id={task.id}>
          {task.title}
        </SortableItem>
      )}
    />
  )
}

Check components/vendor/dnd-kit/ for available wrappers and their props.

Tips

Items need unique IDs. dnd-kit tracks items by ID — make sure each item has a unique identifier.

Add keyboard sensor. Include KeyboardSensor for accessibility — users can reorder with arrow keys.

Use CSS.Transform for smooth animations. The utilities package provides transform helpers.

Handle drag end, not drag move. Update state in onDragEnd to avoid performance issues.

Learn More

For AI Agents

Key rules:

  • Check components/vendor/dnd-kit/ for existing wrappers first
  • Items must have unique ID props
  • Include both PointerSensor and KeyboardSensor for accessibility
  • Use arrayMove from @dnd-kit/sortable for reordering
  • See /examples/kanban for multi-container example