@@ -17,14 +17,6 @@ export function Filters({
1717} : FiltersProps ) {
1818 return (
1919 < 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- ) }
2820 < Menu as = "div" className = "relative inline-block text-left" >
2921 < Transition
3022 enter = "transition ease-out duration-100"
@@ -34,7 +26,7 @@ export function Filters({
3426 leaveFrom = "transform opacity-100 scale-100"
3527 leaveTo = "transform opacity-0 scale-95"
3628 >
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" >
3830 < div className = "py-1" >
3931 { categories . map ( option => (
4032 < Menu . Item key = { option . name } >
@@ -46,18 +38,18 @@ export function Filters({
4638 </ Transition >
4739 </ Menu >
4840 < Popover . Group className = "flex items-baseline space-x-8" >
49- { categories . map ( ( section , sectionIdx ) => (
41+ { categories . map ( ( category , sectionIdx ) => (
5042 < Popover
5143 as = "div"
52- key = { section . name }
44+ key = { category . name }
5345 id = { `desktop-menu-${ sectionIdx } ` }
5446 className = "relative inline-block text-left"
5547 >
5648 < 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 ? (
5951 < 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 }
6153 </ span >
6254 ) : null }
6355 < ChevronDown
@@ -67,34 +59,68 @@ export function Filters({
6759 </ Popover . Button >
6860
6961 < 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+ />
9467 </ Popover . Panel >
9568 </ Popover >
9669 ) ) }
9770 </ Popover . Group >
71+ { Object . values ( filterState ) . flat ( ) . length > 0 && (
72+ < ResetButton onReset = { onReset } />
73+ ) }
9874 </ div >
9975 )
10076}
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