Skip to content

Dynamic Columns

Add, rename, move, delete, reorder, and retype columns at runtime.

Columns become runtime state. useGridColumns owns the list; <DataGridColumns> wires the header menu and add button. New columns render empty cells: no engine changes required.

Open in
Feature
Owner
Status
Preview with Controlled State
Open in
Feature
Owner
Status
Current Grid State
Live view of the grid engine state for demonstration
Focused Cell:None
Editing Cell:None
Selection Anchor:None
Total Rows:3
Column Count:3
Column Ids:feature, owner, status
Can Undo / Redo:No / No
Last Commit:None
pnpm dlx shadcn@latest add @niko-table/data-table-grid @niko-table/data-table-view-dnd-menu
const cols = useGridColumns({
initialColumns: [
{ id: "task", label: "Task", type: "text" },
{ id: "status", label: "Status", type: "select", options: ["Todo", "Done"] },
],
})
const grid = useDataGrid({ columnIds: cols.columnIds, createEmptyRow })

Header menu:

<DataTableColumnActions>
<DataTableColumnHideOptions />
<GridColumnMenuOptions />
</DataTableColumnActions>

Provider + toolbar:

<DataGrid grid={grid}>
<DataGridColumns value={cols}>
<DataGridToolbar>
<DataGridAddColumnButton />
<DataTableViewDndMenu
columnOrder={cols.columnIds}
onColumnOrderChange={cols.reorderColumns}
/>
</DataGridToolbar>
{/* table… */}
</DataGridColumns>
</DataGrid>

API: columns, columnIds, addColumn, renameColumn, moveColumn, removeColumn, reorderColumns, setColumnType.

<DataGridColumns
value={cols}
columnTypes={[
{ value: "text", label: "Text" },
{ value: "select", label: "Select", options: STATUSES },
]}
resolveCell={resolveCell}
>

Existing cells re-resolve against the new type (unmatched values turn invalid).