MRT logoMaterial React Table

Legacy V2 Docs

Row Dragging Example

Material React Table has built-in support row drag and drop features that can be used in a variety of ways. Learn more about column ordering in the Row Ordering/DnD Feature Guide.

More Examples

Demo

Open StackblitzOpen Code SandboxOpen on GitHub
Nice List
DylanMurrayEast Daphne
RaquelKohlerColumbus
ErvinReingerSouth Linda
1-3 of 3
Naughty List
BrittanyMcCulloughLincoln
BransonFramiCharleston
1-2 of 2

Source Code

1import { useMemo, useState } from 'react';
2import {
3 type MRT_TableOptions,
4 type MRT_ColumnDef,
5 type MRT_Row,
6 MaterialReactTable,
7 useMaterialReactTable,
8} from 'material-react-table';
9import { Box, Typography } from '@mui/material';
10import { data, type Person } from './makeData';
11
12const Example = () => {
13 const columns = useMemo<MRT_ColumnDef<Person>[]>(
14 //column definitions...
31 );
32
33 const [data1, setData1] = useState<Person[]>(() => data.slice(0, 3));
34 const [data2, setData2] = useState<Person[]>(() => data.slice(3, 5));
35
36 const [draggingRow, setDraggingRow] = useState<MRT_Row<Person> | null>(null);
37 const [hoveredTable, setHoveredTable] = useState<string | null>(null);
38
39 const commonTableProps: Partial<MRT_TableOptions<Person>> & {
40 columns: MRT_ColumnDef<Person>[];
41 } = {
42 columns,
43 enableRowDragging: true,
44 enableFullScreenToggle: false,
45 muiTableContainerProps: {
46 sx: {
47 minHeight: '320px',
48 },
49 },
50 onDraggingRowChange: setDraggingRow,
51 state: { draggingRow },
52 };
53
54 const table1 = useMaterialReactTable({
55 ...commonTableProps,
56 data: data1,
57 getRowId: (originalRow) => `table-1-${originalRow.firstName}`,
58 muiRowDragHandleProps: {
59 onDragEnd: () => {
60 if (hoveredTable === 'table-2') {
61 setData2((data2) => [...data2, draggingRow!.original]);
62 setData1((data1) => data1.filter((d) => d !== draggingRow!.original));
63 }
64 setHoveredTable(null);
65 },
66 },
67 muiTablePaperProps: {
68 onDragEnter: () => setHoveredTable('table-1'),
69 sx: {
70 outline: hoveredTable === 'table-1' ? '2px dashed pink' : undefined,
71 },
72 },
73 renderTopToolbarCustomActions: () => (
74 <Typography color="success.main" component="span" variant="h4">
75 Nice List
76 </Typography>
77 ),
78 });
79
80 const table2 = useMaterialReactTable({
81 ...commonTableProps,
82 data: data2,
83 defaultColumn: {
84 size: 100,
85 },
86 getRowId: (originalRow) => `table-2-${originalRow.firstName}`,
87 muiRowDragHandleProps: {
88 onDragEnd: () => {
89 if (hoveredTable === 'table-1') {
90 setData1((data1) => [...data1, draggingRow!.original]);
91 setData2((data2) => data2.filter((d) => d !== draggingRow!.original));
92 }
93 setHoveredTable(null);
94 },
95 },
96 muiTablePaperProps: {
97 onDragEnter: () => setHoveredTable('table-2'),
98 sx: {
99 outline: hoveredTable === 'table-2' ? '2px dashed pink' : undefined,
100 },
101 },
102 renderTopToolbarCustomActions: () => (
103 <Typography color="error.main" component="span" variant="h4">
104 Naughty List
105 </Typography>
106 ),
107 });
108
109 return (
110 <Box
111 sx={{
112 display: 'grid',
113 gridTemplateColumns: { xs: 'auto', lg: '1fr 1fr' },
114 gap: '1rem',
115 overflow: 'auto',
116 p: '4px',
117 }}
118 >
119 <MaterialReactTable table={table1} />
120 <MaterialReactTable table={table2} />
121 </Box>
122 );
123};
124
125export default Example;
126

View Extra Storybook Examples