1
+ import { Drawer , styled , useMediaQuery } from '@mui/material' ;
1
2
import { SelectChangeEvent } from '@mui/material/Select' ;
2
3
import React from 'react' ;
3
4
import { Button } from '../base/Button' ;
@@ -8,6 +9,7 @@ import { Paper } from '../base/Paper';
8
9
import { Select } from '../base/Select' ;
9
10
import { FilterIcon } from '../icons' ;
10
11
import { useTheme } from '../theme' ;
12
+ import { darkModalGradient , lightModalGradient } from '../theme/colors/colors' ;
11
13
import PopperListener from './PopperListener' ;
12
14
import { TooltipIcon } from './TooltipIconButton' ;
13
15
@@ -26,6 +28,16 @@ export interface UniversalFilterProps {
26
28
id : string ;
27
29
}
28
30
31
+ export const FilterHeader = styled ( 'div' ) ( ( { theme } ) => ( {
32
+ background : theme . palette . mode === 'light' ? lightModalGradient . fotter : darkModalGradient . fotter ,
33
+ padding : '0.75rem 1rem' ,
34
+ margin : '-1rem -1rem 1rem -1rem' ,
35
+ display : 'flex' ,
36
+ justifyContent : 'space-between' ,
37
+ alignItems : 'center' ,
38
+ color : theme . palette . text . primary
39
+ } ) ) ;
40
+
29
41
function UniversalFilter ( {
30
42
filters,
31
43
selectedFilters,
@@ -37,11 +49,22 @@ function UniversalFilter({
37
49
} : UniversalFilterProps ) : JSX . Element {
38
50
const [ anchorEl , setAnchorEl ] = React . useState < null | HTMLElement > ( null ) ;
39
51
const [ open , setOpen ] = React . useState ( false ) ;
52
+
40
53
const theme = useTheme ( ) ;
54
+ const isMobile = useMediaQuery ( theme . breakpoints . down ( 'sm' ) ) ;
55
+
56
+ const handleClick = ( event : React . MouseEvent < HTMLElement > ) => {
57
+ setAnchorEl ( event . currentTarget ) ;
58
+ setOpen ( ( prevOpen ) => ! prevOpen ) ;
59
+ } ;
60
+
61
+ const handleClose = ( ) => {
62
+ setAnchorEl ( null ) ;
63
+ setOpen ( false ) ;
64
+ } ;
41
65
42
66
const handleFilterChange = ( event : React . ChangeEvent < { value : string } > , columnName : string ) => {
43
67
const value = event . target . value ;
44
-
45
68
setSelectedFilters ( ( prevFilters ) => ( {
46
69
...prevFilters ,
47
70
[ columnName ] : value
@@ -53,98 +76,96 @@ function UniversalFilter({
53
76
handleApplyFilter ( ) ;
54
77
} ;
55
78
56
- const handleClick = ( event : React . MouseEvent < HTMLElement > ) => {
57
- setAnchorEl ( event . currentTarget ) ;
58
- setOpen ( ( previousOpen ) => ! previousOpen ) ;
59
- } ;
60
-
61
- const canBeOpen = open && Boolean ( anchorEl ) ;
62
- const idx = canBeOpen ? 'transition-popper' : undefined ;
79
+ const renderFilterContent = ( ) => (
80
+ < div >
81
+ < FilterHeader >
82
+ < h3 > Filters: </ h3 >
83
+ </ FilterHeader >
84
+ { Object . keys ( filters ) . map ( ( filterColumn ) => {
85
+ const options = filters [ filterColumn ] . options ;
86
+ return (
87
+ < div key = { filterColumn } role = "presentation" >
88
+ < InputLabel id = { filters [ filterColumn ] . name } > { filters [ filterColumn ] . name } </ InputLabel >
89
+ < Select
90
+ defaultValue = "All"
91
+ key = { filterColumn }
92
+ value = { selectedFilters [ filterColumn ] }
93
+ variant = { variant }
94
+ onChange = { ( e : SelectChangeEvent < unknown > ) =>
95
+ handleFilterChange ( e as React . ChangeEvent < { value : string } > , filterColumn )
96
+ }
97
+ style = { {
98
+ width : '20rem' ,
99
+ marginBottom : '1rem'
100
+ } }
101
+ inputProps = { { 'aria-label' : 'Without label' } }
102
+ displayEmpty
103
+ >
104
+ { showAllOption && < MenuItem value = "All" > All</ MenuItem > }
105
+ { options . map ( ( option ) => (
106
+ < MenuItem key = { option . value } value = { option . value } >
107
+ { option . label }
108
+ </ MenuItem >
109
+ ) ) }
110
+ </ Select >
111
+ </ div >
112
+ ) ;
113
+ } ) }
63
114
64
- const handleClose = ( ) => {
65
- setAnchorEl ( null ) ;
66
- setOpen ( false ) ;
67
- } ;
115
+ < div style = { { display : 'flex' , justifyContent : 'center' } } >
116
+ < Button variant = "contained" onClick = { handleApplyOnClick } >
117
+ Apply
118
+ </ Button >
119
+ </ div >
120
+ </ div >
121
+ ) ;
68
122
69
123
return (
70
- < React . Fragment >
124
+ < >
71
125
< div id = { id } >
72
126
< TooltipIcon
73
127
title = "Filter"
74
128
onClick = { handleClick }
75
129
icon = { < FilterIcon fill = { theme . palette . icon . default } /> }
76
130
arrow
77
131
/>
78
- < PopperListener
79
- id = { idx }
80
- open = { open }
81
- anchorEl = { anchorEl }
82
- placement = "bottom-end"
83
- // transition
84
- >
85
- < div >
86
- < ClickAwayListener
87
- onClickAway = { handleClose }
88
- mouseEvent = "onMouseDown"
89
- touchEvent = "onTouchStart"
90
- >
91
- < div >
92
- < Paper
93
- sx = { {
94
- padding : '1rem' ,
95
- paddingTop : '1.8rem' ,
96
- boxShadow : '0px 4px 8px rgba(0, 0, 0, 0.1)' ,
97
- backgroundColor : theme . palette . background . surfaces
98
- } }
99
- >
100
- { Object . keys ( filters ) . map ( ( filterColumn ) => {
101
- const options = filters [ filterColumn ] . options ;
102
- return (
103
- < div key = { filterColumn } role = "presentation" >
104
- < InputLabel id = { filters [ filterColumn ] . name } >
105
- { filters [ filterColumn ] . name }
106
- </ InputLabel >
107
- < Select
108
- defaultValue = "All"
109
- key = { filterColumn }
110
- value = { selectedFilters [ filterColumn ] }
111
- variant = { variant }
112
- onChange = { ( e : SelectChangeEvent < unknown > ) =>
113
- handleFilterChange (
114
- e as React . ChangeEvent < { value : string } > ,
115
- filterColumn
116
- )
117
- }
118
- style = { {
119
- width : '15rem' ,
120
- marginBottom : '1rem'
121
- } }
122
- inputProps = { { 'aria-label' : 'Without label' } }
123
- displayEmpty
124
- >
125
- { showAllOption && < MenuItem value = "All" > All</ MenuItem > }
126
- { options . map ( ( option ) => (
127
- < MenuItem key = { option . value } value = { option . value } >
128
- { option . label }
129
- </ MenuItem >
130
- ) ) }
131
- </ Select >
132
- </ div >
133
- ) ;
134
- } ) }
135
-
136
- < div style = { { display : 'flex' , justifyContent : 'flex-end' } } >
137
- < Button variant = "contained" onClick = { handleApplyOnClick } >
138
- Apply
139
- </ Button >
140
- </ div >
141
- </ Paper >
142
- </ div >
132
+ { ! isMobile ? (
133
+ < PopperListener
134
+ id = { open && anchorEl ? 'transition-popper' : undefined }
135
+ open = { open }
136
+ anchorEl = { anchorEl }
137
+ placement = "bottom-end"
138
+ >
139
+ < ClickAwayListener onClickAway = { handleClose } >
140
+ < Paper
141
+ sx = { {
142
+ padding : '1rem' ,
143
+ paddingTop : '1.8rem' ,
144
+ boxShadow : '0px 4px 8px rgba(0, 0, 0, 0.1)' ,
145
+ backgroundColor : theme . palette . background . surfaces
146
+ } }
147
+ >
148
+ { renderFilterContent ( ) }
149
+ </ Paper >
143
150
</ ClickAwayListener >
144
- </ div >
145
- </ PopperListener >
151
+ </ PopperListener >
152
+ ) : (
153
+ < Drawer
154
+ anchor = "bottom"
155
+ open = { open }
156
+ onClose = { handleClose }
157
+ PaperProps = { {
158
+ style : {
159
+ padding : '0 1rem 1rem 1rem' ,
160
+ backgroundColor : theme . palette . background . surfaces
161
+ }
162
+ } }
163
+ >
164
+ { renderFilterContent ( ) }
165
+ </ Drawer >
166
+ ) }
146
167
</ div >
147
- </ React . Fragment >
168
+ </ >
148
169
) ;
149
170
}
150
171
export default UniversalFilter ;
0 commit comments