@@ -14,6 +14,7 @@ import {
14
14
VStack ,
15
15
useBreakpoints ,
16
16
Box ,
17
+ Text ,
17
18
} from '@fuels/ui' ;
18
19
import { IconCheck , IconSearch , IconX } from '@tabler/icons-react' ;
19
20
import NextLink from 'next/link' ;
@@ -34,6 +35,7 @@ type SearchDropdownProps = {
34
35
searchValue : string ;
35
36
width : number ;
36
37
onSelectItem : ( ) => void ;
38
+ isExpanded ?: boolean ;
37
39
} ;
38
40
39
41
const SearchResultDropdown = forwardRef < HTMLDivElement , SearchDropdownProps > (
@@ -45,6 +47,7 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
45
47
onOpenChange,
46
48
width,
47
49
onSelectItem,
50
+ isExpanded,
48
51
} ,
49
52
ref ,
50
53
) => {
@@ -53,15 +56,25 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
53
56
const trimL = isMobile ? 15 : 20 ;
54
57
const trimR = isMobile ? 13 : 18 ;
55
58
59
+ const hasResult =
60
+ searchResult ?. account ||
61
+ searchResult ?. block ||
62
+ searchResult ?. contract ||
63
+ searchResult ?. transaction ;
64
+
56
65
return (
57
66
< Dropdown open = { openDropdown } onOpenChange = { onOpenChange } >
58
67
< Dropdown . Trigger >
59
68
< Box className = "w-full" > </ Box >
60
69
</ Dropdown . Trigger >
61
70
< Dropdown . Content
62
71
ref = { ref }
63
- className = { cx ( classes . dropdownContent ( ) , classes . searchSize ( ) ) }
72
+ className = { cx (
73
+ classes . dropdownContent ( isExpanded ) ,
74
+ classes . searchSize ( ) ,
75
+ ) }
64
76
style = { { width : width - 0.5 } }
77
+ data-expanded = { isExpanded }
65
78
>
66
79
{ ! searchResult && (
67
80
< >
@@ -70,101 +83,116 @@ const SearchResultDropdown = forwardRef<HTMLDivElement, SearchDropdownProps>(
70
83
</ Dropdown . Item >
71
84
</ >
72
85
) }
73
- { searchResult ?. account && (
86
+ { hasResult ? (
74
87
< >
75
- < Dropdown . Label > Account</ Dropdown . Label >
76
- < Dropdown . Item className = { classes . dropdownItem ( ) } >
77
- < Link
78
- as = { NextLink }
79
- href = { Routes . accountAssets ( searchResult . account . address ! ) }
80
- className = "text-color"
81
- onClick = { onSelectItem }
82
- >
83
- { shortAddress (
84
- searchResult . account . address || '' ,
85
- trimL ,
86
- trimR ,
87
- ) }
88
- </ Link >
89
- </ Dropdown . Item >
90
- < Dropdown . Separator />
91
- < Dropdown . Label > Recent Transactions</ Dropdown . Label >
92
- { searchResult . account . transactions ?. map ( ( transaction ) => {
93
- return (
94
- < Dropdown . Item
95
- key = { transaction ?. id }
96
- className = { classes . dropdownItem ( ) }
97
- >
88
+ { searchResult ?. account && (
89
+ < >
90
+ < Dropdown . Label > Account</ Dropdown . Label >
91
+ < Dropdown . Item className = { classes . dropdownItem ( ) } >
98
92
< Link
99
93
as = { NextLink }
100
- href = { Routes . txSimple ( transaction ! . id ! ) }
94
+ href = { Routes . accountAssets ( searchResult . account . address ! ) }
101
95
className = "text-color"
102
96
onClick = { onSelectItem }
103
97
>
104
- { shortAddress ( transaction ?. id || '' , trimL , trimR ) }
98
+ { shortAddress (
99
+ searchResult . account . address || '' ,
100
+ trimL ,
101
+ trimR ,
102
+ ) }
105
103
</ Link >
106
104
</ Dropdown . Item >
107
- ) ;
108
- } ) }
109
- </ >
110
- ) }
111
- { searchResult ?. block && (
112
- < >
113
- < Dropdown . Label > Block</ Dropdown . Label >
114
- < Dropdown . Item className = { classes . dropdownItem ( ) } >
115
- < Link
116
- as = { NextLink }
117
- href = { Routes . blockSimple ( searchResult . block . id ! ) }
118
- className = "text-color"
119
- onClick = { onSelectItem }
120
- >
121
- { shortAddress ( searchResult . block . id || '' , trimL , trimR ) }
122
- </ Link >
123
- </ Dropdown . Item >
124
- < Dropdown . Item className = { classes . dropdownItem ( ) } >
125
- < Link
126
- as = { NextLink }
127
- href = { Routes . blockSimple ( searchResult . block . height ! ) }
128
- className = "text-color"
129
- onClick = { onSelectItem }
130
- >
131
- { searchResult . block . height }
132
- </ Link >
133
- </ Dropdown . Item >
134
- </ >
135
- ) }
136
- { searchResult ?. contract && (
137
- < >
138
- < Dropdown . Label > Contract</ Dropdown . Label >
139
- < Dropdown . Item className = { classes . dropdownItem ( ) } >
140
- < Link
141
- as = { NextLink }
142
- href = { Routes . contractAssets ( searchResult . contract . id ! ) }
143
- className = "text-color"
144
- onClick = { onSelectItem }
145
- >
146
- { shortAddress ( searchResult . contract . id || '' , trimL , trimR ) }
147
- </ Link >
148
- </ Dropdown . Item >
105
+ < Dropdown . Separator />
106
+ < Dropdown . Label > Recent Transactions</ Dropdown . Label >
107
+ { searchResult . account . transactions ?. map ( ( transaction ) => {
108
+ return (
109
+ < Dropdown . Item
110
+ key = { transaction ?. id }
111
+ className = { classes . dropdownItem ( ) }
112
+ >
113
+ < Link
114
+ as = { NextLink }
115
+ href = { Routes . txSimple ( transaction ! . id ! ) }
116
+ className = "text-color"
117
+ onClick = { onSelectItem }
118
+ >
119
+ { shortAddress ( transaction ?. id || '' , trimL , trimR ) }
120
+ </ Link >
121
+ </ Dropdown . Item >
122
+ ) ;
123
+ } ) }
124
+ </ >
125
+ ) }
126
+ { searchResult ?. block && (
127
+ < >
128
+ < Dropdown . Label > Block</ Dropdown . Label >
129
+ < Dropdown . Item className = { classes . dropdownItem ( ) } >
130
+ < Link
131
+ as = { NextLink }
132
+ href = { Routes . blockSimple ( searchResult . block . id ! ) }
133
+ className = "text-color"
134
+ onClick = { onSelectItem }
135
+ >
136
+ { shortAddress ( searchResult . block . id || '' , trimL , trimR ) }
137
+ </ Link >
138
+ </ Dropdown . Item >
139
+ < Dropdown . Item className = { classes . dropdownItem ( ) } >
140
+ < Link
141
+ as = { NextLink }
142
+ href = { Routes . blockSimple ( searchResult . block . height ! ) }
143
+ className = "text-color"
144
+ onClick = { onSelectItem }
145
+ >
146
+ { searchResult . block . height }
147
+ </ Link >
148
+ </ Dropdown . Item >
149
+ </ >
150
+ ) }
151
+ { searchResult ?. contract && (
152
+ < >
153
+ < Dropdown . Label > Contract</ Dropdown . Label >
154
+ < Dropdown . Item className = { classes . dropdownItem ( ) } >
155
+ < Link
156
+ as = { NextLink }
157
+ href = { Routes . contractAssets ( searchResult . contract . id ! ) }
158
+ className = "text-color"
159
+ onClick = { onSelectItem }
160
+ >
161
+ { shortAddress (
162
+ searchResult . contract . id || '' ,
163
+ trimL ,
164
+ trimR ,
165
+ ) }
166
+ </ Link >
167
+ </ Dropdown . Item >
168
+ </ >
169
+ ) }
170
+ { searchResult ?. transaction && (
171
+ < >
172
+ < Dropdown . Label > Transaction</ Dropdown . Label >
173
+ < Dropdown . Item className = { classes . dropdownItem ( ) } >
174
+ < Link
175
+ as = { NextLink }
176
+ href = { Routes . txSimple ( searchResult . transaction . id ! ) }
177
+ className = "text-color"
178
+ onClick = { onSelectItem }
179
+ >
180
+ { shortAddress (
181
+ searchResult . transaction . id || '' ,
182
+ trimL ,
183
+ trimR ,
184
+ ) }
185
+ </ Link >
186
+ </ Dropdown . Item >
187
+ </ >
188
+ ) }
149
189
</ >
150
- ) }
151
- { searchResult ?. transaction && (
190
+ ) : (
152
191
< >
153
- < Dropdown . Label > Transaction</ Dropdown . Label >
154
- < Dropdown . Item className = { classes . dropdownItem ( ) } >
155
- < Link
156
- as = { NextLink }
157
- href = { Routes . txSimple ( searchResult . transaction . id ! ) }
158
- className = "text-color"
159
- onClick = { onSelectItem }
160
- >
161
- { shortAddress (
162
- searchResult . transaction . id || '' ,
163
- trimL ,
164
- trimR ,
165
- ) }
166
- </ Link >
167
- </ Dropdown . Item >
192
+ < Dropdown . Label > No instances found for:</ Dropdown . Label >
193
+ < Text className = "px-3 text-sm pb-1" >
194
+ "{ shortAddress ( searchValue , trimL , trimR ) } "
195
+ </ Text >
168
196
</ >
169
197
) }
170
198
</ Dropdown . Content >
@@ -178,6 +206,7 @@ type SearchInputProps = BaseProps<InputProps & InputFieldProps> & {
178
206
onClear ?: ( value : string ) => void ;
179
207
searchResult ?: Maybe < SearchResult > ;
180
208
alwaysDisplayActionButtons ?: boolean ;
209
+ expandOnFocus ?: boolean ;
181
210
} ;
182
211
183
212
export function SearchInput ( {
@@ -187,12 +216,14 @@ export function SearchInput({
187
216
autoFocus,
188
217
placeholder = 'Search here...' ,
189
218
searchResult,
219
+ expandOnFocus,
190
220
...props
191
221
} : SearchInputProps ) {
192
222
const classes = styles ( ) ;
193
223
const [ value , setValue ] = useState < string > ( initialValue as string ) ;
194
224
const [ openDropdown , setOpenDropdown ] = useState ( false ) ;
195
225
const [ hasSubmitted , setHasSubmitted ] = useState ( false ) ;
226
+ const [ isExpanded , setIsExpanded ] = useState ( false ) ;
196
227
const inputRef = useRef < HTMLInputElement > ( null ) ;
197
228
const inputWrapperRef = useRef < HTMLInputElement > ( null ) ;
198
229
const { pending } = useFormStatus ( ) ;
@@ -217,11 +248,21 @@ export function SearchInput({
217
248
setValue ( '' ) ;
218
249
setHasSubmitted ( false ) ;
219
250
onClear ?.( value ) ;
220
- inputRef . current ?. focus ( ) ;
251
+ if ( isExpanded ) {
252
+ setIsExpanded ( false ) ;
253
+ } else {
254
+ inputRef . current ?. focus ( ) ;
255
+ }
256
+ }
257
+
258
+ function expandOnFocusHandler ( ) {
259
+ if ( expandOnFocus ) {
260
+ setIsExpanded ( true ) ;
261
+ }
221
262
}
222
263
223
264
return (
224
- < VStack gap = "0" className = "justify-center items-center" >
265
+ < VStack gap = "0" className = { classes . searchBox ( ) } data-expanded = { isExpanded } >
225
266
< Focus . ArrowNavigator autoFocus = { autoFocus } >
226
267
< Input
227
268
ref = { inputWrapperRef }
@@ -230,6 +271,7 @@ export function SearchInput({
230
271
size = "3"
231
272
data-opened = { openDropdown }
232
273
className = { cx ( className , classes . inputWrapper ( ) ) }
274
+ onFocus = { expandOnFocusHandler }
233
275
onKeyDown = { ( e : KeyboardEvent < HTMLInputElement > ) => {
234
276
if ( e . key === 'Enter' ) {
235
277
e . preventDefault ( ) ;
@@ -248,21 +290,23 @@ export function SearchInput({
248
290
value = { value }
249
291
onChange = { handleChange }
250
292
/>
251
- { value ?. length ? (
293
+ { isExpanded || value ?. length ? (
252
294
< >
253
295
< 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 >
296
+ { ! ! value ?. length && (
297
+ < Tooltip content = "Submit" >
298
+ < IconButton
299
+ type = "submit"
300
+ aria-label = "Submit"
301
+ icon = { IconCheck }
302
+ iconColor = "text-brand"
303
+ variant = "link"
304
+ className = "!ml-0 tablet:ml-2"
305
+ isLoading = { pending }
306
+ onClick = { handleSubmit }
307
+ />
308
+ </ Tooltip >
309
+ ) }
266
310
< IconButton
267
311
aria-label = "Clear"
268
312
icon = { IconX }
@@ -296,6 +340,7 @@ export function SearchInput({
296
340
}
297
341
setOpenDropdown ( ! openDropdown ) ;
298
342
} }
343
+ isExpanded = { isExpanded }
299
344
/>
300
345
</ VStack >
301
346
) ;
0 commit comments