Kanban widgetPro
A small board for tasks made in the conversation, moved by drag, by one press, or entirely from the keyboard.
On this page
Installation
Usage
import { KanbanWidget } from "@/components/ui/chatcn/pro/kanban-widget"
<KanbanWidget
title="Corvo Serif launch"
columns={[
{ id: "todo", title: "To do" },
{ id: "doing", title: "Doing", limit: 3 },
{ id: "done", title: "Done" },
]}
tasks={tasks}
onTasksChange={(next, move) => save(next, move)}
onAdd={(column, title) => ({ id: newId(), title, column })}
/>Tasks carry their column and keep their array order inside it. onTasksChange gets the whole list and, for moves, { id, from, to, index }, so a tool can sync one change instead of the board. Tasks with isNew (made by the chat a moment ago) carry a small accent mark until they move.
Three ways to move a task: drag it (a short long press starts the drag on touch, so the thread still scrolls), press its round mark to move it one column on, or focus it and press Space, steer with the arrow keys and press Space again; Escape puts it back. The last column reads as done, with a green check and muted titles.
Columns with a limit show count/limit and turn amber over it, with the reason for screen readers. Due dates are your words in due, tinted amber for soon and red for late. Below about 26 rem the columns stack, and drag still works across them. Render it inside the card your host draws for a widget answer. It fills the width it is given, so a comfortable max width (around 28 rem) comes from the card, and it follows the host theme through the kit tokens. Pass onExpand where the host can go full screen.
Examples
States
Props
| Prop | Type | Notes |
|---|---|---|
title | ReactNode | |
columns | { id, title, limit? }[] | The last column reads as done |
tasks, defaultTasks | { id, title, column, assignee?, due?, dueTone?, isNew? }[] | Order within a column follows the array |
onTasksChange | (tasks, move?) => void | Every change, with the move when there is one |
onAdd | (column, title) => KanbanTask | undefined | Shows Add task per column |
status | "ready" | "loading" | "error" | Default ready |
onRetry, onExpand | () => void | |
disabled | boolean | Read only |
labels | Partial<…Labels> | Every string the widget writes, for translation |
Labels
labels covers the task count (tasks(total, done)), the limit note, the advance button (advance(title, to)), empty and add copy, every keyboard announcement (pickedUp, movedTo, dropped, cancelled) and the instructions read with each card.
Keyboard
| Key | Action |
|---|---|
| Tab | Into the board, one card at a time |
| Arrow keys | Move focus between cards and columns |
| Space or Enter | Pick the focused task up, or drop it |
| Arrow keys while holding | Move the task between columns, or up and down |
| Escape while holding | Put the task back where it was |
Accessibility
- Each column is a labelled region; each card is a focusable list item named with its title, assignee, due date and new mark, and described by the move instructions.
- Every keyboard move is announced with the column and position. Arrow keys follow the reading direction in RTL.
- The advance mark is a labelled button with a 32 px hit area (44 px on touch).
- Due dates and limits carry words, never color alone.
Motion
A dragged card lifts with a shadow and a slight tilt and follows the pointer with no easing. Keyboard moves do not animate. Nothing else moves.