Custom Headless Example
For advanced use cases where you want to be in 100% control of your UI components, you can use Mantine React Table in a more headless way, kind of like how you would use stock TanStack Table.
The power and flexibility here is almost limitless, as you can combine some already built-in Mantine React Table components alongside your own custom components. For the MRT components to work properly, all you need to do is pass the
table
object returned from the useMantineReactTable
hook.My Custom Headless Table
First Name | Last Name | Address | City | State | |
---|---|---|---|---|---|
Christopher | Lee | 555 Cedar Street | Seattle | Washington | |
Rachel | Anderson | 987 Walnut Court | New York | New York | |
David | Garcia | 654 Maple Avenue | Los Angeles | California | |
Zachary | Davis | 261 Battle Ford | Columbus | Ohio | |
Robert | Smith | 566 Brakus Inlet | Westerville | West Virginia |
1import {2flexRender,3MRT_GlobalFilterTextInput,4MRT_TablePagination,5MRT_ToolbarAlertBanner,6type MRT_ColumnDef,7useMantineReactTable,8} from 'mantine-react-table';9import { Divider, Flex, Stack, Table, Title } from '@mantine/core';10import { type Person, data } from './makeData';1112const columns: MRT_ColumnDef<Person>[] = [13{14accessorKey: 'name.firstName',15header: 'First Name',16},17{18accessorKey: 'name.lastName',19header: 'Last Name',20},21{22accessorKey: 'address',23header: 'Address',24},25{26accessorKey: 'city',27header: 'City',28},29{30accessorKey: 'state',31header: 'State',32},33];3435const Example = () => {36const table = useMantineReactTable({37columns,38data, //must be memoized or stable (useState, useMemo, defined outside of this component, etc.)39//MRT display columns can still work, optionally override cell renders with `displayColumnDefOptions`40enableRowSelection: true,41initialState: {42pagination: { pageSize: 5, pageIndex: 0 },43showGlobalFilter: true,44},45//customize the MRT components46mantinePaginationProps: {47rowsPerPageOptions: ['5', '10', '15'],48},49paginationDisplayMode: 'pages',50});5152return (53<Stack>54<Divider />55<Title order={4}>My Custom Headless Table</Title>56<Flex justify="space-between" align="center">57{/**58* Use MRT components along side your own markup.59* They just need the `table` instance passed as a prop to work!60*/}61<MRT_GlobalFilterTextInput table={table} />62<MRT_TablePagination table={table} />63</Flex>64{/* Using Vanilla Mantine Table component here */}65<Table66captionSide="top"67fontSize="md"68highlightOnHover69horizontalSpacing="xl"70striped71verticalSpacing="xs"72withBorder73withColumnBorders74m="0"75>76{/* Use your own markup, customize however you want using the power of TanStack Table */}77<thead>78{table.getHeaderGroups().map((headerGroup) => (79<tr key={headerGroup.id}>80{headerGroup.headers.map((header) => (81<th key={header.id}>82{header.isPlaceholder83? null84: flexRender(85header.column.columnDef.Header ??86header.column.columnDef.header,87header.getContext(),88)}89</th>90))}91</tr>92))}93</thead>94<tbody>95{table.getRowModel().rows.map((row) => (96<tr key={row.id}>97{row.getVisibleCells().map((cell) => (98<td key={cell.id}>99{flexRender(100cell.column.columnDef.Cell ?? cell.column.columnDef.cell,101cell.getContext(),102)}103</td>104))}105</tr>106))}107</tbody>108</Table>109<MRT_ToolbarAlertBanner stackAlertBanner table={table} />110</Stack>111);112};113114export default Example;
1import {2flexRender,3MRT_GlobalFilterTextInput,4MRT_TablePagination,5MRT_ToolbarAlertBanner,6useMantineReactTable,7} from 'mantine-react-table';8import { Divider, Flex, Stack, Table } from '@mantine/core';9import { data } from './makeData';1011const columns = [12{13accessorKey: 'name.firstName',14header: 'First Name',15},16{17accessorKey: 'name.lastName',18header: 'Last Name',19},20{21accessorKey: 'address',22header: 'Address',23},24{25accessorKey: 'city',26header: 'City',27},28{29accessorKey: 'state',30header: 'State',31},32];3334const Example = () => {35const table = useMantineReactTable({36columns,37data, //must be memoized or stable (useState, useMemo, defined outside of this component, etc.)38//MRT display columns can still work, optionally override cell renders with `displayColumnDefOptions`39enableRowSelection: true,40initialState: {41pagination: { pageSize: 5, pageIndex: 0 },42showGlobalFilter: true,43},44//customize the MRT components45mantinePaginationProps: {46rowsPerPageOptions: ['5', '10', '15'],47},48paginationDisplayMode: 'pages',49});5051return (52<Stack>53<Divider />54<Flex justify="space-between" align="center">55{/**56* Use MRT components along side your own markup.57* They just need the `table` instance passed as a prop to work!58*/}59<MRT_GlobalFilterTextInput table={table} />60<MRT_TablePagination table={table} />61</Flex>62{/* Using Vanilla Mantine Table component here */}63<Table64captionSide="top"65fontSize="md"66highlightOnHover67horizontalSpacing="xl"68striped69verticalSpacing="xs"70withBorder71withColumnBorders72>73{/* Use your own markup, customize however you want using the power of TanStack Table */}74<thead>75{table.getHeaderGroups().map((headerGroup) => (76<tr key={headerGroup.id}>77{headerGroup.headers.map((header) => (78<th key={header.id}>79{header.isPlaceholder80? null81: flexRender(82header.column.columnDef.Header ??83header.column.columnDef.header,84header.getContext(),85)}86</th>87))}88</tr>89))}90</thead>91<tbody>92{table.getRowModel().rows.map((row) => (93<tr key={row.id}>94{row.getVisibleCells().map((cell) => (95<td key={cell.id}>96{flexRender(97cell.column.columnDef.Cell ?? cell.column.columnDef.cell,98cell.getContext(),99)}100</td>101))}102</tr>103))}104</tbody>105</Table>106<MRT_ToolbarAlertBanner stackAlertBanner table={table} />107</Stack>108);109};110111export default Example;
View Extra Storybook Examples