forked from FlowwStar/FlowStar
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconnect-wallet-button.tsx
More file actions
131 lines (125 loc) · 4.42 KB
/
Copy pathconnect-wallet-button.tsx
File metadata and controls
131 lines (125 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
'use client'
import { useState } from 'react'
import { Check, Copy, LogOut, Loader2, Wallet } from 'lucide-react'
import { Button } from '@/components/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { useWallet } from '@/hooks/use-wallet'
import { WALLET_OPTIONS } from '@/components/providers/wallet-provider'
import { shortenAddress } from '@/lib/stream-utils'
import { cn } from '@/lib/utils'
export function ConnectWalletButton({ className }: { className?: string }) {
const { address, isConnected, connecting, connect, disconnect, walletId } =
useWallet()
const [open, setOpen] = useState(false)
const [copied, setCopied] = useState(false)
const [pendingId, setPendingId] = useState<string | null>(null)
async function handleConnect(id: string) {
setPendingId(id)
try {
await connect(id)
setOpen(false)
} finally {
setPendingId(null)
}
}
function copyAddress() {
if (!address) return
navigator.clipboard.writeText(address)
setCopied(true)
setTimeout(() => setCopied(false), 1500)
}
if (isConnected && address) {
const activeWallet = WALLET_OPTIONS.find((w) => w.id === walletId)
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="secondary" className={cn('gap-2', className)}>
<span className="size-2 rounded-full bg-primary" aria-hidden />
<span className="font-mono">{shortenAddress(address)}</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56">
<div className="px-2 py-1.5">
<p className="text-xs text-muted-foreground">
Connected with {activeWallet?.name ?? 'wallet'}
</p>
<p className="truncate font-mono text-sm">{shortenAddress(address, 8)}</p>
</div>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={copyAddress}>
{copied ? (
<Check className="size-4 text-primary" />
) : (
<Copy className="size-4" />
)}
{copied ? 'Copied' : 'Copy address'}
</DropdownMenuItem>
<DropdownMenuItem onClick={disconnect} variant="destructive">
<LogOut className="size-4" />
Disconnect
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button className={cn('gap-2', className)}>
<Wallet className="size-4" />
Connect wallet
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Connect a wallet</DialogTitle>
<DialogDescription>
Choose a Stellar wallet to continue. You'll sign transactions
from your wallet — FlowStar never holds your keys.
</DialogDescription>
</DialogHeader>
<div className="grid gap-2 pt-2">
{WALLET_OPTIONS.map((wallet) => {
const isPending = connecting && pendingId === wallet.id
return (
<button
key={wallet.id}
type="button"
disabled={connecting}
onClick={() => handleConnect(wallet.id)}
className="flex items-center gap-3 rounded-lg border border-border bg-secondary/40 p-3 text-left transition-colors hover:bg-secondary disabled:opacity-60"
>
<span className="flex size-9 items-center justify-center rounded-md bg-background font-semibold text-primary">
{wallet.name.charAt(0)}
</span>
<span className="flex-1">
<span className="block text-sm font-medium">{wallet.name}</span>
<span className="block text-xs text-muted-foreground">
{wallet.detail}
</span>
</span>
{isPending && (
<Loader2 className="size-4 animate-spin text-muted-foreground" />
)}
</button>
)
})}
</div>
</DialogContent>
</Dialog>
)
}