@@ -17,14 +17,6 @@ export function Filters({
17
17
} : FiltersProps ) {
18
18
return (
19
19
< div className = "flex justify-center gap-3 pb-10" >
20
- { Object . values ( filterState ) . flat ( ) . length > 0 && (
21
- < button
22
- onClick = { onReset }
23
- className = "flex cursor-pointer items-center gap-x-2 bg-neu-100 px-2 py-1 text-neu-700 hover:bg-neu-200/80 hover:text-neu-900"
24
- >
25
- Reset filters < X className = "inline-block size-4" />
26
- </ button >
27
- ) }
28
20
< Menu as = "div" className = "relative inline-block text-left" >
29
21
< Transition
30
22
enter = "transition ease-out duration-100"
@@ -34,7 +26,7 @@ export function Filters({
34
26
leaveFrom = "transform opacity-100 scale-100"
35
27
leaveTo = "transform opacity-0 scale-95"
36
28
>
37
- < Menu . Items className = "absolute left-0 z-10 mt-2 w-40 origin-top-left rounded-md shadow-2xl ring-1 ring-black /5 focus:outline-none" >
29
+ < Menu . Items className = "absolute left-0 z-10 mt-2 w-40 origin-top-left rounded-md shadow-2xl ring-1 ring-blk /5 focus:outline-none" >
38
30
< div className = "py-1" >
39
31
{ categories . map ( option => (
40
32
< Menu . Item key = { option . name } >
@@ -46,18 +38,18 @@ export function Filters({
46
38
</ Transition >
47
39
</ Menu >
48
40
< Popover . Group className = "flex items-baseline space-x-8" >
49
- { categories . map ( ( section , sectionIdx ) => (
41
+ { categories . map ( ( category , sectionIdx ) => (
50
42
< Popover
51
43
as = "div"
52
- key = { section . name }
44
+ key = { category . name }
53
45
id = { `desktop-menu-${ sectionIdx } ` }
54
46
className = "relative inline-block text-left"
55
47
>
56
48
< Popover . Button className = "group inline-flex cursor-pointer items-center justify-center bg-inherit p-1 px-2 text-neu-700 hover:text-neu-900" >
57
- < span > { section . name } </ span >
58
- { filterState [ section . name ] . length ? (
49
+ < span > { category . name } </ span >
50
+ { filterState [ category . name ] . length ? (
59
51
< span className = "ml-1.5 bg-neu-200 px-1.5 py-0.5 tabular-nums text-neu-700" >
60
- { filterState [ section . name ] . length }
52
+ { filterState [ category . name ] . length }
61
53
</ span >
62
54
) : null }
63
55
< ChevronDown
@@ -67,34 +59,68 @@ export function Filters({
67
59
</ Popover . Button >
68
60
69
61
< Popover . Panel className = "absolute right-0 z-10 mt-2 origin-top-right rounded-md bg-neu-0 p-4 shadow-lg focus:outline-none" >
70
- < form className = "space-y-4" >
71
- { section . options . map ( ( option , optionIdx ) => (
72
- < div key = { option } className = "flex items-center gap-3" >
73
- < input
74
- id = { `filter-${ section . name } -${ optionIdx } ` }
75
- name = { `${ section . name } []` }
76
- defaultValue = { option }
77
- onChange = { e => {
78
- const { checked, value } = e . target
79
- onFilterChange ( section . name , value , checked )
80
- } }
81
- checked = { filterState [ section . name ] . includes ( option ) }
82
- type = "checkbox"
83
- className = "size-4 cursor-pointer rounded border-neu-300 text-indigo-600 focus:ring-indigo-500"
84
- />
85
- < label
86
- htmlFor = { `filter-${ section . name } -${ optionIdx } ` }
87
- className = "cursor-pointer whitespace-nowrap pr-6 text-neu-900"
88
- >
89
- { option }
90
- </ label >
91
- </ div >
92
- ) ) }
93
- </ form >
62
+ < FilterOptions
63
+ category = { category }
64
+ filterState = { filterState }
65
+ onFilterChange = { onFilterChange }
66
+ />
94
67
</ Popover . Panel >
95
68
</ Popover >
96
69
) ) }
97
70
</ Popover . Group >
71
+ { Object . values ( filterState ) . flat ( ) . length > 0 && (
72
+ < ResetButton onReset = { onReset } />
73
+ ) }
98
74
</ div >
99
75
)
100
76
}
77
+
78
+ function ResetButton ( { onReset } : { onReset : ( ) => void } ) {
79
+ return (
80
+ < button
81
+ onClick = { onReset }
82
+ className = "flex cursor-pointer items-center gap-x-2 bg-neu-100 px-2 py-1 text-neu-700 hover:bg-neu-200/80 hover:text-neu-900"
83
+ >
84
+ Reset filters < X className = "inline-block size-4" />
85
+ </ button >
86
+ )
87
+ }
88
+
89
+ interface FilterOptionsProps {
90
+ category : { name : string ; options : string [ ] }
91
+ filterState : Record < string , string [ ] >
92
+ onFilterChange : ( category : string , option : string , checked : boolean ) => void
93
+ }
94
+
95
+ function FilterOptions ( {
96
+ category,
97
+ filterState,
98
+ onFilterChange,
99
+ } : FilterOptionsProps ) {
100
+ return (
101
+ < form className = "space-y-4" >
102
+ { category . options . map ( ( option , optionIdx ) => (
103
+ < div key = { option } className = "flex items-center gap-3" >
104
+ < input
105
+ id = { `filter-${ category . name } -${ optionIdx } ` }
106
+ name = { `${ category . name } []` }
107
+ defaultValue = { option }
108
+ onChange = { e => {
109
+ const { checked, value } = e . target
110
+ onFilterChange ( category . name , value , checked )
111
+ } }
112
+ checked = { filterState [ category . name ] . includes ( option ) }
113
+ type = "checkbox"
114
+ className = "size-4 cursor-pointer rounded border-neu-300"
115
+ />
116
+ < label
117
+ htmlFor = { `filter-${ category . name } -${ optionIdx } ` }
118
+ className = "cursor-pointer whitespace-nowrap pr-6 text-neu-900"
119
+ >
120
+ { option }
121
+ </ label >
122
+ </ div >
123
+ ) ) }
124
+ </ form >
125
+ )
126
+ }
0 commit comments