Row actions
Provide renderRowActions to add a trailing actions column. It receives { row, table } and returns whatever controls you need — for example a delete button.
Usage
const table = useDataTable({
data,
columns,
getRowId: (row) => row.id,
renderRowActions: ({ row }) => (
<Button
variant="ghost"
size="icon"
onClick={() =>
setData((prev) => prev.filter((r) => r.id !== row.original.id))
}
>
<RiDeleteBinLine />
<span className="sr-only">Delete</span>
</Button>
),
})
return <DataTable table={table} />
Combine with editing
Row actions sit alongside editing controls — wire up an edit button here to start row editing programmatically.
As a menu
For a compact kebab menu instead of inline buttons, use renderRowActionMenuItems. It returns the menu items (e.g. DropdownMenuItems) rendered inside an auto-injected dropdown in the actions column. Both slots can be combined — inline controls plus a menu.
While editing is on ("row" or "modal" display), the Edit action moves into this menu: it arrives as internalMenuItems. The callback also gets closeMenu().
import { DropdownMenuItem } from "@/components/ui/dropdown-menu"
const table = useDataTable({
data,
columns,
getRowId: (row) => row.id,
enableEditing: true,
editDisplayMode: "modal",
renderRowActionMenuItems: ({ row, internalMenuItems }) => (
<>
{internalMenuItems}
<DropdownMenuItem variant="destructive" onClick={() => remove(row.id)}>
Delete
</DropdownMenuItem>
</>
),
})
Positioning the column
The actions column trails the data columns by default. Set positionActionsColumn: "first" to move it to the leading edge.
useDataTable({
renderRowActions: ({ row }) => <RowMenu row={row} />,
positionActionsColumn: "first", // "first" | "last"
})