1
+ import { ConnectWalletList } from '@cardano-foundation/cardano-connect-with-wallet'
2
+ import { NetworkType } from '@cardano-foundation/cardano-connect-with-wallet-core'
1
3
import { useWalletStore } from '../stores/walletStore'
2
4
import { useNavigate } from 'react-router'
5
+ import { useState , useRef , useEffect } from 'react'
3
6
4
7
interface WalletConnectionProps {
5
8
variant ?: 'default' | 'white'
@@ -14,30 +17,53 @@ const WalletConnection = ({
14
17
} : WalletConnectionProps ) => {
15
18
const { isConnected, connect, disconnect } = useWalletStore ( )
16
19
const navigate = useNavigate ( )
20
+ const [ showWalletList , setShowWalletList ] = useState ( false )
21
+ const [ connectionError , setConnectionError ] = useState < string | null > ( null )
22
+ const [ isConnecting , setIsConnecting ] = useState ( false )
23
+ const dropdownRef = useRef < HTMLDivElement > ( null )
17
24
18
- const handleConnect = async ( ) => {
25
+ const onConnectWallet = async ( walletName : string ) => {
26
+ setIsConnecting ( true )
27
+ setConnectionError ( null )
28
+
19
29
try {
20
- const walletNames = [ 'nami' , 'eternl' , 'flint' , 'yoroi' , 'gerowallet' ]
21
- let connected = false
30
+ const success = await connect ( walletName )
22
31
23
- for ( const walletName of walletNames ) {
24
- const success = await connect ( walletName )
25
- if ( success ) {
26
- console . log ( `Connected to ${ walletName } ` )
27
- connected = true
28
- navigate ( '/account' )
29
- break
30
- }
31
- }
32
-
33
- if ( ! connected ) {
34
- console . warn ( 'No compatible wallets found. Please install a supported Cardano wallet.' )
32
+ if ( success ) {
33
+ setShowWalletList ( false )
34
+ navigate ( '/account' )
35
+ } else {
36
+ console . error ( `Failed to connect to ${ walletName } - connect function returned false` )
37
+ setConnectionError ( `Failed to connect to ${ walletName } . Please try again.` )
35
38
}
36
39
} catch ( error ) {
37
- console . error ( 'Failed to connect wallet:' , error )
40
+ console . error ( `Error connecting to ${ walletName } :` , error )
41
+ setConnectionError ( `Error connecting to ${ walletName } : ${ error instanceof Error ? error . message : 'Unknown error' } ` )
42
+ } finally {
43
+ setIsConnecting ( false )
38
44
}
39
45
}
40
46
47
+ // Add error handler for ConnectWalletList
48
+ const onConnectError = ( walletName : string , error : Error ) => {
49
+ console . error ( `ConnectWalletList error for ${ walletName } :` , error )
50
+ setConnectionError ( `Error with ${ walletName } : ${ error . message } ` )
51
+ }
52
+
53
+ useEffect ( ( ) => {
54
+ const handleClickOutside = ( event : MouseEvent ) => {
55
+ if ( dropdownRef . current && ! dropdownRef . current . contains ( event . target as Node ) ) {
56
+ setShowWalletList ( false )
57
+ setConnectionError ( null ) ;
58
+ }
59
+ }
60
+
61
+ document . addEventListener ( 'mousedown' , handleClickOutside )
62
+ return ( ) => {
63
+ document . removeEventListener ( 'mousedown' , handleClickOutside )
64
+ }
65
+ } , [ ] )
66
+
41
67
if ( isConnected ) {
42
68
return (
43
69
< div className = "flex items-center space-x-4" >
@@ -53,14 +79,13 @@ const WalletConnection = ({
53
79
54
80
const buttonClasses = variant === 'white'
55
81
? "flex py-3 px-8 justify-center items-center gap-2.5 rounded-md bg-white text-black font-medium cursor-pointer text-lg md:text-base"
56
- : "flex py-2.5 px-6 justify-center items-center gap-2.5 self-stretch rounded-md border border-white/20 backdrop-blur-sm text-white font-medium z-40 cursor-pointer"
82
+ : "flex py-2.5 px-10 justify-center items-center gap-2.5 self-stretch rounded-md border border-white/20 backdrop-blur-sm text-white font-medium z-40 cursor-pointer"
57
83
58
84
if ( showTitle || showDescription ) {
59
85
return (
60
86
< div className = "flex flex-col items-center justify-center w-full max-w-4xl mx-auto" >
61
87
< div className = "border-2 border-white rounded-3xl p-8 md:p-12 w-full" >
62
88
< div className = "flex items-start gap-4 mb-6" >
63
- { /* Logomark Icon */ }
64
89
< div className = "flex-shrink-0" >
65
90
< img
66
91
src = "/wallet-icon-white.svg"
@@ -84,24 +109,137 @@ const WalletConnection = ({
84
109
</ p >
85
110
) }
86
111
87
- < button
88
- onClick = { handleConnect }
89
- className = "bg-white text-black font-medium py-3 px-8 rounded-lg text-lg cursor-pointer"
90
- >
91
- Connect
92
- </ button >
112
+ < div className = "relative" ref = { dropdownRef } >
113
+ < button
114
+ onClick = { ( ) => setShowWalletList ( ! showWalletList ) }
115
+ className = "bg-white text-black font-medium py-3 px-8 rounded-lg text-lg cursor-pointer"
116
+ disabled = { isConnecting }
117
+ >
118
+ { isConnecting ? 'Connecting...' : 'Connect' }
119
+ </ button >
120
+
121
+ { showWalletList && (
122
+ < div className = "absolute top-full left-0 mt-2 backdrop-blur-sm p-4 z-50 min-w-[200px]" >
123
+ { connectionError && (
124
+ < div className = "mb-3 p-2 bg-red-100 border border-red-300 rounded text-red-700 text-sm" >
125
+ { connectionError }
126
+ </ div >
127
+ ) }
128
+ < ConnectWalletList
129
+ borderRadius = { 15 }
130
+ gap = { 12 }
131
+ primaryColor = "#000000"
132
+ onConnect = { onConnectWallet }
133
+ onConnectError = { onConnectError }
134
+ supportedWallets = { [ 'eternl' , 'yoroi' , 'gerowallet' , 'begin' , 'nufi' , 'lace' , 'vespr' ] }
135
+ showUnavailableWallets = { 0 }
136
+ peerConnectEnabled = { false }
137
+ limitNetwork = { NetworkType . TESTNET }
138
+ customCSS = { `
139
+ font-family: Helvetica Light, sans-serif;
140
+ font-size: 1rem;
141
+ font-weight: 700;
142
+ width: 100%;
143
+ & > span {
144
+ padding: 10px 24px;
145
+ color: #ffffff;
146
+ border: 1px solid rgba(255, 255, 255, 0.2);
147
+ border-radius: 6px;
148
+ margin-bottom: 12px;
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: center;
152
+ gap: 8px;
153
+ background: transparent;
154
+ backdrop-filter: blur(10px);
155
+ transition: all 0.2s ease;
156
+ cursor: pointer;
157
+ }
158
+ & > span:hover {
159
+ background: rgba(255, 255, 255, 0.1);
160
+ border-color: rgba(255, 255, 255, 0.3);
161
+ }
162
+ ` }
163
+ />
164
+ </ div >
165
+ ) }
166
+ </ div >
93
167
</ div >
94
168
</ div >
95
169
)
96
170
}
97
171
98
172
return (
99
- < button
100
- onClick = { handleConnect }
101
- className = { buttonClasses }
102
- >
103
- Connect Wallet
104
- </ button >
173
+ < div className = "relative" ref = { dropdownRef } >
174
+ < button
175
+ onClick = { ( ) => setShowWalletList ( ! showWalletList ) }
176
+ className = { buttonClasses }
177
+ disabled = { isConnecting }
178
+ >
179
+ { isConnecting ? 'Connecting...' : 'Connect Wallet' }
180
+ </ button >
181
+
182
+ { showWalletList && (
183
+ < div className = "absolute top-full left-0 right-0 pt-3 z-50 animate-in slide-in-from-top-2 duration-300" >
184
+ < ConnectWalletList
185
+ borderRadius = { 15 }
186
+ gap = { 12 }
187
+ primaryColor = "#000000"
188
+ onConnect = { onConnectWallet }
189
+ onConnectError = { onConnectError }
190
+ supportedWallets = { [ 'eternl' , 'yoroi' , 'begin' , 'nufi' , 'lace' , 'vespr' ] }
191
+ showUnavailableWallets = { 0 }
192
+ peerConnectEnabled = { false }
193
+ limitNetwork = { NetworkType . TESTNET } // MUST BE CHANGED TO MAINNET to work on mainnet
194
+ customCSS = { `
195
+ font-family: Helvetica Light, sans-serif;
196
+ font-size: 0.875rem;
197
+ font-weight: 700;
198
+ width: 100%;
199
+ & > span {
200
+ padding: 10px 12px;
201
+ color: #ffffff;
202
+ border: 1px solid rgba(255, 255, 255, 0.2);
203
+ border-radius: 6px;
204
+ margin-bottom: 10px;
205
+ display: flex;
206
+ align-items: center;
207
+ justify-content: start;
208
+ gap: 8px;
209
+ background: transparent;
210
+ backdrop-filter: blur(10px);
211
+ transition: all 0.2s ease;
212
+ cursor: pointer;
213
+ opacity: 0;
214
+ transform: translateY(-10px);
215
+ animation: cascadeIn 0.4s ease-out forwards;
216
+ }
217
+ & > span:nth-child(1) { animation-delay: 0.02s; }
218
+ & > span:nth-child(2) { animation-delay: 0.08s; }
219
+ & > span:nth-child(3) { animation-delay: 0.12s; }
220
+ & > span:nth-child(4) { animation-delay: 0.17s; }
221
+ & > span:nth-child(5) { animation-delay: 0.22s; }
222
+ & > span:nth-child(6) { animation-delay: 0.27s; }
223
+ & > span:hover {
224
+ background: rgba(255, 255, 255, 0.1);
225
+ border-color: rgba(255, 255, 255, 0.3);
226
+ transform: translateY(-2px);
227
+ }
228
+ @keyframes cascadeIn {
229
+ from {
230
+ opacity: 0;
231
+ transform: translateY(-10px);
232
+ }
233
+ to {
234
+ opacity: 1;
235
+ transform: translateY(0);
236
+ }
237
+ }
238
+ ` }
239
+ />
240
+ </ div >
241
+ ) }
242
+ </ div >
105
243
)
106
244
}
107
245
0 commit comments