Kanban Board
Note
@nofinite/kanban is a standalone package powered by Atlassian Pragmatic Drag-and-Drop, featuring WIP limits, column reordering, search filtering, and imperative handles. Visit the dedicated Kanban Documentation Hub for the complete guide.
An accessible, responsive drag-and-drop workflow board powered by @atlaskit/pragmatic-drag-and-drop. Supports reorderable columns, draggable task cards, member avatars, priority status badges, and custom drag events.
tsx
import { Kanban } from '@nofinite/kanban/react';Interactive Preview
Loading preview...
Key Features
- Smooth Drag-and-Drop: Fluid physics powered by Pragmatic DnD with clear drop targets and drag elevation shadows.
- Card Metadata: Native support for tags, assignees, dates, and priority indicators (
low,medium,high,urgent). - Flexible Column Config: Customize titles, column actions, card limits, and add-card buttons.
- Accessible Interactions: Keyboard support for moving cards between columns with arrow keys.
- Mobile Friendly: Horizontal scroll containers with responsive touch-friendly cards.
Usage
Basic Usage
tsx
import React, { useState } from 'react';
import { Kanban } from '@nofinite/kanban/react';
export default function MyBoard() {
const [columns, setColumns] = useState([
{
id: 'backlog',
title: 'Backlog',
items: [
{ id: '1', content: <div className="p-2.5 bg-surface border border-default rounded shadow-xs text-sm font-medium">Research OAuth 2.1 specs</div> },
{ id: '2', content: <div className="p-2.5 bg-surface border border-default rounded shadow-xs text-sm font-medium">Prepare Q3 roadmap</div> }
]
},
{
id: 'in-progress',
title: 'In Progress',
items: [
{ id: '3', content: <div className="p-2.5 bg-surface border border-default rounded shadow-xs text-sm font-medium">Develop DataGrid virtual scrolling</div> }
]
},
{
id: 'completed',
title: 'Completed',
items: [
{ id: '4', content: <div className="p-2.5 bg-surface border border-default rounded shadow-xs text-sm font-medium">Update Nuicss theme tokens</div> }
]
}
]);
return (
<Kanban
columns={columns}
onChange={setColumns}
/>
);
}Best Practices
Do
- Provide unique string identifiers for every column and card (
id). - Persist state changes via the
onCardMovecallback to keep your remote backend synchronized. - Keep card titles concise and move lengthy notes into card descriptions or popovers.
Don't
- Avoid placing dense nested clickable inputs inside cards that interfere with drag event listeners.
- Do not overload a single column with thousands of un-paginated cards; consider archiving completed tasks.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
columns* | KanbanColumnProps[] | — | — |
onChange | ((columns: KanbanColumnProps[]) => void) | — | — |
onCardMove | ((event: CardMoveEvent) => void) | — | — |
onColumnMove | ((event: ColumnMoveEvent) => void) | — | — |
onCardAdd | ((columnId: string) => void) | — | — |
onCardClick | ((cardId: string, columnId: string, item: KanbanItem) => void) | — | — |
onColumnOptions | ((columnId: string) => void) | — | — |
onColumnAdd | (() => void) | — | — |
onColumnClear | ((columnId: string) => void) | — | — |
allowAdd | boolean | true | — |
allowAddColumn | boolean | false | — |
addColumnLabel | string | + Add Column | — |
headerActions | boolean | true | — |
enforceWipLimit | boolean | false | — |
canMoveCard | ((event: CardMoveEvent) => boolean) | — | — |
columnClassName | string | — | — |
renderCard | ((item: KanbanItem, columnId: string) => ReactNode) | — | — |
renderHeader | ((column: KanbanColumnProps) => ReactNode) | — | — |