Data display
List
The workhorse task view — rows grouped into collapsible sections, with subtasks, sortable and re-orderable columns, drag-to-reorder, inline rename and a quick-add on every group. Drag a row to another group to re-assign it; drag a column header to rearrange.
npx shadcn@latest add @orbit/listOverview
Live — drag a row to reorder or drop it on another group, click a column header to sort or drag it to rearrange, click a task name to rename, expand a subtask, or use + Add task.
Everything is direct
No dialogs, no edit modes — the list edits in place. Drag, click, type; each change commits immediately and the groups recount.
Regroup and compress
Group by any field — status, priority or assignee — switch to a compact row height, or hide the quick-add. Drag still re-assigns by whatever the grouping is. Each instance is live.
Column config
columns selects and orders the meta columns (assignee · priority · progress · due); quickAdd={false} drops the add row for read-heavy views. Column order stays draggable either way.
Controlled
Pass items + onItemsChange to own the tree — every reorder, nest, regroup, rename, toggle and quick-add reports the full updated structure, ready to persist. onItemClick fires when a row's background is clicked.
onItemsChange fired 0 times · 8 top-level tasks · click a row background to fire onItemClick
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| items / defaultItems | ListItem[] | — | Controlled / uncontrolled task tree: { id, name, status?, done?, assignee?, priority?, due?, progress?, children? }. Subtasks are one level deep. |
| onItemsChange | (items: ListItem[]) => void | — | Fires with the full updated tree on reorder, nest, denest, regroup, rename, checkbox toggle, cell edit and quick-add. |
| people | ListPerson[] | [] | Assignable directory: { id, name, color? }. Drives avatars, the assignee column and assignee grouping. |
| groupBy / defaultGroupBy | "none" | "status" | "priority" | "assignee" | "status" | Controlled / uncontrolled grouping; the toolbar menu switches it. Also settable via onGroupByChange. |
| columns / defaultColumns | ListColumnKey[] | ["assignee", "priority", "progress", "due"] | Meta-column set and order. Header drag reorders; onColumnsChange reports the new order. |
| density | "comfortable" | "compact" | "comfortable" | Row height 40px or 34px (group headers and quick-add compress to match). |
| quickAdd | boolean | true | Show the “+ Add task” row at the end of every group. |
| onItemClick | (item: ListItem) => void | — | A row's background was clicked (controls inside stop propagation). |
| defaultExpandedIds | string[] | — | Parent ids whose subtasks start expanded. |
| …rest | HTMLAttributes | — | Forwarded to the root <div>, including ref. |
Usage
Group by the field you triage on
If the team works status-first, group by status so dragging a row down the list moves it through the workflow.
Carry a dozen columns
A list is for scanning. Keep three or four meta columns; push the rest into the row's detail Drawer.
Let sort and manual coexist
Manual drag order is the default; a column sort overrides it for a look, and the next drag returns to manual.
Nest more than one level
Subtasks are one level deep on purpose. For arbitrary hierarchy reach for the Tree instead.
Keyboard & accessibility
Checkboxes, disclosure chevrons, sortable headers, editable cells and task names are real focusable controls with the 3px themed focus ring — Enter activates each (rename, sort, popover). Escape closes an edit, quick-add or popover; the cell popovers and group-by menu build on Base UI for focus and dismiss handling.