TaskDnd

dnd-kit wiring for task drag sources and drop targets. Drop policy and move effects stay consumer-owned.

Preview#

import {
  TaskBoardColumn,
  TaskBoardRoot,
  TaskCard,
  TaskDndProvider,
  TaskDragOverlay,
  TaskDraggable,
  TaskDropPlaceholder,
  TaskDropZone,
} from "raft-ui";

<TaskDndProvider isDropAllowed={() => true} onMove={() => {}}>
  <TaskBoardRoot>
    <TaskBoardColumn render={<TaskDropZone id="task-status:todo" data={{ status: "todo" }} />}>
      <TaskDropPlaceholder id="task-1" placement="before" />
      <TaskDraggable
        id="task-1"
        dropId="task-1"
        dropData={{ status: "todo", taskId: "task-1" }}
      >
        <TaskCard />
      </TaskDraggable>
      <TaskDropPlaceholder id="task-1" placement="after" />
    </TaskBoardColumn>
  </TaskBoardRoot>
  <TaskDragOverlay>
    <TaskCard />
  </TaskDragOverlay>
</TaskDndProvider>

Allowed and blocked drops#

The demo composition passes blockedDropStatus="closed", which the board turns into an isDropAllowed policy. Drag a card onto Closed to see blocked empty-state copy; other columns accept the drop and call onMove.

API#WIP

PropTypeDefaultDescription
disabledbooleanfalseDisables pointer, touch, and keyboard drag sensors.
isDropAllowed(activeId, overId, overData) => booleanConsumer policy for whether a drop target is allowed.
onMove(details: TaskMoveDetails) => void | Promise<void>Called when a drag ends over an allowed target.
onMoveError(error, details) => voidCalled when onMove rejects.
onDragStart(event: DragStartEvent) => voidOptional hook fired when a drag starts.
onDragOver(event: DragOverEvent) => voidOptional hook fired when a draggable moves over another droppable.
onDragCancel(event: DragCancelEvent) => voidOptional hook fired when a drag is cancelled.
onDragEnd(event: DragEndEvent) => voidOptional hook fired when a drag ends.
childrenReactNodeBoard or list content that participates in drag and drop.
PropTypeDefaultDescription
idUniqueIdentifierStable drag source id.
disabledbooleanfalseDisables dragging for this item.
dropIdUniqueIdentifierOptional card-level drop target id for before/after insertion.
dropDataTaskDropDataConsumer metadata returned from onMove for the card-level target.
...propsComponentPropsWithRef<"div">Draggable host. Usually wraps a TaskCard.
PropTypeDefaultDescription
idUniqueIdentifierStable drop target id.
disabledbooleanfalseDisables this drop target.
dataTaskDropDataConsumer metadata returned from onMove for this target.
...propsuseRender.ComponentProps<"div", { dropState: TaskDropState }>Droppable host. Exposes dropState idle | allowed | blocked via render state.
PropTypeDefaultDescription
idUniqueIdentifierThe matching drop target id. Renders an allowed landing placeholder at the active card height.
placement"before" | "after"Optional insertion edge for a card-level target.
...propsuseRender.ComponentProps<"div", { dropState: TaskDropState }>A presentational landing slot; it is hidden unless the matching target allows the active task.
PropTypeDefaultDescription
childrenReactNodeConsumer-rendered drag preview. Render null when no item is active.