@@ -11,7 +11,6 @@ import { KeplrWalletManager } from "integrations/Keplr";
11
11
import { getChainFromAddress } from "integrations/utils" ;
12
12
import { useAtom , useAtomValue } from "jotai" ;
13
13
import { useEffect , useState } from "react" ;
14
- import { GoChevronDown } from "react-icons/go" ;
15
14
import { useLocation } from "react-router-dom" ;
16
15
import { twMerge } from "tailwind-merge" ;
17
16
import namadaShieldedIcon from "./assets/namada-shielded.svg" ;
@@ -27,12 +26,10 @@ type AddressOption = {
27
26
iconUrl : string ;
28
27
} ;
29
28
30
- type AddressDropdownProps = {
29
+ type AddressListProps = {
31
30
selectedAddress ?: string ;
32
31
destinationAddress ?: string ;
33
32
className ?: string ;
34
- showAddress ?: boolean ;
35
- onClick ?: ( ) => void ;
36
33
onSelectAddress ?: ( address : string ) => void ;
37
34
} ;
38
35
@@ -42,11 +39,8 @@ export const AddressDropdown = ({
42
39
selectedAddress,
43
40
destinationAddress,
44
41
className = "" ,
45
- showAddress = false ,
46
- onClick,
47
42
onSelectAddress,
48
- } : AddressDropdownProps ) : JSX . Element => {
49
- const [ isOpen , setIsOpen ] = useState ( false ) ;
43
+ } : AddressListProps ) : JSX . Element => {
50
44
const [ keplrAddress , setKeplrAddress ] = useState < string | null > ( null ) ;
51
45
const [ isConnectingKeplr , setIsConnectingKeplr ] = useState ( false ) ;
52
46
const { data : accounts } = useAtomValue ( allDefaultAccountsAtom ) ;
@@ -147,21 +141,7 @@ export const AddressDropdown = ({
147
141
} ) ;
148
142
}
149
143
150
- // Find the selected option
151
- const selectedOption = addressOptions . find (
152
- ( option ) => option . address === selectedAddress
153
- ) ;
154
-
155
- const handleToggle = ( ) : void => {
156
- if ( onClick ) {
157
- onClick ( ) ;
158
- } else if ( addressOptions . length > 1 || ! connectedWallets . keplr ) {
159
- setIsOpen ( ! isOpen ) ;
160
- }
161
- } ;
162
-
163
144
const handleSelectOption = ( option : AddressOption ) : void => {
164
- setIsOpen ( false ) ;
165
145
if ( onSelectAddress ) {
166
146
onSelectAddress ( option . address ) ;
167
147
}
@@ -203,159 +183,90 @@ export const AddressDropdown = ({
203
183
} catch ( error ) {
204
184
console . error ( "Failed to fetch Keplr address after connection:" , error ) ;
205
185
}
206
-
207
- setIsOpen ( false ) ;
208
186
} catch ( error ) {
209
187
console . error ( "Failed to connect to Keplr:" , error ) ;
210
188
} finally {
211
189
setIsConnectingKeplr ( false ) ;
212
190
}
213
191
} ;
214
192
215
- // Close dropdown when clicking outside
216
- useEffect ( ( ) => {
217
- const handleClickOutside = ( event : MouseEvent ) : void => {
218
- const target = event . target as Element ;
219
- if ( ! target . closest ( "[data-dropdown-container]" ) ) {
220
- setIsOpen ( false ) ;
221
- }
222
- } ;
223
-
224
- if ( isOpen ) {
225
- document . addEventListener ( "mousedown" , handleClickOutside ) ;
226
- }
227
-
228
- return ( ) => {
229
- document . removeEventListener ( "mousedown" , handleClickOutside ) ;
230
- } ;
231
- } , [ isOpen ] ) ;
232
-
233
- if ( ! selectedAddress || addressOptions . length === 0 ) return < > </ > ;
234
-
235
- const shouldShowDropdown =
236
- addressOptions . length > 1 || ! connectedWallets . keplr ;
193
+ if ( addressOptions . length === 0 && connectedWallets . keplr ) return < > </ > ;
237
194
238
195
return (
239
- < div className = "relative" data-dropdown-container >
240
- < div
241
- role = "button"
242
- className = { twMerge (
243
- clsx (
244
- "flex justify-between items-center gap-2.5 text-sm text-neutral-500" ,
245
- "font-light text-right transition-colors" ,
246
- {
247
- "hover:text-neutral-400" : Boolean ( onClick ) || shouldShowDropdown ,
248
- "cursor-auto" : ! onClick && ! shouldShowDropdown ,
249
- "cursor-pointer" : Boolean ( onClick ) || shouldShowDropdown ,
250
- } ,
251
- className
252
- )
253
- ) }
254
- onClick = { handleToggle }
255
- >
256
- < div className = "flex items-center gap-2.5 mt-2" >
257
- < img
258
- src = { selectedOption ?. iconUrl || namadaTransparentIcon }
259
- alt = { ( selectedOption ?. walletType || "Namada" ) + " Logo" }
260
- className = "w-7 select-none"
261
- />
262
- { showAddress && selectedOption && (
263
- < div className = "text-xs text-neutral-400" >
264
- { shortenAddress ( selectedOption . address , 10 , 10 ) }
265
- </ div >
266
- ) }
267
- </ div >
268
- { shouldShowDropdown && (
269
- < GoChevronDown
196
+ < div className = { twMerge ( "space-y-1" , className ) } >
197
+ { /* Address Options List */ }
198
+ { addressOptions . map ( ( option ) => {
199
+ const keplr = option . id === "keplr" ;
200
+ const transparent = option . id === "namada-transparent" ;
201
+ const shielded = option . id === "namada-shielded" ;
202
+ const isShieldedTransfer =
203
+ location . pathname !== routes . maspShield &&
204
+ isShieldedAddress ( destinationAddress ?? "" ) ;
205
+ const isShieldingTxn = location . pathname === routes . maspShield ;
206
+ const disabled =
207
+ ( keplr && isShieldedTransfer ) ||
208
+ ( transparent && isShieldedTransfer ) ||
209
+ ( shielded && isShieldingTxn ) ;
210
+ const isSelected = option . address === selectedAddress ;
211
+ if ( disabled ) return null ;
212
+ return (
213
+ < button
214
+ key = { option . id }
215
+ type = "button"
270
216
className = { clsx (
271
- "text-xs text-neutral-400 transition-transform ml-1" ,
272
- isOpen && "rotate-180"
217
+ "w-full p-2 text-left flex items-center gap-3" ,
218
+ "transition-all duration-200" ,
219
+ {
220
+ "opacity-40 cursor-not-allowed" : disabled ,
221
+ }
273
222
) }
223
+ onClick = { ( ) => handleSelectOption ( option ) }
224
+ >
225
+ < div className = "flex-shrink-0" >
226
+ < img
227
+ src = { option . iconUrl }
228
+ alt = { option . label }
229
+ className = "w-6 h-6"
230
+ />
231
+ </ div >
232
+ < div className = "flex-1 min-w-0" >
233
+ < div
234
+ className = { clsx (
235
+ "text-sm truncate" ,
236
+ isSelected ?
237
+ "text-yellow-300 font-medium"
238
+ : "text-neutral-300"
239
+ ) }
240
+ >
241
+ { shortenAddress ( option . address , 8 , 6 ) }
242
+ </ div >
243
+ </ div >
244
+ </ button >
245
+ ) ;
246
+ } ) }
247
+
248
+ { /* Connect Wallet button if Keplr is not connected */ }
249
+ { ! connectedWallets . keplr && (
250
+ < button
251
+ type = "button"
252
+ className = { clsx (
253
+ "w-full p-2 text-left flex items-center gap-3" ,
254
+ "transition-all duration-200" ,
255
+ "text-sm font-medium text-neutral-300" ,
256
+ isConnectingKeplr && "opacity-50 cursor-not-allowed"
257
+ ) }
258
+ onClick = { handleConnectKeplr }
259
+ disabled = { isConnectingKeplr }
260
+ >
261
+ < img
262
+ src = { wallets . keplr . iconUrl }
263
+ alt = "Keplr"
264
+ className = "w-6 h-6 flex-shrink-0 opacity-70"
274
265
/>
275
- ) }
276
- </ div >
277
-
278
- { isOpen && shouldShowDropdown && (
279
- < >
280
- < div
281
- className = "fixed inset-0 z-10"
282
- onClick = { ( ) => setIsOpen ( false ) }
283
- />
284
-
285
- < div className = "absolute right-0 top-full mt-1 z-20 bg-neutral-800 rounded-md border border-neutral-700 shadow-lg min-w-[240px]" >
286
- < ul className = "py-1" >
287
- { addressOptions . map ( ( option ) => {
288
- const keplr = option . id === "keplr" ;
289
- const transparent = option . id === "namada-transparent" ;
290
- const shielded = option . id === "namada-shielded" ;
291
- const isShieldedTransfer =
292
- location . pathname !== routes . maspShield &&
293
- isShieldedAddress ( destinationAddress ?? "" ) ;
294
- const isShieldingTxn = location . pathname === routes . maspShield ;
295
- const disabled =
296
- ( keplr && isShieldedTransfer ) ||
297
- ( transparent && isShieldedTransfer ) ||
298
- ( shielded && isShieldingTxn ) ;
299
- return (
300
- < li key = { option . id } >
301
- < button
302
- disabled = { disabled }
303
- type = "button"
304
- className = { clsx (
305
- "w-full px-4 py-3 text-left flex items-center gap-3" ,
306
- "hover:bg-neutral-700 transition-colors" ,
307
- "text-sm text-white" ,
308
- option . address === selectedAddress && "bg-neutral-700" ,
309
- disabled && "opacity-30 cursor-not-allowed"
310
- ) }
311
- onClick = { ( ) => handleSelectOption ( option ) }
312
- >
313
- < img
314
- src = { option . iconUrl }
315
- alt = { option . label }
316
- className = "w-6 h-6 flex-shrink-0"
317
- />
318
- < div className = "flex-1 min-w-0" >
319
- < div className = "font-medium text-white" >
320
- { option . label }
321
- </ div >
322
- < div className = "text-xs text-neutral-400 truncate" >
323
- { shortenAddress ( option . address , 10 , 10 ) }
324
- </ div >
325
- </ div >
326
- </ button >
327
- </ li >
328
- ) ;
329
- } ) }
330
-
331
- { /* Connect Wallet button if Keplr is not connected */ }
332
- { ! connectedWallets . keplr && (
333
- < li className = "border-t border-neutral-700 mt-1 pt-1" >
334
- < button
335
- type = "button"
336
- className = { clsx (
337
- "w-full px-4 py-3 text-left flex items-center gap-3" ,
338
- "hover:bg-neutral-700 transition-colors" ,
339
- "text-sm font-medium" ,
340
- isConnectingKeplr && "opacity-50 cursor-not-allowed"
341
- ) }
342
- onClick = { handleConnectKeplr }
343
- disabled = { isConnectingKeplr }
344
- >
345
- < img
346
- src = { wallets . keplr . iconUrl }
347
- alt = "Keplr"
348
- className = "w-5 h-5 flex-shrink-0"
349
- />
350
- < div className = "flex-1 ml-1" >
351
- { isConnectingKeplr ? "Connecting..." : "Connect Wallet" }
352
- </ div >
353
- </ button >
354
- </ li >
355
- ) }
356
- </ ul >
266
+ < div className = "flex-1" >
267
+ { isConnectingKeplr ? "Connecting..." : "Connect Wallet" }
357
268
</ div >
358
- </ >
269
+ </ button >
359
270
) }
360
271
</ div >
361
272
) ;
0 commit comments