Kanban Board
A generic multi-column stage board. Designed for recruiter pipelines, project workflows, and any process with discrete stages — with column accents, gate notes, and per-column card overflow.
Basic board
Pass columns, cards, getCardColumnId, and a renderCard function. Cards are distributed into the matching column automatically.
Alice Chen
Eng II
Bob Okafor
Senior Eng
Carol Rivera
Eng I
Dave Kim
Staff Eng
Eve Patel
Eng II
With column accents and notes
Supply an accent color on any column def to draw a thin colored bar below the header. A note renders a gate description beneath the accent bar.
Alice Chen
Eng II
Bob Okafor
Senior Eng
Schedule via Calendly
Carol Rivera
Eng I
Dave Kim
Staff Eng
Comp approval required
Eve Patel
Eng II
Overflow cap
Set cardCap to limit visible cards per column. Cards beyond the cap are hidden behind a +N more button; wire up onShowMore to open a drawer or expand the column.
Alice Chen
Eng II
Bob Okafor
Senior Eng
Frank Wu
Eng II
Carol Rivera
Eng I
Dave Kim
Staff Eng
Eve Patel
Eng II
Installation
pnpm add @refraction-ui/reactUsage
import { KanbanBoard, KanbanCard } from '@refraction-ui/react'
import type { KanbanColumnDef } from '@refraction-ui/react'
const stages: KanbanColumnDef[] = [
{ id: 'applied', title: 'Applied', accent: '#6366f1' },
{ id: 'screen', title: 'Phone Screen', note: 'Schedule via Calendly' },
{ id: 'offer', title: 'Offer', accent: '#22c55e' },
]
const candidates = [
{ id: '1', name: 'Alice Chen', stageId: 'applied' },
{ id: '2', name: 'Bob Okafor', stageId: 'screen' },
{ id: '3', name: 'Carol Rivera', stageId: 'offer' },
]
export function Pipeline() {
return (
<KanbanBoard
columns={stages}
cards={candidates}
getCardColumnId={(c) => c.stageId}
getCardKey={(c) => c.id}
renderCard={(c) => (
<KanbanCard clickable>
<p className="font-medium">{c.name}</p>
</KanbanCard>
)}
cardCap={5}
/>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
columns | KanbanColumnDef[] | -- | Column definitions in left-to-right render order. Each def has `id`, `title`, optional `accent` color, and optional `note`. |
cards | T[] | -- | All cards to distribute across columns. |
getCardColumnId | (card: T) => string | -- | Selector returning the column id for a card. |
getCardKey | (card: T) => string | -- | Selector returning a unique React key for a card. |
renderCard | (card: T, column: KanbanColumnDef) => ReactNode | -- | Render function for a single card inside a column. |
cardCap | number | 5 | Maximum visible cards per column. Cards beyond the cap are hidden behind a "+N more" button. |
onCardClick | (card: T) => void | -- | Optional click handler — pass to renderCard as needed. |
columnHeader | (def: KanbanColumnDef, count: number) => ReactNode | -- | Override the default column header (icon + title + count badge). |
onShowMore | (columnId: string) => void | -- | Called when the user clicks "+N more" for a column. |
className | string | -- | Additional CSS classes for the board container. |