Kanban
Columns of cards, movable between them. Drag-and-drop is pointer-only, so every card also moves with the arrow keys — a board you can only drag excludes keyboard users from its main action.
src/components/ui/kanban.tsxAbout
From the component's own source, where it was written.
Columns of cards, movable between them.
Uses the HTML drag-and-drop API rather than pointer maths. It is the API that gives a native drag image and works with the OS conventions, and reaching for a pointer-based library is how a board ends up unusable on touch.
Because drag-and-drop is pointer-only, every card also carries a keyboard path: focus it and use the arrow keys to move it between columns. A board where the only way to move work is dragging excludes anyone using a keyboard, and that is the majority of the actions on a board people use daily.
The board never reorders anything itself — onMove reports the intent and the caller owns the data. Optimistically moving a card and then having the server reject it is worse than a moment of latency.
Install
npx astralyx-ui add kanban
Usage
import { Kanban } from '@/components/ui/kanban'
<Kanban columns={columns} onMove={move} />Composer
Change the props and the source below follows.
To do
2Extract the copy button
choreRange slider ARIA review
In progress
1 / 3Menubar roving focus
a11y
Done
1Drawer drag dismissal
<Kanban columns={columns} onMove={move} />Examples
Board
<Kanban columns={columns} onMove={move} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
Kanban
Extends Omit<ComponentProps<'div'>, 'onDrop'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| columns | KanbanColumn[] | required | { id, title, cards, limit? } where a card is { id, title, meta?, accent? }. |
| onMove | (cardId: string, fromColumn: string, toColumn: string) => void | — | The board never reorders anything itself — moving optimistically and having the server reject it is worse than a moment of latency. |
| renderCard | (card: KanbanCard, column: KanbanColumn) => ReactNode | — | Replace the card body while keeping the drag behaviour. |
| emptyLabel | ReactNode | 'Nothing here' | Shown in an empty column. |
Types
KanbanCard
Columns of cards, movable between them.
| Field | Type | Description |
|---|---|---|
| id | string | — |
| title | ReactNode | — |
| meta? | ReactNode | — |
| accent? | string | — |
KanbanColumn
| Field | Type | Description |
|---|---|---|
| id | string | — |
| title | string | — |
| cards | KanbanCard[] | — |
| limit? | number | — |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| keyboard | ← → | Moves a focused card between columns. |