Skip to content

BoardView

<BoardView> is the kanban primitive — columns = values of a single status attribute, cards = items grouped by that attribute. Drag-and-drop between columns; optional shift-click multi-select.

import from "@na/ui/components/BoardView" ▶ Open in Storybook packages/ui/src/components/BoardView.tsx

When to use

  • Pipelines where stage progression is the primary action — deals, tickets, leads.
  • Cases where the user moves things across a small set of states (3–6 columns).

Don’t use BoardView for: every list (DataTable is denser when scanning), free-form drag-drop (Resizable is wrong; build feature-local), or single-state collections.

Default

Discovery2
Acme
$12,000
Globex
$8,000
Negotiation1
Initech
$42,000
Closed-won1
Soylent
$24,000
<BoardView<Deal>
items={deals}
columns={[
{ id: 'discovery', label: 'Discovery' },
{ id: 'negotiation', label: 'Negotiation' },
{ id: 'won', label: 'Closed-won' },
]}
groupBy={(d) => d.stage}
renderCard={(d, state) => (
<Card data-selected={state.selected}>
<CardHeader>
<CardTitle>{d.name}</CardTitle>
<CardDescription>${d.amount.toLocaleString()}</CardDescription>
</CardHeader>
</Card>
)}
onMove={(itemId, toCol, fromCol) => api.moveDeal(itemId, toCol)}
/>

API

Prop Type Default Description
items * T[] All cards. Must extend { id }.
columns * BoardColumn[] Ordered columns. Each: { id, label, description?, isDropDisabled? }.
groupBy * (item: T) => string Extract the column id for each item — typically (item) => item.status.
renderCard * (item: T, state: BoardCardState) => ReactNode Card renderer. State has { selected, dragging }.
onMove (itemId, toColumnId, fromColumnId) => void Caller persists the move; component re-renders from updated items.
selection Set<string> Controlled multi-select. Omit to disable multi-select.
onSelectionChange (next: Set<string>) => void Fires on selection change.
renderColumnActions (column, count) => ReactNode Right-aligned per-column-header actions.
renderColumnEmpty (column) => ReactNode Rendered inside a column with zero items.

Design guidelines

✓ Do

  • Cap columns at 5–6. More turns the board into a horizontal scroller.
  • Set isDropDisabled on terminal columns the user can't move backward into (e.g. Closed-Won → Lead).
  • Show the count in renderColumnActions — users plan from "12 in Discovery" before opening any card.

✗ Don't

  • Use BoardView when the data has more than one status attribute the user needs to see. That's a DataTable.
  • Stuff cards with 10+ properties. Show 3–5; the rest belongs on the detail page.
  • Render BoardView in a fixed-width container too narrow for all columns — horizontal scroll is OK but signal it.

Accessibility

  • Drag and drop is a real event; alternative keyboard moves (TBD per implementation) — screen-reader users should be able to reach the underlying property edit on the detail page.
  • Cards are role="article"; columns are role="region" with aria-label.

▶ Open BoardView stories in Storybook