Skip to content

Commit 8297fab

Browse files
authored
[DataGrid] Update Quick Filter component to be expandable (#16862)
1 parent 128c20f commit 8297fab

56 files changed

Lines changed: 3328 additions & 508 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import * as React from 'react';
2+
import { styled } from '@mui/material/styles';
3+
import {
4+
DataGrid,
5+
Toolbar,
6+
ToolbarButton,
7+
QuickFilter,
8+
QuickFilterControl,
9+
QuickFilterClear,
10+
QuickFilterTrigger,
11+
useGridApiContext,
12+
} from '@mui/x-data-grid';
13+
import { useDemoData } from '@mui/x-data-grid-generator';
14+
import TextField from '@mui/material/TextField';
15+
import InputAdornment from '@mui/material/InputAdornment';
16+
import CancelIcon from '@mui/icons-material/Cancel';
17+
import SearchIcon from '@mui/icons-material/Search';
18+
import Tooltip from '@mui/material/Tooltip';
19+
20+
const StyledQuickFilter = styled(QuickFilter)({
21+
display: 'grid',
22+
alignItems: 'center',
23+
marginLeft: 'auto',
24+
});
25+
26+
const StyledToolbarButton = styled(ToolbarButton)(({ theme, ownerState }) => ({
27+
gridArea: '1 / 1',
28+
width: 'min-content',
29+
height: 'min-content',
30+
zIndex: 1,
31+
opacity: ownerState.expanded ? 0 : 1,
32+
pointerEvents: ownerState.expanded ? 'none' : 'auto',
33+
transition: theme.transitions.create(['opacity']),
34+
}));
35+
36+
const StyledTextField = styled(TextField)(({ theme, ownerState }) => ({
37+
gridArea: '1 / 1',
38+
overflowX: 'clip',
39+
width: ownerState.expanded ? 260 : 'var(--trigger-width)',
40+
opacity: ownerState.expanded ? 1 : 0,
41+
transition: theme.transitions.create(['width', 'opacity']),
42+
}));
43+
44+
function CustomToolbar() {
45+
const [expanded, setExpanded] = React.useState(false);
46+
const apiRef = useGridApiContext();
47+
48+
React.useEffect(() => {
49+
const rootElement = apiRef.current.rootElementRef.current;
50+
51+
const handleKeyDown = (event) => {
52+
if ((event.ctrlKey || event.metaKey) && event.key === 'p') {
53+
event.preventDefault();
54+
setExpanded(true);
55+
}
56+
};
57+
58+
rootElement?.addEventListener('keydown', handleKeyDown);
59+
return () => rootElement?.removeEventListener('keydown', handleKeyDown);
60+
}, [apiRef]);
61+
62+
return (
63+
<Toolbar>
64+
<StyledQuickFilter expanded={expanded} onExpandedChange={setExpanded}>
65+
<QuickFilterTrigger
66+
render={(triggerProps) => (
67+
<Tooltip title="Search" enterDelay={0}>
68+
<StyledToolbarButton
69+
{...triggerProps}
70+
ownerState={{ expanded }}
71+
color="default"
72+
disabled={expanded}
73+
>
74+
<SearchIcon fontSize="small" />
75+
</StyledToolbarButton>
76+
</Tooltip>
77+
)}
78+
/>
79+
<QuickFilterControl
80+
render={({ ref, ...controlProps }, state) => (
81+
<StyledTextField
82+
{...controlProps}
83+
ownerState={{ expanded }}
84+
inputRef={ref}
85+
aria-label="Search"
86+
placeholder="Search..."
87+
size="small"
88+
slotProps={{
89+
input: {
90+
startAdornment: (
91+
<InputAdornment position="start">
92+
<SearchIcon fontSize="small" />
93+
</InputAdornment>
94+
),
95+
endAdornment: state.value ? (
96+
<InputAdornment position="end">
97+
<QuickFilterClear
98+
edge="end"
99+
size="small"
100+
aria-label="Clear search"
101+
sx={{ marginRight: -0.75 }}
102+
>
103+
<CancelIcon fontSize="small" />
104+
</QuickFilterClear>
105+
</InputAdornment>
106+
) : null,
107+
...controlProps.slotProps?.input,
108+
},
109+
...controlProps.slotProps,
110+
}}
111+
/>
112+
)}
113+
/>
114+
</StyledQuickFilter>
115+
</Toolbar>
116+
);
117+
}
118+
119+
export default function GridControlledQuickFilter() {
120+
const { data, loading } = useDemoData({
121+
dataSet: 'Commodity',
122+
rowLength: 10,
123+
maxColumns: 10,
124+
});
125+
126+
return (
127+
<div style={{ height: 400, width: '100%' }}>
128+
<DataGrid
129+
{...data}
130+
loading={loading}
131+
slots={{ toolbar: CustomToolbar }}
132+
showToolbar
133+
/>
134+
</div>
135+
);
136+
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import * as React from 'react';
2+
import { styled } from '@mui/material/styles';
3+
import {
4+
DataGrid,
5+
Toolbar,
6+
ToolbarButton,
7+
QuickFilter,
8+
QuickFilterControl,
9+
QuickFilterClear,
10+
QuickFilterTrigger,
11+
useGridApiContext,
12+
} from '@mui/x-data-grid';
13+
import { useDemoData } from '@mui/x-data-grid-generator';
14+
import TextField from '@mui/material/TextField';
15+
import InputAdornment from '@mui/material/InputAdornment';
16+
import CancelIcon from '@mui/icons-material/Cancel';
17+
import SearchIcon from '@mui/icons-material/Search';
18+
import Tooltip from '@mui/material/Tooltip';
19+
20+
type OwnerState = {
21+
expanded: boolean;
22+
};
23+
24+
const StyledQuickFilter = styled(QuickFilter)({
25+
display: 'grid',
26+
alignItems: 'center',
27+
marginLeft: 'auto',
28+
});
29+
30+
const StyledToolbarButton = styled(ToolbarButton)<{ ownerState: OwnerState }>(
31+
({ theme, ownerState }) => ({
32+
gridArea: '1 / 1',
33+
width: 'min-content',
34+
height: 'min-content',
35+
zIndex: 1,
36+
opacity: ownerState.expanded ? 0 : 1,
37+
pointerEvents: ownerState.expanded ? 'none' : 'auto',
38+
transition: theme.transitions.create(['opacity']),
39+
}),
40+
);
41+
42+
const StyledTextField = styled(TextField)<{
43+
ownerState: OwnerState;
44+
}>(({ theme, ownerState }) => ({
45+
gridArea: '1 / 1',
46+
overflowX: 'clip',
47+
width: ownerState.expanded ? 260 : 'var(--trigger-width)',
48+
opacity: ownerState.expanded ? 1 : 0,
49+
transition: theme.transitions.create(['width', 'opacity']),
50+
}));
51+
52+
function CustomToolbar() {
53+
const [expanded, setExpanded] = React.useState(false);
54+
const apiRef = useGridApiContext();
55+
56+
React.useEffect(() => {
57+
const rootElement = apiRef.current.rootElementRef.current;
58+
59+
const handleKeyDown = (event: KeyboardEvent) => {
60+
if ((event.ctrlKey || event.metaKey) && event.key === 'p') {
61+
event.preventDefault();
62+
setExpanded(true);
63+
}
64+
};
65+
66+
rootElement?.addEventListener('keydown', handleKeyDown);
67+
return () => rootElement?.removeEventListener('keydown', handleKeyDown);
68+
}, [apiRef]);
69+
70+
return (
71+
<Toolbar>
72+
<StyledQuickFilter expanded={expanded} onExpandedChange={setExpanded}>
73+
<QuickFilterTrigger
74+
render={(triggerProps) => (
75+
<Tooltip title="Search" enterDelay={0}>
76+
<StyledToolbarButton
77+
{...triggerProps}
78+
ownerState={{ expanded }}
79+
color="default"
80+
disabled={expanded}
81+
>
82+
<SearchIcon fontSize="small" />
83+
</StyledToolbarButton>
84+
</Tooltip>
85+
)}
86+
/>
87+
<QuickFilterControl
88+
render={({ ref, ...controlProps }, state) => (
89+
<StyledTextField
90+
{...controlProps}
91+
ownerState={{ expanded }}
92+
inputRef={ref}
93+
aria-label="Search"
94+
placeholder="Search..."
95+
size="small"
96+
slotProps={{
97+
input: {
98+
startAdornment: (
99+
<InputAdornment position="start">
100+
<SearchIcon fontSize="small" />
101+
</InputAdornment>
102+
),
103+
endAdornment: state.value ? (
104+
<InputAdornment position="end">
105+
<QuickFilterClear
106+
edge="end"
107+
size="small"
108+
aria-label="Clear search"
109+
sx={{ marginRight: -0.75 }}
110+
>
111+
<CancelIcon fontSize="small" />
112+
</QuickFilterClear>
113+
</InputAdornment>
114+
) : null,
115+
...controlProps.slotProps?.input,
116+
},
117+
...controlProps.slotProps,
118+
}}
119+
/>
120+
)}
121+
/>
122+
</StyledQuickFilter>
123+
</Toolbar>
124+
);
125+
}
126+
127+
export default function GridControlledQuickFilter() {
128+
const { data, loading } = useDemoData({
129+
dataSet: 'Commodity',
130+
rowLength: 10,
131+
maxColumns: 10,
132+
});
133+
134+
return (
135+
<div style={{ height: 400, width: '100%' }}>
136+
<DataGrid
137+
{...data}
138+
loading={loading}
139+
slots={{ toolbar: CustomToolbar }}
140+
showToolbar
141+
/>
142+
</div>
143+
);
144+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<DataGrid
2+
{...data}
3+
loading={loading}
4+
slots={{ toolbar: CustomToolbar }}
5+
showToolbar
6+
/>
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import * as React from 'react';
2+
import {
3+
DataGrid,
4+
Toolbar,
5+
QuickFilter,
6+
QuickFilterControl,
7+
QuickFilterClear,
8+
} from '@mui/x-data-grid';
9+
import { useDemoData } from '@mui/x-data-grid-generator';
10+
import InputAdornment from '@mui/material/InputAdornment';
11+
import TextField from '@mui/material/TextField';
12+
import CancelIcon from '@mui/icons-material/Cancel';
13+
import SearchIcon from '@mui/icons-material/Search';
14+
import { styled } from '@mui/material/styles';
15+
16+
const StyledQuickFilter = styled(QuickFilter)({
17+
marginLeft: 'auto',
18+
});
19+
20+
function CustomToolbar() {
21+
return (
22+
<Toolbar>
23+
<StyledQuickFilter expanded>
24+
<QuickFilterControl
25+
render={({ ref, ...other }) => (
26+
<TextField
27+
{...other}
28+
sx={{ width: 260 }}
29+
inputRef={ref}
30+
aria-label="Search"
31+
placeholder="Search..."
32+
size="small"
33+
slotProps={{
34+
input: {
35+
startAdornment: (
36+
<InputAdornment position="start">
37+
<SearchIcon fontSize="small" />
38+
</InputAdornment>
39+
),
40+
endAdornment: other.value ? (
41+
<InputAdornment position="end">
42+
<QuickFilterClear
43+
edge="end"
44+
size="small"
45+
aria-label="Clear search"
46+
sx={{ marginRight: -0.75 }}
47+
>
48+
<CancelIcon fontSize="small" />
49+
</QuickFilterClear>
50+
</InputAdornment>
51+
) : null,
52+
...other.slotProps?.input,
53+
},
54+
...other.slotProps,
55+
}}
56+
/>
57+
)}
58+
/>
59+
</StyledQuickFilter>
60+
</Toolbar>
61+
);
62+
}
63+
64+
export default function GridPersistentQuickFilter() {
65+
const { data, loading } = useDemoData({
66+
dataSet: 'Commodity',
67+
rowLength: 10,
68+
maxColumns: 10,
69+
});
70+
71+
return (
72+
<div style={{ height: 400, width: '100%' }}>
73+
<DataGrid
74+
{...data}
75+
loading={loading}
76+
slots={{ toolbar: CustomToolbar }}
77+
showToolbar
78+
/>
79+
</div>
80+
);
81+
}

0 commit comments

Comments
 (0)