Skip to content
Design System
Contact

Kanban

Drag cards between columns with pointer, touch or keyboard.

Components@dnd-kit

Playground

Drag with a mouse, with the grip on touch screens, or from the keyboard: focus a card, press Space, move with the arrow keys and press Space again. The strip under the board shows what a screen reader announces.

Preview
Demo data

Backlog

4
  1. Migrate billing webhooks

    Globex

    IntegrationOct 2LF
  2. Audit onboarding emails

    Northwind

    CRMOct 6MC
  3. Rate limit alerts

    Globex

    AutomationOct 9MC
  4. Draft Q4 roadmap

    Acme Corporation

    DesignPR

In progress

3/3
  1. Contract renewal flow

    Acme Corporation

    Waiting on legal review

    SaaSLF
  2. SSO for Initech

    Initech

    Priya Raman is editing

    EnterpriseMC
  3. Dashboard empty states

    Hooli

    DashboardSep 30PR

Review

0
  1. No cards yet. Drag one here or add one below.

Done

2
  1. Export to CSV

    Northwind

    DashboardPR
  2. Invoice PDF redesign

    Hooli

    DesignLF

Props

WIP limit on In progress
example.tsxtsx
1import { Kanban } from "@/components/ui/kanban"
2
3// DndContext + SortableContext per column, closestCorners,
4// PointerSensor (6px) and KeyboardSensor (sortableKeyboardCoordinates)
5<Kanban
6 columns={["Backlog", "In progress", "Review", "Done"]}
7 cards={cards}
8 wipLimits={{ "In progress": 3 }}
9 onMove={(cardId, { to, index }) => moveCard(cardId, to, index)}
10 onAddCard={(column, title) => createCard(column, title)}
11/>

Card states

Locked cards can't be dragged and say who holds them; blocked cards say why. Cards in Done carry a check.

States
  • Migrate billing webhooks

    Globex

    IntegrationOct 2LF
    Defaultrest
  • Migrate billing webhooks

    Globex

    IntegrationOct 2LF
    Hover:hover
  • Migrate billing webhooks

    Globex

    IntegrationOct 2LF
    Focus:focus-visible
  • Migrate billing webhooks

    Globex

    IntegrationOct 2LF
    Loadingdragging (DragOverlay)
  • SSO for Initech

    Initech

    Priya Raman is editing

    EnterpriseMC
    Disabledlocked, aria-disabled
  • Contract renewal flow

    Acme Corporation

    Waiting on legal review

    SaaSLF
    Errorblocked
  • Export to CSV

    Northwind

    DashboardPR
    Successdone

Examples

The same sensors with a single SortableContext: reorder a backlog by priority, locked to the vertical axis.

Priority list
Demo data
  1. 1Rate limit alerts
  2. 2Migrate billing webhooks
  3. 3Draft Q4 roadmap
  4. 4Audit onboarding emails

API

PropTypeDefaultDescription
columnsstring[] | { id: string; title: string }[]—Column order. Each column is a droppable, so empty columns still accept cards.
cardsRecord<string, Card[]>—Cards per column. Card has id, title, company, tags, assignee, due, locked and blocked.
onMove(id: string, to: { column: string; index: number }) => void—Called once on drop with the final position. Previews during the drag are local.
wipLimitsRecord<string, number>—Soft work-in-progress limits. Over the limit, the column turns amber and the drop is still allowed.
onAddCard(column: string, title: string) => void—Inline Add card at the bottom of each column. Enter adds, Escape cancels.
showAvatarsbooleantrueAssignee avatar on each card.
showTagsbooleantrueTags on each card.
compactbooleanfalseHides the company line, tightens padding and narrows the columns.

Accessibility

Keyboard

Focus the next card
Tab
Pick up or drop the focused card
SpaceorEnter
Move within a column
↑or↓
Move to the neighbouring column
←or→
Cancel and put the card back
Esc

Semantics and ARIA

  • Cards get role="button", aria-roledescription="sortable" and a description with the keyboard instructions from dnd-kit.
  • Custom announcements name the card, the column and the position, for example Dropped Rate limit alerts in Review, position 1 of 1, and mention an exceeded WIP limit.
  • Escape and drops outside the board restore the snapshot taken when the drag started, and say where the card went back to.
  • Locked cards stay focusable with aria-disabled and a reason, so the lock is discoverable instead of silently ignored.
  • Pointer drags start after 6px so clicks and scrolling still work; on touch, drag from the grip and swipe elsewhere to scroll the board.
  • The board scrolls sideways inside its own region on narrow screens; the page itself never scrolls horizontally.