Shadcn React Table

Search documentation

Search the docs

Toolbar customization

The table renders a top toolbar (title slot + your actions on the left, an icon-action cluster on the right) and a bottom toolbar (pagination). Every part can be hidden, replaced, or extended.

Showing / hiding the toolbars

tsx
const table = useDataTable({
  data,
  columns,
  getRowId: (row) => row.id,
  enableTopToolbar: false, // remove the entire top toolbar
  enableBottomToolbar: false, // remove the entire bottom toolbar
})
Body onlyNo header or toolbars: a compact list.
GitHub
Ava Thompsonopened a ticket7 min ago
Liam Nguyenclosed a deal14 min ago
Noah Silvajoined21 min ago
Emma Carterleft a comment28 min ago
Olivia Rossiopened a ticket35 min ago
William Walkerclosed a deal42 min ago

Internal actions (the icon cluster)

The right-hand cluster holds global search, the filter toggle, column visibility, the density toggle, and the full-screen toggle. Hide individual items, or the whole cluster:

tsx
useDataTable({
  // per-item
  enableGlobalFilter: false,
  enableColumnFilters: false,
  enableColumnActions: false, // column visibility menu
  enableDensityToggle: false,
  enableFullscreenToggle: false,
  // …or hide all of them at once
  enableToolbarInternalActions: false,
})

Custom actions

Add your own buttons without replacing anything. renderTopToolbarCustomActions fills the top toolbar's left region (next to the title); renderBottomToolbarCustomActions fills the bottom toolbar's left region (next to pagination):

tsx
useDataTable({
  renderTopToolbarCustomActions: ({ table }) => (
    <Button size="sm" onClick={() => table.beginCreate()}>
      Add row
    </Button>
  ),
  renderBottomToolbarCustomActions: ({ table }) => (
    <span className="text-xs text-muted-foreground">
      {table.getSelectedRowModel().rows.length} selected
    </span>
  ),
})

Facet filters

DataTableFacetFilter puts a column filter on the toolbar as a button. It is dashed while nothing is picked and names the pick in a badge once something is. It reads and writes the table's columnFilters by id, so it works the same with or without the header filter row. DataTableResetFilters clears every column filter, and renders nothing while none is set.

tsx
useDataTable({
  renderTopToolbarCustomActions: ({ table }) => (
    <>
      {/* one choice; options come from the column's meta.filterSelectOptions */}
      <DataTableFacetFilter table={table} columnId="role" />
      {/* several choices, with a heading and a count beside each option */}
      <DataTableFacetFilter
        table={table}
        columnId="status"
        multiple
        menuLabel="Show people who are"
        counts={{ active: 12, pending: 4 }}
      />
      <DataTableResetFilters table={table} />
    </>
  ),
})
Toolbar facet filtersSingle- and multi-choice filter buttons on the toolbar, with a reset button.
GitHub
ID
AvaThompsonOwnerEngineeringactive22$45,000Jan 2, 2023
0%
LiamNguyenAdminMarketinginactive25$47,137Jan 13, 2023
9%
NoahSilvaEditorDesignpending28$49,274Jan 24, 2023
18%
EmmaCarterViewerSalesactive31$51,411Feb 4, 2023
27%
OliviaRossiOwnerSupportinactive34$53,548Feb 15, 2023
36%
WilliamWalkerAdminEngineeringpending37$55,685Feb 26, 2023
45%
SophiaPatelEditorMarketingactive40$57,822Mar 9, 2023
54%
JamesMullerViewerDesigninactive43$59,959Mar 20, 2023
63%
IsabellaParkOwnerSalespending46$62,096Mar 31, 2023
72%
LucasReyesAdminSupportactive49$64,233Apr 11, 2023
81%
$4,120,536
Rows per page
1–10 of 48

Pass options to list values the column doesn't define, and title to rename the button. For a filter your page keeps outside the table, pass value and onValueChange; the table's own columnFilters are then left alone. Give DataTableResetFilters the matching active and onReset so it clears that filter too.

Replacing a whole toolbar

For full control, replace the built-in toolbar entirely. The render slot receives the table instance:

tsx
useDataTable({
  renderTopToolbar: ({ table }) => <MyToolbar table={table} />,
  renderBottomToolbar: ({ table }) => <MyFooter table={table} />,
  // or replace just the icon cluster, keeping the title/actions layout:
  renderToolbarInternalActions: ({ table }) => <MyIconButtons table={table} />,
})

Pagination placement

positionPagination controls where the pagination controls render. "none" keeps pagination active (the data is still paged) but hides the controls.

tsx
useDataTable({
  positionPagination: "both", // "top" | "bottom" | "both" | "none"
})

Search placement

positionGlobalFilter moves the global search to the left region (next to the title/actions) or keeps it in the right-hand icon cluster. "none" hides it (same as enableGlobalFilter: false).

tsx
useDataTable({
  positionGlobalFilter: "left", // "left" | "right" | "none"
})

Alert banner & drop zone

The row-selection alert banner and the group-by drop zone default to the top. Reposition or hide them independently:

tsx
useDataTable({
  positionToolbarAlertBanner: "bottom", // "top" | "bottom" | "head-overlay" | "none"
  positionToolbarDropZone: "both", // "top" | "bottom" | "both" | "none"
})

Styling

Every toolbar slot exposes a data-slot attribute, so you can target it with a Tailwind selector instead of a styling prop — no per-slot props needed:

SlotDescription
data-table-toolbarTop toolbar root.
data-table-toolbar-actionsInternal actions cluster (search, filters, density, full screen, …).
data-table-alert-bannerSelection alert banner (`data-position="head-overlay"` when it lies over the header row).
data-table-bottom-toolbarBottom toolbar (custom actions and/or pagination).
data-table-paginationPagination controls.
data-table-facet-filterTrigger button of a `DataTableFacetFilter` (dashed border while nothing is picked).
data-table-reset-filtersThe `DataTableResetFilters` button (rendered only while a column filter is set).
tsx
<DataTable table={table} className="[&_[data-slot=data-table-toolbar]]:px-2" />