Diamond Diamond

ui · 6 variants · 1 categories

Kanban

Drag-and-drop column board with hover-active focus, WIP limits, animated checkboxes, quick-move buttons, and inline add / edit / remove.

npx "@rueda.dev/gems-diamond" add kanban
§01

Display

6 variants
To do2
In progress1
Done1
classic
Backlog1
Active1
Shipped1
active
In review2
Approved1
two-col
Today0/2
This week1/2
Later0/1
tasks
Inbox1
Doing1
Review1
Done1
compact
Inbox0/3
— empty —
Today2/3
Due in 2h
Later0/5
— empty —
priority

Usage Guide

How to wire up this component in your app — props, callbacks, customization, and the conventions Diamond shares across the library.

State management

Hybrid controlled/uncontrolled. Pass defaultColumns for a self-managed board, or columns + onColumnsChange when you want to persist to a backend.

const [columns, setColumns] = useState<KanbanColumn[]>(initial);

<Kanban
  variant="classic"
  columns={columns}
  onColumnsChange={(next) => {
    setColumns(next);
    fetch("/api/board", { method: "PUT", body: JSON.stringify(next) });
  }}
/>

Built-in interactions

  • HTML5 native drag-and-drop between and within columns. Drop on a card inserts before it; drop on empty zone goes to the end.
  • Inline + Add card at the bottom of each column. Disable with allowAdd=false.
  • Click a card title to edit inline (Enter saves, Escape cancels). Hover shows an X to remove. Disable with allowEdit=false.
  • Drag disabled per-variant: two-col uses quick-move buttons instead.

Variant behaviors

PropTypeDescription
classic / compactGeneric DnD board. Compact = denser visuals, 4 columns.
activeHighlights the first non-empty column statically. Override per column with `column.active=true`.
two-colDnD off; each card has ← Back / Next → buttons in the footer. First column's Next renders as 'Finish'.
tasksAnimated checkbox + per-column 'n/N' progress bar. Toggle done with the checkbox.
priorityPer-column WIP `limit`. Badge turns yellow at limit, red over. Drop past limit shakes and blocks. Cards can have `urgent` (pulsing border) and `due` (badge).

Card shape

interface KanbanCard {
  id: React.Key;
  title: React.ReactNode;
  description?: React.ReactNode;
  color?: string;         // left-border accent
  done?: boolean;         // tasks variant
  urgent?: boolean;       // priority variant
  due?: ReactNode;        // priority variant
  leading?: ReactNode;    // custom left slot
  trailing?: ReactNode;   // custom right slot
}

Universal patterns

Every Diamond component shares the same prop conventions, so once you learn one you can predict the others.

  • variant — discriminated union of every visual option. Categories shown above are docs-only metadata; the prop is a flat string union.
  • accent — any CSS color string. Overrides --diamond-accent just for that instance via inline style. Cascades into hover, ring, and selection states.
  • asChild (when present) — renders the underlying primitive via @radix-ui/react-slot, letting you compose with <Link>, motion.button, etc.
  • className — merged with internal Tailwind classes via cn(). Use it to override layout, spacing, or colors.
  • Native HTML attributes (onClick, aria-*, data-*, ref, etc.) flow through to the root element without any whitelist.
  • Diamond is the skin: zero domain state, zero fetch, zero providers. You wire data and reactions in your app code; the components just render and emit events.