Customizing toolbar and controls
Use this guide when the default toolbar structure is close to right, but the control mix still needs to match your product.
The toolbar is already a composed surface. Most customization starts by deciding which built-in controls belong there before you replace any deeper UI.
Show a realistic toolbar with quick search and filters on the left, views plus display controls on the right, and one product-specific action called out as a source-level extension.
1. Start by choosing whether the toolbar exists at all
The toolbar can be disabled entirely or enabled with defaults.
<Datatable
tableKey="customers"
data={customers}
columns={columns}
toolbar={false}
/><Datatable
tableKey="customers"
data={customers}
columns={columns}
toolbar={true}
/>Use false only when the table is intentionally minimal or the surrounding screen already provides the same controls elsewhere.
2. Turn individual built-in controls on and off from toolbar
Most real customization starts with the object form.
<Datatable
tableKey="customers"
data={customers}
columns={columns}
toolbar={{
quickSearch: {
placeholder: "Search customers...",
debounceMs: 300,
},
filterButton: true,
displayOptions: true,
copyLink: false,
views: true,
appliedState: {
showFilters: true,
showSorting: true,
},
}}
/>This decides whether the toolbar shows:
- quick search
- the filter button
- the display-options button
- the copy-link button
- the saved-views dropdown
- the applied sorting and filter chip bar below the toolbar
3. Treat the toolbar and applied-state bar as one workflow
The toolbar is where users change table state. The applied-state bar is where they see and clear that state.
That means toolbar customization should usually include a decision about appliedState too.
toolbar={{
filterButton: true,
appliedState: {
showFilters: true,
showSorting: false,
},
}}A common healthy pattern is:
- keep filter chips visible when filtering matters
- hide sorting chips only when sorting is mostly a quiet default
- avoid removing both the entry point and the visible feedback for the same control
4. Some toolbar controls depend on top-level features
A toolbar button exposes a feature entry point, while the feature's deeper behavior lives in its own configuration and state model.
Two important examples:
toolbar.views: trueonly shows the views dropdown if the top-levelviewsadapter config also existstoolbar.displayOptions: trueonly shows the button; the top-leveldisplayOptionsprop still decides what appears inside the popover
<Datatable
tableKey="customers"
data={customers}
columns={columns}
toolbar={{
views: true,
displayOptions: true,
}}
views={{
adapter: trpcViewAdapter,
workspaceId: workspace.id,
}}
displayOptions={{
sections: {
grouping: false,
columnVisibility: true,
displaySettings: true,
},
}}
/>The toolbar controls the entry point. The top-level feature config controls the behavior behind it.
5. Tune quick search and filters to match the table's real job
The toolbar source places quick search and the filter button on the left because they are the primary query controls.
Keep that logic intact unless the workflow truly differs.
Good uses:
- quick search for fast broad lookup
- filter button for field-specific narrowing
- applied chips for visible active state
Less healthy uses:
- hiding query controls while expecting users to understand active filtering
- adding too many top-level controls until search and filters stop feeling primary
If query behavior needs work, customize the underlying guides first instead of treating the toolbar as a cosmetic shell.
6. Use views, display options, and copy link as secondary controls
The shipped toolbar keeps these controls on the right as secondary table-management actions:
- Views for named working states
- Display options for presentation controls
- Copy link for sharing the current URL state
That separation is useful because it keeps querying distinct from layout and sharing.
If a product hides one of these controls, do it because the workflow truly does not need it, not because the button cluster feels visually busy.
7. Expect the toolbar to wrap on narrow widths
The copied source already changes layout on smaller containers.
In narrow mode it becomes a multi-row surface:
- quick search plus filter button
- views on the left and display/copy controls on the right
- the Match all/Match any toggle when active filters require it
That means toolbar customization should be judged in both wide and narrow layouts.
A control mix that looks fine on desktop can become cramped or confusing once it wraps.
8. Use viewColumnsButton when visibility changes belong near the grid
Not every control has to live in the toolbar.
viewColumnsButton adds the pinned + affordance near the table grid for fast column visibility changes.
<Datatable
tableKey="customers"
data={customers}
columns={columns}
toolbar={{
displayOptions: true,
}}
viewColumnsButton={{
show: true,
width: 32,
}}
/>Use this when users frequently toggle visible columns while actively scanning rows, not only from the top toolbar.
9. The current limit: there is no public arbitrary toolbar slot
The copied DataTableToolbar source has an internal children slot, while the public Datatable API shown in props.types.ts keeps toolbar composition fixed.
That means you can safely customize the shipped toolbar surface through:
- feature toggles
- quick-search config
- applied-state visibility
- top-level views and display-options configuration
- the separate
viewColumnsButton
If you need product-specific buttons, extra segmented controls, or a different toolbar composition, you are beyond public configuration and into source-level customization.
10. Verify the toolbar in context before shipping
Before you call the toolbar done, check that:
- primary query controls still feel primary
- applied chips stay visible when users need feedback
- views and display options only appear when their backing config exists
- the control mix still works after the layout wraps on narrow widths
- column-visibility controls live in the most natural place for the workflow
- extra product actions only enter the toolbar when prop-level customization is truly insufficient
Where to go next
- For the surface this control cluster belongs to, read Table anatomy.
- For search behavior inside the toolbar, read Add global search.
- For the display-options popover behind one of these controls, read Configure display options.
- For the broader decision of whether a change belongs in props or source, read Customization overview.