Action buttons
The action-buttons column pattern (inline Edit/Delete buttons and a more dropdown, composed over store actions).
The action-buttons column: a pinned-right readOnly column whose renderCell composes plain
shadcn Buttons over store actions. Every button calls an existing store action,
and the column's readOnly: true keeps the grid from ever trying to edit it.
Each row's pinned-right column offers inline Edit / Delete buttons plus a "more" dropdown (Edit, Duplicate, Delete) — all plain store actions.
pnpm dlx shadcn@latest add @gridcn/data-grid-actions-demo
The two patterns
| Pattern | Good for | Trade-off |
|---|---|---|
| Inline buttons (Edit, Delete) | 1–2 actions every row always uses | Takes horizontal space per row |
| "More" dropdown | 3+ actions, or rarely-used ones | One extra click per action |
The demo ships both: two always-visible icon buttons plus a dropdown carrying the same Edit and a Duplicate.
How it's wired
{
id: "actions",
header: "",
pin: "right",
readOnly: true,
width: 110,
renderCell: ({ viewRowIndex }) => <RowActions rowIndex={viewRowIndex} />,
}Inside RowActions (inside the provider):
const actions = useDataGridActions();
// Edit drops the row's first editable cell into edit mode
actions.startEditingAt({ row: rowIndex, col: 0 });
// Duplicate/delete work on view-space indices — the same space renderCell's viewRowIndex is in
actions.duplicateRows([rowIndex]);
actions.deleteRows([rowIndex]);viewRowIndex is the view-index position, exactly what the row-operation actions expect (no
index translation needed). Cell actions like startEditing take a stable CellRef
({ rowId, columnId }) by default; the *At variants take the viewRowIndex/column position
instead. Target the row by identity through rowId (in renderCell's props) whenever the
action needs something beyond its position.
Behavior reference
- Programmatic actions: signatures for
startEditing's siblings - Pinning: the pinned band the column sits in
- Selection & keyboard: what happens to the selection after a delete