Skip to content

Components

Sortable list and board

Reordering without a drag library: the pointer uses the platform's own drag protocol and the keyboard uses pick up, move, drop, narrated through a polite live region.

Examples

import { KanbanBoard, SortableList } from "@luc/ui";

Sortable list

The order on the left is the array read back on the right: `onReorder` receives the complete order rather than a delta, so a caller never has to replay the move itself.

  • Ingest04:00 · 1,284 bars
  • Analytics04:12 · seven domains
  • Materialize04:24 · serving generation
  • Research pass05:02 · RP01
  • Notify05:10 · Lark

Current order

ingest → analytics → materialize → research → notify

Drag the handle with a pointer, or press Space to pick up, the arrow keys to move, Space to drop and Escape to cancel.

Kanban board

A board is a two-axis sortable: Up/Down reorders inside a column and Left/Right carries the card into the neighbouring column at the same depth.

Backlog

  • Volatility surface 3DProjected surface, no GPUcharts
  • Chord diagramMatrix → arcscharts

Doing

  • Bilingual bodiesLong-form copyshowcase

Done

  • Spatial design languagetokens

Public API

Both components are controlled: they report the intent and the application decides how the model changes.

Component props
PropTypeDefaultNotes
SortableList.itemsSortableItem[]—List items: an id, a label and optional description and disabled.
SortableList.onReorder(ids: string[]) => void—The complete id order after the move.
KanbanBoard.columnsKanbanColumn[]—Columns and cards; each column has an id, a title and its cards.
KanbanBoard.onMove({ cardId, from, to, index }) => void—One move's intent: the card id, the source column, the destination column and the destination index.

Dragging uses only native browser events, the keyboard uses `aria-pressed` plus a live announcement, and neither needs an extra dependency.

Usage

import { KanbanBoard } from "@luc/ui";
<KanbanBoard
  columns={columns}
  onMove={({ cardId, from, to, index }) => move(cardId, from, to, index)}
  label="Sprint"
/>

Guidelines

Do

  • Keep the move in the caller: `onMove` reports the card, the source column, the target column and the index, and the board re-renders from the new columns.
  • Use `disabled` for a read-only plan rather than rendering a second static layout.

Don't

  • Use a board for an ordered list with two states; a `SortableList` or a `DataTable` is the smaller instrument.

Accessibility

Each column keeps its title as a heading inside a named group, and every card is a focusable control, so a reader can reach a card and its column without a pointer.

Luc UI v1.0KanbanBoarddark theme