Files
Arkie-Library-Frontend/src/wallet/WalletButton.tsx

121 lines
4.7 KiB
TypeScript
Raw Normal View History

import { Heart, Wallet } from "lucide-react";
2026-06-02 00:32:46 +08:00
import { useEffect, useRef, useState } from "react";
import { Link } from "react-router-dom";
2026-06-02 00:32:46 +08:00
import { useI18n } from "../i18n";
import { useLocalizedPath } from "../useLocalizedPath";
2026-06-02 00:32:46 +08:00
import { shortenAddress, useWallet } from "./WalletProvider";
export function WalletButton({
compact = false,
onOpenLogin,
}: {
compact?: boolean;
onOpenLogin?: () => void;
}) {
2026-06-02 00:32:46 +08:00
const { t } = useI18n();
const lp = useLocalizedPath();
2026-06-02 00:32:46 +08:00
const wallet = useWallet();
const [open, setOpen] = useState(false);
const rootRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!open) return;
const closeOnOutside = (event: MouseEvent | TouchEvent) => {
if (!rootRef.current?.contains(event.target as Node)) setOpen(false);
};
const closeOnEscape = (event: KeyboardEvent) => {
if (event.key === "Escape") setOpen(false);
};
document.addEventListener("mousedown", closeOnOutside);
document.addEventListener("touchstart", closeOnOutside);
window.addEventListener("keydown", closeOnEscape);
return () => {
document.removeEventListener("mousedown", closeOnOutside);
document.removeEventListener("touchstart", closeOnOutside);
window.removeEventListener("keydown", closeOnEscape);
};
}, [open]);
if (wallet.status === "loggedIn" && wallet.address) {
if (compact) {
return (
<div className="grid w-full gap-2">
<div className="inline-flex h-10 w-full items-center justify-center rounded-full border border-ark-gold/45 bg-ark-gold/10 px-3 text-sm font-semibold text-ark-gold2">
<span className="mr-2 h-2 w-2 rounded-full bg-emerald-400" />
{shortenAddress(wallet.address)}
</div>
<button
type="button"
onClick={() => wallet.logout()}
className="h-10 w-full rounded-full border border-red-400/35 bg-red-500/10 px-4 text-sm font-semibold text-red-200 transition hover:bg-red-500/15"
>
{t("walletDisconnect")}
</button>
</div>
);
}
2026-06-02 00:32:46 +08:00
return (
<div ref={rootRef} className="relative">
<button
type="button"
onClick={() => setOpen((value) => !value)}
className={[
"inline-flex h-10 items-center justify-center rounded-full border border-ark-gold/45 bg-ark-gold/10 px-3 text-sm font-semibold text-ark-gold2 outline-none transition hover:bg-ark-gold/15 focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg",
compact ? "w-full" : "",
].join(" ")}
aria-label={t("walletConnectedAs")}
aria-expanded={open}
>
<span className="mr-2 h-2 w-2 rounded-full bg-emerald-400" />
{shortenAddress(wallet.address)}
</button>
{open ? (
<div className="absolute right-0 top-[calc(100%+0.5rem)] z-50 w-52 rounded-2xl border border-white/10 bg-[#1c1c21]/95 p-2 shadow-2xl shadow-black/70 ring-1 ring-ark-line/80 backdrop-blur-xl">
<div className="truncate px-3 py-2 text-xs text-neutral-400">
{wallet.address}
</div>
<Link
to={lp("/favorites")}
onClick={() => setOpen(false)}
className="flex w-full items-center gap-2 rounded-xl px-3 py-2 text-left text-sm font-medium text-neutral-100 transition hover:bg-ark-gold/10 hover:text-ark-gold"
>
<Heart size={16} strokeWidth={2} />
{t("favorites")}
</Link>
2026-06-02 00:32:46 +08:00
<button
type="button"
onClick={() => {
setOpen(false);
wallet.logout();
}}
className="w-full rounded-xl px-3 py-2 text-left text-sm font-medium text-red-200 transition hover:bg-red-500/10"
>
{t("walletDisconnect")}
</button>
</div>
) : null}
</div>
);
}
return (
<button
type="button"
onClick={() => {
onOpenLogin?.();
wallet.openLoginModal();
}}
2026-06-02 00:32:46 +08:00
className={[
"inline-flex h-10 items-center justify-center gap-2 rounded-full border border-ark-gold bg-ark-gold px-4 text-sm font-bold text-black outline-none transition hover:bg-ark-gold2 focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg",
compact ? "w-full" : "min-w-[124px] shrink-0 whitespace-nowrap",
2026-06-02 00:32:46 +08:00
].join(" ")}
>
<Wallet className="h-4 w-4" strokeWidth={2.5} aria-hidden />
<span>
{wallet.status === "loading" ? t("loading") : t("walletConnect")}
</span>
2026-06-02 00:32:46 +08:00
</button>
);
}