MRT logoMaterial React Table

    Toolbar Customization Guide

    This guide shows you how to hide, customize, or override the top and bottom toolbars in Material React Table.

    Relevant Props

    1
    boolean
    true
    MRT Customize Toolbars Docs
    2
    boolean
    true
    3
    boolean
    true
    4
    ToolbarProps | ({ table }) => ToolbarProps
    Material UI Toolbar Props
    5
    LinearProgressProps | ({ isTopToolbar, table }) => LinearProgressProps
    Material UI LinearProgress Props
    6
    ChipProps| ({ table }} => ChipProps
    Material UI Chip Props
    7
    AlertProps | ({ table }) => AlertProps
    Material UI Alert Props
    8
    ToolbarProps | ({ table }) => ToolbarProps
    Material UI Toolbar Props
    9
    'left' | 'right'
    10
    'bottom' | 'top' | 'both'
    11
    'bottom' | 'top' | 'none'
    12
    'bottom' | 'top' | 'both' | 'none'
    13
    ReactNode | ({ table }) => ReactNode
    14
    ({ table }) => ReactNode
    15
    ({ table}) => ReactNode
    16
    ReactNode | ({ table }) => ReactNode
    17
    ({ table }) => ReactNode

    Relevant State

    1
    boolean
    false
    2
    boolean
    false

    Hide or Disable Toolbars

    There are enableTopToolbar and enableBottomToolbar props that you can use to show or hide the toolbars.

    <MaterialReactTable
    data={data}
    columns={columns}
    enableTopToolbar={false} //hide top toolbar
    enableBottomToolbar={false} //hide bottom toolbar
    />

    No Toolbars Example


    Demo

    Open StackblitzOpen Code SandboxOpen on GitHub
    DylanMurray261 Erdman FordEast DaphneKentucky
    RaquelKohler769 Dominic GroveColumbusOhio
    ErvinReinger566 Brakus InletSouth LindaWest Virginia
    BrittanyMcCullough722 Emie StreamLincolnNebraska
    BransonFrami32188 Larkin TurnpikeCharlestonSouth Carolina

    Source Code

    1import React, { FC, useMemo } from 'react';
    2import MaterialReactTable, { MRT_ColumnDef } from 'material-react-table';
    3import { data, Person } from './makeData';
    4
    5export const Example: FC = () => {
    6 const columns = useMemo<MRT_ColumnDef<Person>[]>(
    7 //column definitions...
    32 );
    33
    34 return (
    35 <MaterialReactTable
    36 columns={columns}
    37 data={data}
    38 enableColumnActions={false}
    39 enableColumnFilters={false}
    40 enablePagination={false}
    41 enableSorting={false}
    42 enableBottomToolbar={false}
    43 enableTopToolbar={false}
    44 muiTableBodyRowProps={{ hover: false }}
    45 />
    46 );
    47};
    48
    49export default Example;
    50

    Customize Toolbar buttons

    Everything in the toolbars is customizable. You can add your own buttons or change the order of the built-in buttons.

    Customize Built-In Internal Toolbar Button Area

    The renderToolbarInternalActions prop allows you to redefine the built-in buttons that usually reside in the top right of the top toolbar. You can reorder the icon buttons or even insert your own custom buttons. All of the built-in buttons are available to be imported from 'material-react-table'.

    import MaterialReactTable, {
    MRT_ShowHideColumnsButton,
    MRT_FullScreenToggleButton,
    } from 'material-react-table';
    //...
    return (
    <MaterialReactTable
    data={data}
    columns={columns}
    renderToolbarInternalActions={({ table }) => (
    <>
    {/* add your own custom print button or something */}
    <IconButton onClick={() => showPrintPreview(true)}>
    <PrintIcon />
    </IconButton>
    {/* built-in buttons (must pass in table prop for them to work!) */}
    <MRT_ShowHideColumnsButton table={table} />
    <MRT_FullScreenToggleButton table={table} />
    </>
    )}
    />
    );

    Add Custom Toolbar Buttons/Components

    The renderTopToolbarCustomActions and renderBottomToolbarCustomActions props allow you to add your own custom buttons or components to the top and bottom toolbar areas. These props are functions that return a ReactNode. You can add your own buttons or whatever components you want.

    In all of these render... props, you get access to the underlying table instance that you can use to perform actions or extract data from the table.

    <MaterialReactTable
    data={data}
    columns={columns}
    enableRowSelection
    //Simply adding a table title to the top-left of the top toolbar
    renderTopToolbarCustomActions={() => (
    <Typography variant="h3">Customer's Table</Typography>
    )}
    //Adding a custom button to the bottom toolbar
    renderBottomToolbarCustomActions={({ table }) => (
    <Button
    variant="contained"
    color="primary"
    //extract all selected rows from the table instance and do something with them
    onClick={() => handleDownloadRows(table.getSelectedRowModel().rows)}
    >
    Download Selected Rows
    </Button>
    )}
    />

    Full Custom Top Toolbar Example


    HomerSimpson3953000
    MargeSimpson3860000
    BartSimpson1046000
    LisaSimpson8120883
    MaggieSimpson122

    Rows per page

    1-5 of 5

    Source Code

    1import React, { FC, useMemo } from 'react';
    2import MaterialReactTable, {
    3 MRT_ColumnDef,
    4 MRT_ToggleDensePaddingButton,
    5 MRT_FullScreenToggleButton,
    6} from 'material-react-table';
    7import { Box, Button, IconButton } from '@mui/material';
    8import PrintIcon from '@mui/icons-material/Print';
    9import { data, Person } from './makeData';
    10
    11const Example: FC = () => {
    12 const columns = useMemo<MRT_ColumnDef<Person>[]>(
    13 //column definitions...
    34 );
    35
    36 return (
    37 <MaterialReactTable
    38 columns={columns}
    39 data={data}
    40 enableRowSelection
    41 positionToolbarAlertBanner="bottom" //show selected rows count on bottom toolbar
    42 //add custom action buttons to top-left of top toolbar
    43 renderTopToolbarCustomActions={({ table }) => (
    44 <Box sx={{ display: 'flex', gap: '1rem', p: '4px' }}>
    45 <Button
    46 color="secondary"
    47 onClick={() => {
    48 alert('Create New Account');
    49 }}
    50 variant="contained"
    51 >
    52 Create Account
    53 </Button>
    54 <Button
    55 color="error"
    56 disabled={!table.getIsSomeRowsSelected()}
    57 onClick={() => {
    58 alert('Delete Selected Accounts');
    59 }}
    60 variant="contained"
    61 >
    62 Delete Selected Accounts
    63 </Button>
    64 </Box>
    65 )}
    66 //customize built-in buttons in the top-right of top toolbar
    67 renderToolbarInternalActions={({ table }) => (
    68 <Box>
    69 {/* add custom button to print table */}
    70 <IconButton
    71 onClick={() => {
    72 window.print();
    73 }}
    74 >
    75 <PrintIcon />
    76 </IconButton>
    77 {/* along-side built-in buttons in whatever order you want them */}
    78 <MRT_ToggleDensePaddingButton table={table} />
    79 <MRT_FullScreenToggleButton table={table} />
    80 </Box>
    81 )}
    82 />
    83 );
    84};
    85
    86export default Example;
    87

    Position Toolbar Areas

    The positionToolbarAlertBanner, positionGlobalFilter, positionPagination, and positionToolbarDropZone props allow you to swap the default position of certain areas of the toolbars. Experiment moving them around until you find a layout that works for you.

    <MaterialReactTable
    data={data}
    columns={columns}
    //if rendering top toolbar buttons, sometimes you want alerts to be at the bottom
    positionToolbarAlertBanner="bottom"
    positionGlobalFilter="left" //move the search box to the left of the top toolbar
    positionPagination="top"
    renderTopToolbarCustomActions={() => <Box>...</Box>}
    />

    Customize Toolbar Props and Styles

    The muiTopToolbarProps, muiBottomToolbarProps, muiToolbarAlertBannerProps, and muiToolbarAlertBannerChipProps props allow you to customize the props and styles of the underlying MUI components that make up the toolbar components. Remember that you can pass CSS overrides to their sx or style props. Some have found this useful for forcing position: absolute on alerts, etc.

    Customize Linear Progress Bars

    The progress bars that display in both the top and bottom toolbars become visible when either the isLoading or showProgressBars state options are set to true. You can customize the progress bars by passing in props to the muiLinearProgressProps prop. By default, the progress bars have an indeterminate state, but you can set the value prop to a number between 0 and 100 to show real progress values if your table is doing some complicated long running tasks that you want to show progress for. Visit the MUI Linear Progress docs to learn more.

    <MaterialReactTable
    data={data}
    columns={columns}
    muiLinearProgressProps={({ isTopToolbar }) => ({
    color: 'secondary',
    sx: { display: isTopToolbar ? 'block' : 'none' }, //only show top toolbar progress bar
    value: fetchProgress, //show precise real progress value if you so desire
    variant: 'determinate',
    })}
    state={{
    isLoading,
    showProgressBars,
    }}
    />

    Customize Toolbar Alert Banner

    The toolbar alert banner is an internal component used to display alerts to the user. By default, it will automatically show messages around the number of selected rows or grouping state.

    However, you can repurpose this alert banner to show your own custom messages too. You can force the alert banner to show by setting the showAlertBanner state option to true. You can then customize the messages and other stylings using the muiToolbarAlertBannerProps to create your custom message. You probably saw this in the Remote Data or React Query examples.

    <MaterialReactTable
    columns={columns}
    data={data}
    //show a custom error message if there was an error fetching data in the top toolbar
    muiToolbarAlertBannerProps={
    isError
    ? {
    color: 'error',
    children: 'Network Error. Could not fetch data.',
    }
    : undefined
    }
    state={{
    showAlertBanner: isError,
    showProgressBars: isFetching,
    }}
    />

    Override with Custom Toolbar Components

    If you want to completely override the default toolbar components, you can do so by passing in your own custom components to the renderTopToolbar and renderBottomToolbar props.

    The drawback to this approach is that you will not get all the automatic features of the default toolbar components, such as the automatic alert banner, progress bars, etc. You will have to implement all of that yourself if you still want those features.

    <MaterialReactTable
    columns={columns}
    data={data}
    renderTopToolbar={({ table }) => <Box></Box>}
    renderBottomToolbar={({ table }) => <Box></Box>}
    />

    Import MRT Components for Custom Toolbars

    If you are using a custom toolbar, you can still import some of the built-in MRT components to use in your custom toolbar. For example, you can import all of the built-in internal toolbar icon buttons components and use them in your custom toolbar.

    import MaterialReactTable, {
    MRT_ShowHideColumnsButton, // import the built-in show/hide columns button
    MRT_FullScreenToggleButton, // import the built-in full screen toggle button
    } from 'material-react-table';
    //...
    return (
    <MaterialReactTable
    columns={columns}
    data={data}
    renderTopToolbar={({ table }) => (
    <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
    <Typography>Custom Toolbar</Typography>
    <Box>
    <MRT_ShowHideColumnsButton table={table} />
    <MRT_FullScreenToggleButton table={table} />
    </Box>
    </Box>
    )}
    />
    );

    Create Your Own External Toolbar Component

    You may want to separate out your own toolbar functionality away from the main table component. MRT lets you do this and still connect your custom components to the table instance using the tableInstanceRef prop.

    You can import import the MRT Internal Toolbar button components and use them in your custom toolbar, just like you can when customizing the built-in toolbar, BUT there are some extra re-render hacks that you hve to do to make the icon buttons work properly. See the example below:

    Passing the tableInstanceRef as a prop for the table prop that MRT_* components need also requires some weird re-render hacks to make the icon buttons work properly, because refs do not trigger re-renders in React.


    Hey I'm some page content. I'm just one of your normal components between your custom toolbar and the MRT Table below

    HomerSimpson3953000
    MargeSimpson386000
    BartSimpson10460
    LisaSimpson8120883
    MaggieSimpson122

    Source Code

    1import React, { FC, useReducer, useRef, useState } from 'react';
    2import MaterialReactTable, {
    3 DensityState,
    4 MRT_ColumnDef,
    5 MRT_FullScreenToggleButton,
    6 MRT_GlobalFilterTextField,
    7 MRT_ShowHideColumnsButton,
    8 MRT_TableInstance,
    9 MRT_TablePagination,
    10 MRT_ToggleDensePaddingButton,
    11 MRT_ToggleFiltersButton,
    12 MRT_ToolbarAlertBanner,
    13} from 'material-react-table';
    14import type {
    15 PaginationState,
    16 RowSelectionState,
    17 VisibilityState,
    18} from '@tanstack/react-table';
    19import {
    20 alpha,
    21 Box,
    22 Button,
    23 IconButton,
    24 Toolbar,
    25 Tooltip,
    26 Typography,
    27} from '@mui/material';
    28import PrintIcon from '@mui/icons-material/Print';
    29import { data, Person } from './makeData';
    30
    31//column definitions...
    51
    52const Example: FC = () => {
    53 //we need a table instance ref to pass as a prop to the MRT Toolbar buttons
    54 const tableInstanceRef = useRef<MRT_TableInstance<Person>>(null);
    55
    56 //we will also need some weird re-render hacks to force the MRT_ components to re-render since ref changes don't trigger a re-render
    57 const rerender = useReducer(() => ({}), {})[1];
    58
    59 //we need to manage the state that should trigger the MRT_ components in our custom toolbar to re-render
    60 const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
    61 const [density, setDensity] = useState<DensityState>('comfortable');
    62 const [pagination, setPagination] = useState<PaginationState>({
    63 pageIndex: 0,
    64 pageSize: 5,
    65 });
    66 const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
    67 const [showColumnFilters, setShowColumnFilters] = useState(false);
    68
    69 return (
    70 <Box sx={{ border: 'gray 2px dashed', p: '1rem' }}>
    71 {/* Our Custom External Top Toolbar */}
    72 {tableInstanceRef.current && (
    73 <Toolbar
    74 sx={(theme) => ({
    75 backgroundColor: alpha(theme.palette.secondary.light, 0.2),
    76 borderRadius: '4px',
    77 display: 'flex',
    78 flexDirection: {
    79 xs: 'column',
    80 lg: 'row',
    81 },
    82 gap: '1rem',
    83 justifyContent: 'space-between',
    84 p: '1.5rem 0',
    85 })}
    86 >
    87 <Box>
    88 <Button
    89 color="primary"
    90 onClick={() => {
    91 alert('Add User');
    92 }}
    93 variant="contained"
    94 >
    95 Crete New Account
    96 </Button>
    97 </Box>
    98 <MRT_GlobalFilterTextField table={tableInstanceRef.current} />
    99 <Box>
    100 <MRT_ToggleFiltersButton table={tableInstanceRef.current} />
    101 <MRT_ShowHideColumnsButton table={tableInstanceRef.current} />
    102 <MRT_ToggleDensePaddingButton table={tableInstanceRef.current} />
    103 <Tooltip arrow title="Print">
    104 <IconButton onClick={() => window.print()}>
    105 <PrintIcon />
    106 </IconButton>
    107 </Tooltip>
    108 <MRT_FullScreenToggleButton table={tableInstanceRef.current} />
    109 </Box>
    110 </Toolbar>
    111 )}
    112 <Typography padding="1rem 4px">
    113 {
    114 "Hey I'm some page content. I'm just one of your normal components between your custom toolbar and the MRT Table below"
    115 }
    116 </Typography>
    117 {/* The MRT Table */}
    118 <MaterialReactTable
    119 columns={columns}
    120 data={data}
    121 enableBottomToolbar={false}
    122 enableRowSelection
    123 enableTopToolbar={false}
    124 initialState={{ showGlobalFilter: true }}
    125 // See the Table State Management docs for why we need to use the updater function like this
    126 onColumnVisibilityChange={(updater) => {
    127 setColumnVisibility((prev) =>
    128 updater instanceof Function ? updater(prev) : updater,
    129 );
    130 queueMicrotask(rerender); //hack to rerender after state update
    131 }}
    132 onDensityChange={(updater) => {
    133 setDensity((prev) =>
    134 updater instanceof Function ? updater(prev) : updater,
    135 );
    136 queueMicrotask(rerender); //hack to rerender after state update
    137 }}
    138 onRowSelectionChange={(updater) => {
    139 setRowSelection((prev) =>
    140 updater instanceof Function ? updater(prev) : updater,
    141 );
    142 queueMicrotask(rerender); //hack to rerender after state update
    143 }}
    144 onPaginationChange={(updater) => {
    145 setPagination((prev) =>
    146 updater instanceof Function ? updater(prev) : updater,
    147 );
    148 queueMicrotask(rerender); //hack to rerender after state update
    149 }}
    150 onShowFiltersChange={(updater) => {
    151 setShowColumnFilters((prev) =>
    152 updater instanceof Function ? updater(prev) : updater,
    153 );
    154 queueMicrotask(rerender); //hack to rerender after state update
    155 }}
    156 state={{
    157 columnVisibility,
    158 density,
    159 rowSelection,
    160 pagination,
    161 showColumnFilters,
    162 }}
    163 tableInstanceRef={tableInstanceRef} //get access to the underlying table instance ref
    164 />
    165 {/* Our Custom Bottom Toolbar */}
    166 {tableInstanceRef.current && (
    167 <Toolbar
    168 sx={{
    169 display: 'flex',
    170 justifyContent: 'center',
    171 flexDirection: 'column',
    172 }}
    173 >
    174 <MRT_TablePagination table={tableInstanceRef.current} />
    175 <Box sx={{ display: 'grid', width: '100%' }}>
    176 <MRT_ToolbarAlertBanner
    177 stackAlertBanner
    178 table={tableInstanceRef.current}
    179 />
    180 </Box>
    181 </Toolbar>
    182 )}
    183 </Box>
    184 );
    185};
    186
    187export default Example;
    188