MRT logoMaterial React Table

Row Pinning Feature Guide

Material React Table has a powerful row pinning feature that allows you to either pin rows to the top and bottom of the table as a user scrolls, or pin rows to the top and bottom of the table regardless of scrolling.

Relevant Table Options

1
boolean | (row: MRT_Row) => boolean
2
boolean
true
3
OnChangeFn<RowSelectionState>
TanStack Table Pinning Docs
4
'sticky' | 'top' | 'bottom' | 'top-and-bottom' | 'select-sticky' | 'select-top' | 'select-bottom'
'sticky'

Relevant State

1
{ top: string[], bottom: string[] }
{ top: [], bottom: [] }
TanStack Table Column Pinning Docs

Row Pinning Display Modes

You can enable the row pinning feature with the enableRowPinning table option. There are multiple display modes that you can choose from with the rowPinningDisplayMode table option.

const table = useMaterialReactTable({
columns,
data,
enableRowPinning: true,
rowPinningDisplayMode: 'sticky', // default
});
  • sticky - This is the default display mode. It will make rows stick to the top and bottom of the table as a user scrolls.

  • top - This will statically pin rows to the top of the table upon pinning.

  • bottom - This will statically pin rows to the bottom of the table upon pinning.

  • top-and-bottom - This allows the user to statically pin rows to either the top or bottom of the table.

  • select-sticky - This pins selected rows to the top and bottom of the table as a user scrolls. (alternative pinning UI)

  • select-top - This statically pins selected rows to the top of the table upon pinning. (alternative pinning UI)

  • select-bottom - This statically pins selected rows to the bottom of the table upon pinning. (alternative pinning UI)

Sticky Row Pinning

By default, the row pinning feature will add a position sticky style to the pinned rows. This means that the pinned rows will stay in place if the row is already in view. However, the rows will stay in view as the user scrolls up or down.

Sticky row pinning will work best if you give your rows a fixed height, or at least disable any kind of whitespace wrapping.

const table = useMaterialReactTable({
columns,
data,
enableRowPinning: true,
muiTableBodyRowProps: ({ row, table }) => {
const { density } = table.getState();
return {
sx: {
//Set a fixed height for pinned rows
height: row.getIsPinned()
? `${
//Default mrt row height estimates. Adjust as needed.
density === 'compact' ? 37 : density === 'comfortable' ? 53 : 69
}px`
: undefined,
},
};
},
rowPinningDisplayMode: 'sticky', // default
});
DylanMurraydmurray@yopmail.comEast Daphne
RaquelKohlerrkholer33@yopmail.comColumbus
ErvinReingerereinger@mailinator.comSouth Linda
BrittanyMcCulloughbmccullough44@mailinator.comLincoln
BransonFramibframi@yopmain.comNew York
BenMurraybenm@email.comSalt Lake City
ElenaSmithesmith@yopmail.comLos Angeles
MichaelJohnsonmjohnson@mailinator.comChicago
SophiaBrownsbrown@yopmail.comHouston
LucasDavisldavis@mailinator.comPhoenix
OliviaGarciaogarcia@yopmail.comPhiladelphia
LiamRodriguezlrodriguez@mailinator.comSan Antonio
EmmaMartinezemartinez@yopmail.comSan Diego
NoahHernandeznhernandez@mailinator.comDallas
AvaLopezalopez@yopmail.comSan Jose
WilliamGonzalezwgonzalez@mailinator.comAustin
IsabellaWilsoniwilson@yopmail.comJacksonville
JamesAndersonjanderson@mailinator.comFort Worth
MiaThomasmthomas@yopmail.comColumbus
AlexanderTaylorataylor@mailinator.comCharlotte
GraceMooregmoore@yopmail.comIndianapolis
EthanWhiteewhite@mailinator.comSan Francisco
LilyHarrislharris@yopmail.comSeattle
DanielMartindmartin@mailinator.comDenver
ZoeJacksonzjackson@yopmail.comBoston
MatthewThompsonmthompson@mailinator.comNashville
EllaGarciaegarcia@yopmail.comDetroit
DavidMartinezdmartinez@mailinator.comPortland
AriaRobinsonarobinson@yopmail.comLas Vegas
JosephClarkjclark@mailinator.comBaltimore

Source Code

1import { useMemo } from 'react';
2import {
3 MaterialReactTable,
4 useMaterialReactTable,
5 type MRT_ColumnDef,
6} from 'material-react-table';
7import { data, type Person } from './makeData';
8
9const Example = () => {
10 const columns = useMemo<MRT_ColumnDef<Person>[]>(
11 () => [
12 {
13 accessorKey: 'firstName',
14 header: 'First Name',
15 },
16 {
17 accessorKey: 'lastName',
18 header: 'Last Name',
19 },
20 {
21 accessorKey: 'email',
22 header: 'Email',
23 },
24 {
25 accessorKey: 'city',
26 header: 'City',
27 },
28 ],
29 [],
30 );
31
32 const table = useMaterialReactTable({
33 columns,
34 data,
35 enableRowPinning: true,
36 enablePagination: false,
37 enableStickyHeader: true,
38 getRowId: (row) => row.email,
39 initialState: {
40 rowPinning: {
41 top: ['rkholer33@yopmail.com', 'egarcia@yopmail.com'],
42 bottom: [],
43 },
44 },
45 muiTableContainerProps: {
46 sx: {
47 maxHeight: '400px',
48 },
49 },
50 muiTableBodyRowProps: ({ row, table }) => {
51 const { density } = table.getState();
52 return {
53 sx: {
54 //Set a fixed height for pinned rows
55 height: row.getIsPinned()
56 ? `${
57 //Default mrt row height estimates. Adjust as needed.
58 density === 'compact' ? 37 : density === 'comfortable' ? 53 : 69
59 }px`
60 : undefined,
61 },
62 };
63 },
64 });
65
66 return <MaterialReactTable table={table} />;
67};
68
69export default Example;
70

Note: Sticky Row Pinning is not currently compatible with row virtualization.

Static Row Pinning

Some of the other row pinning modes will show pinned rows at the top or bottom of the the table regardless of scrolling. This is a simpler implementation of the row pinning feature.

Static row pinning does not require set row heights, as they will render in a normal <tbody> element that itself is what is sticky.

DylanMurraydmurray@yopmail.comEast Daphne
RaquelKohlerrkholer33@yopmail.comColumbus
ErvinReingerereinger@mailinator.comSouth Linda
BrittanyMcCulloughbmccullough44@mailinator.comLincoln
BransonFramibframi@yopmain.comNew York
BenMurraybenm@email.comSalt Lake City
ElenaSmithesmith@yopmail.comLos Angeles
MichaelJohnsonmjohnson@mailinator.comChicago
SophiaBrownsbrown@yopmail.comHouston
LucasDavisldavis@mailinator.comPhoenix
OliviaGarciaogarcia@yopmail.comPhiladelphia
LiamRodriguezlrodriguez@mailinator.comSan Antonio
EmmaMartinezemartinez@yopmail.comSan Diego
NoahHernandeznhernandez@mailinator.comDallas
AvaLopezalopez@yopmail.comSan Jose
WilliamGonzalezwgonzalez@mailinator.comAustin
IsabellaWilsoniwilson@yopmail.comJacksonville
JamesAndersonjanderson@mailinator.comFort Worth
MiaThomasmthomas@yopmail.comColumbus
AlexanderTaylorataylor@mailinator.comCharlotte
GraceMooregmoore@yopmail.comIndianapolis
EthanWhiteewhite@mailinator.comSan Francisco
LilyHarrislharris@yopmail.comSeattle
DanielMartindmartin@mailinator.comDenver
ZoeJacksonzjackson@yopmail.comBoston
MatthewThompsonmthompson@mailinator.comNashville
EllaGarciaegarcia@yopmail.comDetroit
DavidMartinezdmartinez@mailinator.comPortland
AriaRobinsonarobinson@yopmail.comLas Vegas
JosephClarkjclark@mailinator.comBaltimore

Source Code

1import { useMemo } from 'react';
2import {
3 MaterialReactTable,
4 useMaterialReactTable,
5 type MRT_ColumnDef,
6} from 'material-react-table';
7import { data, type Person } from './makeData';
8
9const Example = () => {
10 const columns = useMemo<MRT_ColumnDef<Person>[]>(
11 () => [
12 {
13 accessorKey: 'firstName',
14 header: 'First Name',
15 },
16 {
17 accessorKey: 'lastName',
18 header: 'Last Name',
19 },
20 {
21 accessorKey: 'email',
22 header: 'Email',
23 },
24 {
25 accessorKey: 'city',
26 header: 'City',
27 },
28 ],
29 [],
30 );
31
32 const table = useMaterialReactTable({
33 columns,
34 data,
35 enableRowPinning: true,
36 enablePagination: false,
37 enableStickyHeader: true,
38 rowPinningDisplayMode: 'top-and-bottom',
39 getRowId: (row) => row.email,
40 muiTableContainerProps: {
41 sx: {
42 maxHeight: '400px',
43 },
44 },
45 });
46
47 return <MaterialReactTable table={table} />;
48};
49
50export default Example;
51

Alternative Selection Row Pinning UI

By default, the row pinning feature adds a pinning display column with pinning buttons for each row. However, you can instead combine the row pinning feature with the row selection feature to pin selected rows.

const table = useMaterialReactTable({
columns,
data,
enableRowPinning: true,
enableRowSelection: true,
rowPinningDisplayMode: 'select-sticky',
});
DylanMurraydmurray@yopmail.comEast Daphne
RaquelKohlerrkholer33@yopmail.comColumbus
ErvinReingerereinger@mailinator.comSouth Linda
BrittanyMcCulloughbmccullough44@mailinator.comLincoln
BransonFramibframi@yopmain.comNew York
BenMurraybenm@email.comSalt Lake City
ElenaSmithesmith@yopmail.comLos Angeles
MichaelJohnsonmjohnson@mailinator.comChicago
SophiaBrownsbrown@yopmail.comHouston
LucasDavisldavis@mailinator.comPhoenix
OliviaGarciaogarcia@yopmail.comPhiladelphia
LiamRodriguezlrodriguez@mailinator.comSan Antonio
EmmaMartinezemartinez@yopmail.comSan Diego
NoahHernandeznhernandez@mailinator.comDallas
AvaLopezalopez@yopmail.comSan Jose
WilliamGonzalezwgonzalez@mailinator.comAustin
IsabellaWilsoniwilson@yopmail.comJacksonville
JamesAndersonjanderson@mailinator.comFort Worth
MiaThomasmthomas@yopmail.comColumbus
AlexanderTaylorataylor@mailinator.comCharlotte
GraceMooregmoore@yopmail.comIndianapolis
EthanWhiteewhite@mailinator.comSan Francisco
LilyHarrislharris@yopmail.comSeattle
DanielMartindmartin@mailinator.comDenver
ZoeJacksonzjackson@yopmail.comBoston
MatthewThompsonmthompson@mailinator.comNashville
EllaGarciaegarcia@yopmail.comDetroit
DavidMartinezdmartinez@mailinator.comPortland
AriaRobinsonarobinson@yopmail.comLas Vegas
JosephClarkjclark@mailinator.comBaltimore

Source Code

1import { useMemo } from 'react';
2import {
3 MaterialReactTable,
4 useMaterialReactTable,
5 type MRT_ColumnDef,
6} from 'material-react-table';
7import { data, type Person } from './makeData';
8
9const Example = () => {
10 const columns = useMemo<MRT_ColumnDef<Person>[]>(
11 //column definitions...
32 );
33
34 const table = useMaterialReactTable({
35 columns,
36 data,
37 enablePagination: false,
38 enableRowPinning: true,
39 enableRowSelection: true,
40 enableStickyHeader: true,
41 rowPinningDisplayMode: 'select-sticky',
42 getRowId: (row) => row.email,
43 initialState: {
44 rowPinning: {
45 top: ['ereinger@mailinator.com'],
46 },
47 rowSelection: {
48 'ereinger@mailinator.com': true,
49 },
50 },
51 muiTableContainerProps: {
52 sx: {
53 maxHeight: '400px',
54 },
55 },
56 muiTableBodyRowProps: ({ row, table }) => {
57 const { density } = table.getState();
58 return {
59 sx: {
60 //Set a fixed height for pinned rows
61 height: row.getIsPinned()
62 ? `${
63 //Default mrt row height estimates. Adjust as needed.
64 density === 'compact' ? 37 : density === 'comfortable' ? 53 : 69
65 }px`
66 : undefined,
67 },
68 };
69 },
70 });
71
72 return <MaterialReactTable table={table} />;
73};
74
75export default Example;
76