1
1
import { useState , useEffect } from "react" ;
2
2
import { Combobox as HeadlessCombobox } from "@headlessui/react" ;
3
- import { CaretSortIcon , MagnifyingGlassIcon } from "@radix-ui/react-icons" ;
3
+ import { ChevronDownIcon , MagnifyingGlassIcon } from "@radix-ui/react-icons" ;
4
4
import { cn } from "@ui/cn" ;
5
- import isEqual from "lodash/isEqual " ;
6
- import { test } from "fuzzy" ;
5
+ import { isEqual } from "lodash-es " ;
6
+ import fuzzy from "fuzzy" ;
7
7
import { Button , ButtonProps } from "@ui/Button" ;
8
8
import { createPortal } from "react-dom" ;
9
9
import { usePopper } from "react-popper" ;
10
10
11
+ const { test } = fuzzy ;
12
+
11
13
export type Option < T > = { label : string ; value : T } ;
12
14
13
15
export function Combobox < T > ( {
14
16
options,
17
+ optionsHeader,
15
18
optionsWidth = "fixed" ,
16
19
selectedOption,
17
20
setSelectedOption,
@@ -35,6 +38,7 @@ export function Combobox<T>({
35
38
label : React . ReactNode ;
36
39
labelHidden ?: boolean ;
37
40
className ?: string ;
41
+ optionsHeader ?: React . ReactNode ;
38
42
options : Readonly < Option < T > [ ] > ;
39
43
placeholder ?: string ;
40
44
searchPlaceholder ?: string ;
@@ -157,13 +161,13 @@ export function Combobox<T>({
157
161
data-testid = { `combobox-button-${ label } ` }
158
162
className = { cn (
159
163
"flex gap-1 w-full items-center group" ,
160
- "truncate relative text-left text-content-primary rounded disabled:bg-background-tertiary disabled:text-content-secondary disabled:cursor-not-allowed" ,
164
+ "truncate relative text-left text-content-primary rounded-md disabled:bg-background-tertiary disabled:text-content-secondary disabled:cursor-not-allowed" ,
161
165
"border focus-visible:z-10 focus-visible:border-border-selected focus-visible:outline-none bg-background-secondary text-sm" ,
162
166
"hover:bg-background-tertiary" ,
163
167
"cursor-pointer" ,
164
168
open && "border-border-selected z-10" ,
165
- size === "sm" && "py-1 px-2 text-xs" ,
166
- size === "md" && "py-2 px-3 " ,
169
+ size === "sm" && "py-1 px-1.5 text-xs" ,
170
+ size === "md" && "p-1.5 " ,
167
171
innerButtonClasses ,
168
172
) }
169
173
{ ...buttonProps }
@@ -190,8 +194,11 @@ export function Combobox<T>({
190
194
) }
191
195
</ div >
192
196
{ size === "md" && (
193
- < CaretSortIcon
194
- className = { cn ( "text-content-primary" , "ml-auto size-5" ) }
197
+ < ChevronDownIcon
198
+ className = { cn (
199
+ "text-content-primary ml-auto size-4 transition-all" ,
200
+ open && "rotate-180" ,
201
+ ) }
195
202
/>
196
203
) }
197
204
</ HeadlessCombobox . Button >
@@ -210,12 +217,15 @@ export function Combobox<T>({
210
217
< HeadlessCombobox . Options
211
218
static
212
219
className = { cn (
213
- "mt-1 max-h-[14.75rem] overflow-auto rounded bg-background-secondary pb-1 text-xs shadow scrollbar border" ,
220
+ "mt-1 max-h-[14.75rem] overflow-auto rounded-md bg-background-secondary pb-1 text-xs shadow scrollbar border" ,
214
221
) }
215
222
ref = { ( el ) => {
216
223
el && "scrollTo" in el && el . scrollTo ( 0 , 0 ) ;
217
224
} }
218
225
>
226
+ { optionsHeader && (
227
+ < div className = "border-b p-1 pb-2" > { optionsHeader } </ div >
228
+ ) }
219
229
< div className = "min-w-fit" >
220
230
{ ! disableSearch && (
221
231
< div className = "sticky top-0 z-10 flex w-full items-center gap-2 border-b bg-background-secondary px-3 pt-1" >
0 commit comments