@@ -13,27 +13,41 @@ import {
13
13
Link ,
14
14
VStack ,
15
15
useBreakpoints ,
16
+ Box ,
16
17
} from '@fuels/ui' ;
17
18
import { IconCheck , IconSearch , IconX } from '@tabler/icons-react' ;
18
19
import NextLink from 'next/link' ;
19
20
import type { KeyboardEvent } from 'react' ;
20
21
import { forwardRef , useContext , useEffect , useRef , useState } from 'react' ;
21
22
import { useFormStatus } from 'react-dom' ;
22
- import { tv } from 'tailwind-variants' ;
23
23
import { Routes } from '~/routes' ;
24
24
25
25
import { cx } from '../../utils/cx' ;
26
- import { SearchContext } from '../SearchWidget/SearchWidget' ;
26
+
27
+ import { SearchContext } from './SearchWidget' ;
28
+ import { styles } from './styles' ;
27
29
28
30
type SearchDropdownProps = {
29
31
searchResult ?: Maybe < SearchResult > ;
30
32
openDropdown : boolean ;
31
33
onOpenChange : ( ) => void ;
32
34
searchValue : string ;
35
+ width : number ;
36
+ onSelectItem : ( ) => void ;
33
37
} ;
34
38
35
39
const SearchResultDropdown = forwardRef < HTMLDivElement , SearchDropdownProps > (
36
- ( { searchResult, searchValue, openDropdown, onOpenChange } , ref ) => {
40
+ (
41
+ {
42
+ searchResult,
43
+ searchValue,
44
+ openDropdown,
45
+ onOpenChange,
46
+ width,
47
+ onSelectItem,
48
+ } ,
49
+ ref ,
50
+ ) => {
37
51
const classes = styles ( ) ;
38
52
const { isMobile } = useBreakpoints ( ) ;
39
53
const trimL = isMobile ? 15 : 20 ;
@@ -42,9 +56,13 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
42
56
return (
43
57
< Dropdown open = { openDropdown } onOpenChange = { onOpenChange } >
44
58
< Dropdown . Trigger >
45
- < div > </ div >
59
+ < Box className = "w-full" > </ Box >
46
60
</ Dropdown . Trigger >
47
- < Dropdown . Content ref = { ref } className = "w-[311px] tablet:w-[400px]" >
61
+ < Dropdown . Content
62
+ ref = { ref }
63
+ className = { cx ( classes . dropdownContent ( ) , classes . searchSize ( ) ) }
64
+ style = { { width : width - 0.5 } }
65
+ >
48
66
{ ! searchResult && (
49
67
< >
50
68
< Dropdown . Item className = "hover:bg-transparent focus:bg-transparent text-error hover:text-error focus:text-error" >
@@ -60,6 +78,7 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
60
78
as = { NextLink }
61
79
href = { Routes . accountAssets ( searchResult . account . address ! ) }
62
80
className = "text-color"
81
+ onClick = { onSelectItem }
63
82
>
64
83
{ shortAddress (
65
84
searchResult . account . address || '' ,
@@ -80,6 +99,7 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
80
99
as = { NextLink }
81
100
href = { Routes . txSimple ( transaction ! . id ! ) }
82
101
className = "text-color"
102
+ onClick = { onSelectItem }
83
103
>
84
104
{ shortAddress ( transaction ?. id || '' , trimL , trimR ) }
85
105
</ Link >
@@ -96,6 +116,7 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
96
116
as = { NextLink }
97
117
href = { Routes . blockSimple ( searchResult . block . id ! ) }
98
118
className = "text-color"
119
+ onClick = { onSelectItem }
99
120
>
100
121
{ shortAddress ( searchResult . block . id || '' , trimL , trimR ) }
101
122
</ Link >
@@ -105,6 +126,7 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
105
126
as = { NextLink }
106
127
href = { Routes . blockSimple ( searchResult . block . height ! ) }
107
128
className = "text-color"
129
+ onClick = { onSelectItem }
108
130
>
109
131
{ searchResult . block . height }
110
132
</ Link >
@@ -119,6 +141,7 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
119
141
as = { NextLink }
120
142
href = { Routes . contractAssets ( searchResult . contract . id ! ) }
121
143
className = "text-color"
144
+ onClick = { onSelectItem }
122
145
>
123
146
{ shortAddress ( searchResult . contract . id || '' , trimL , trimR ) }
124
147
</ Link >
@@ -133,6 +156,7 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
133
156
as = { NextLink }
134
157
href = { Routes . txSimple ( searchResult . transaction . id ! ) }
135
158
className = "text-color"
159
+ onClick = { onSelectItem }
136
160
>
137
161
{ shortAddress (
138
162
searchResult . transaction . id || '' ,
@@ -163,13 +187,14 @@ export function SearchInput({
163
187
autoFocus,
164
188
placeholder = 'Search here...' ,
165
189
searchResult,
166
- alwaysDisplayActionButtons,
167
190
...props
168
191
} : SearchInputProps ) {
192
+ const classes = styles ( ) ;
169
193
const [ value , setValue ] = useState < string > ( initialValue as string ) ;
170
194
const [ openDropdown , setOpenDropdown ] = useState ( false ) ;
171
195
const [ hasSubmitted , setHasSubmitted ] = useState ( false ) ;
172
196
const inputRef = useRef < HTMLInputElement > ( null ) ;
197
+ const inputWrapperRef = useRef < HTMLInputElement > ( null ) ;
173
198
const { pending } = useFormStatus ( ) ;
174
199
const { dropdownRef } = useContext ( SearchContext ) ;
175
200
@@ -196,12 +221,15 @@ export function SearchInput({
196
221
}
197
222
198
223
return (
199
- < VStack gap = "0" className = "justify-center" >
224
+ < VStack gap = "0" className = "justify-center items-center " >
200
225
< Focus . ArrowNavigator autoFocus = { autoFocus } >
201
226
< Input
202
- className = { cx ( className ) }
227
+ ref = { inputWrapperRef }
228
+ variant = "surface"
203
229
radius = "large"
204
230
size = "3"
231
+ data-opened = { openDropdown }
232
+ className = { cx ( className , classes . inputWrapper ( ) ) }
205
233
onKeyDown = { ( e : KeyboardEvent < HTMLInputElement > ) => {
206
234
if ( e . key === 'Enter' ) {
207
235
e . preventDefault ( ) ;
@@ -212,9 +240,6 @@ export function SearchInput({
212
240
}
213
241
} }
214
242
>
215
- < Input . Slot className = "mx-1" >
216
- < Icon icon = { IconSearch } size = { 16 } />
217
- </ Input . Slot >
218
243
< Input . Field
219
244
{ ...props }
220
245
ref = { inputRef }
@@ -223,37 +248,48 @@ export function SearchInput({
223
248
value = { value }
224
249
onChange = { handleChange }
225
250
/>
226
- { ( alwaysDisplayActionButtons || ! ! value . length ) && (
227
- < Input . Slot className = "mx-1" >
228
- < IconButton
229
- aria-label = "Clear"
230
- icon = { IconX }
231
- iconColor = "text-icon"
232
- variant = "link"
233
- className = "!ml-0 tablet:ml-2"
234
- onClick = { handleClear }
235
- />
236
- < Tooltip content = "Submit" >
251
+ { value ?. length ? (
252
+ < >
253
+ < Input . Slot className = "" >
254
+ < Tooltip content = "Submit" >
255
+ < IconButton
256
+ type = "submit"
257
+ aria-label = "Submit"
258
+ icon = { IconCheck }
259
+ iconColor = "text-brand"
260
+ variant = "link"
261
+ className = "!ml-0 tablet:ml-2"
262
+ isLoading = { pending }
263
+ onClick = { handleSubmit }
264
+ />
265
+ </ Tooltip >
237
266
< IconButton
238
- type = "submit"
239
- aria-label = "Submit"
240
- icon = { IconCheck }
241
- iconColor = "text-brand"
267
+ aria-label = "Clear"
268
+ icon = { IconX }
269
+ iconColor = "text-gray-11"
242
270
variant = "link"
243
- className = "!ml-0 tablet:ml-2"
244
- isLoading = { pending }
245
- onClick = { handleSubmit }
271
+ className = "m-0"
272
+ onClick = { handleClear }
246
273
/>
247
- </ Tooltip >
274
+ </ Input . Slot >
275
+ </ >
276
+ ) : (
277
+ < Input . Slot >
278
+ < Icon icon = { IconSearch } size = { 16 } />
248
279
</ Input . Slot >
249
280
) }
250
281
</ Input >
251
282
</ Focus . ArrowNavigator >
252
283
< SearchResultDropdown
253
284
ref = { dropdownRef }
285
+ width = { inputWrapperRef . current ?. offsetWidth || 0 }
254
286
searchResult = { searchResult }
255
287
searchValue = { value }
256
288
openDropdown = { openDropdown }
289
+ onSelectItem = { ( ) => {
290
+ setOpenDropdown ( false ) ;
291
+ handleClear ( ) ;
292
+ } }
257
293
onOpenChange = { ( ) => {
258
294
if ( openDropdown ) {
259
295
setHasSubmitted ( false ) ;
@@ -264,9 +300,3 @@ export function SearchInput({
264
300
</ VStack >
265
301
) ;
266
302
}
267
-
268
- const styles = tv ( {
269
- slots : {
270
- dropdownItem : 'hover:bg-border focus:bg-border' ,
271
- } ,
272
- } ) ;
0 commit comments