Raft 设计系统

组件 · 任务

TaskDnd

The drag-and-drop parts that let people move task cards between columns and around other cards, with the drop policy and the move left to the caller.

稳定也叫 Drag and drop, DnD, TaskDraggable, TaskDropZone
import { TaskDnd } from "@botiverse/raft-ui";
本页尚未翻译
译文完成之前,这里显示英文原文。 阅读英文版

TaskDnd is the drag-and-drop wiring behind the TaskBoard: a provider, the cards people drag, the places they drop them, the gap a card lands in and the copy of the card that follows the pointer. It decides nothing about tasks. The caller says which drops are allowed and what a move does, such as changing #25 from Todo to In Review.

task-dnd/compositions/task-dnd

When to use

SituationUse
Moving a card to another column of a board to change its statusTaskDnd, inside a TaskBoard
Reordering a card among the cards of a columnTaskDnd, with a drop target on each card
Changing a status without draggingThe status chip on the card, or the property in the task's details (Tasks)
Reordering composer attachmentsThe composer's own sortable attachments (Composer)
Resizing a columnResizable

Anatomy

  • TaskDndProvider: wraps the board and its overlay. It holds isDropAllowed, the caller's policy, calls onMove when a card is dropped on an allowed target, and passes accessibility to dnd-kit. Required.
  • TaskDropZone: a place a card can be dropped, usually a TaskBoardColumn through render. It reports dropState: idle, allowed or blocked.
  • TaskDraggable: wraps one TaskCard and makes it draggable. With dropId it is also a drop target, so a card can land before or after it.
  • TaskDropPlaceholder: the gap where the card would land, before or after a card, or in an empty column. It shows only while the drop there is allowed.
  • TaskDragOverlay: the copy of the card that follows the pointer. Render the dragged card inside it, and nothing when no card is dragged.

States

StateLook
DraggingThe copy in TaskDragOverlay is the only card with shadow-float (TaskCard)
Over an allowed targetTaskDropPlaceholder shows a dashed line-strong box with the height of the dragged card
Over a blocked targetNo placeholder; the target's dropState is blocked, and an empty column says why (TaskBoard)
Dragging turned offdisabled on the provider removes every way to drag; disabled on a TaskDraggable removes it for that card

Behavior

  • With a mouse, a drag starts once the pointer has moved 5px, so a click on the card isn't a drag.
  • On a touch screen, hold the card still for 500ms, then move it: the drag starts on that move. Moving before the hold is up scrolls the board instead (Dragging on a touch screen).
  • Where the card lands follows the middle of the dragged card: above the middle of the card under it is before, below is after.
  • The card doesn't animate back or into place on drop. The move is the caller's: onMove may return a promise, and onMoveError receives its rejection, so the caller can undo the change and say what went wrong.

Accessibility

  • The parts wrap dnd-kit, not Base UI. TaskDraggable carries dnd-kit's attributes: it is focusable, with a role description and instructions for screen readers.
  • Keyboard: Tab to a card, then Space picks it up. ArrowDown and ArrowUp move it one slot down or up its column, before or after each card; ArrowLeft and ArrowRight move it to the nearest drop target in the next column, such as an empty column or the card level with it. Space drops it and Escape cancels. The keys step between drop targets, so a card moves the same way whether or not it leaves its column while it is dragged.
  • After a keyboard drop, focus stays where dnd-kit leaves it. Moving focus to the moved card, which has a new place in the DOM, is the caller's job: focus it in onMove or onDragEnd once the board has rendered the move.
  • dnd-kit's own announcements name cards and targets by their ID. Pass accessibility to TaskDndProvider to replace them: it goes to dnd-kit's DndContext as is, with announcements (what to say on pick-up, move, drop and cancel) and screenReaderInstructions (how to drag, read with each card). Write them in words, such as "Task #25 moved to In Review", or announce each move in a polite live region of your own; the TaskBoard composition shows how.
  • TaskDropPlaceholder is hidden from assistive technology.

Rules

  • Decide in isDropAllowed which drops are allowed, so the target says while the card is over it that it can't move there (TaskBoard).
  • Offer another way to change a status: dragging is one of three (Tasks).
  • Put the dragged card's own TaskCard in TaskDragOverlay, so the card under the pointer reads the same as the one in the column.

API

TaskDndProvider

Prop类型默认值
accessibility{ announcements?: Announcements; container?: Element; restoreFocus?: boolean; screenReaderInstructions?: ScreenReaderInstructions; }
children (required)ReactNode
disabledbooleanfalse
isDropAllowed(activeId: UniqueIdentifier, overId: UniqueIdentifier, overData: TaskDropData | undefined) => booleanallowTaskDrop
onDragCancel(event: DragCancelEvent) => void
onDragEnd(event: DragEndEvent) => void
onDragMove(event: DragMoveEvent) => void
onDragOver(event: DragOverEvent) => void
onDragStart(event: DragStartEvent) => void
onMove(details: TaskMoveDetails) => void | Promise<void>
onMoveError(error: unknown, details: TaskMoveDetails) => void

TaskDragOverlay

Prop类型默认值
childrenReactNode

TaskDraggable

Prop类型默认值
disabledbooleanfalse
dropDataTaskDropData
dropDisabledbooleanfalse
dropIdUniqueIdentifier

Also takes the attributes of its element.

TaskDropPlaceholder

Prop类型默认值
placementTaskDropPlacement
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component.ReactElement | ((props, state) => ReactElement)

Also takes the attributes of its element.

TaskDropZone

Prop类型默认值
dataTaskDropData
disabledbooleanfalse
renderAllows you to replace the component's HTML element with a different tag, or compose it with another component.ReactElement | ((props, state) => ReactElement)

Also takes the attributes of its element.

改动

  • 0.8.1 · AddedTaskDndProvider takes accessibility (the TaskDndAccessibility type), passed through to dnd-kit, so you can translate the screen-reader announcements and drag instructions.
  • 0.8.1 · FixedKeyboard dragging in TaskDndProvider moves a card between drop targets. Before, Space picked the card up but the arrow keys never moved it.