Tx Status
Install this component.
Confirmed0x4e3a37…b6f4f3
Controls
Source
"use client"
import * as React from "react"
import {
CheckCircle2Icon,
ExternalLinkIcon,
Loader2Icon,
XCircleIcon,
} from "lucide-react"
import { cn } from "@/lib/utils"
type TxStatusKind = "pending" | "confirmed" | "failed"
const statusConfig: Record<
TxStatusKind,
{
icon: React.ComponentType<{ className?: string }>
label: string
tone: string
}
> = {
pending: {
icon: Loader2Icon,
label: "Pending",
tone: "text-muted-foreground [&>svg]:animate-spin",
},
confirmed: {
icon: CheckCircle2Icon,
label: "Confirmed",
tone: "text-emerald-600 dark:text-emerald-400",
},
failed: {
icon: XCircleIcon,
label: "Failed",
tone: "text-destructive",
},
}
function truncateHash(hash: string, start = 8, end = 6) {
if (hash.length <= start + end + 1) return hash
return `${hash.slice(0, start)}…${hash.slice(-end)}`
}
function TxStatus({
status,
hash,
label,
explorerUrl,
href,
className,
...props
}: React.HTMLAttributes<HTMLDivElement> & {
status: TxStatusKind
hash: string
label?: React.ReactNode
explorerUrl?: string
href?: string
}) {
const config = statusConfig[status]
const Icon = config.icon
const finalHref =
href ??
(explorerUrl
? `${explorerUrl.replace(/\/$/, "")}/tx/${hash}`
: undefined)
return (
<div
data-slot="tx-status"
data-status={status}
className={cn(
"inline-flex items-center gap-2 rounded-md border bg-card px-3 py-2 text-sm shadow-xs",
className
)}
{...props}
>
<span className={cn("inline-flex items-center gap-1.5", config.tone)}>
<Icon className="size-4" />
<span className="font-medium">{label ?? config.label}</span>
</span>
<span aria-hidden="true" className="text-muted-foreground">
·
</span>
{finalHref ? (
<a
href={finalHref}
target="_blank"
rel="noopener noreferrer"
title={hash}
className="inline-flex items-center gap-1 font-mono text-xs text-muted-foreground tabular-nums hover:text-foreground hover:underline underline-offset-4"
>
{truncateHash(hash)}
<ExternalLinkIcon className="size-3" />
</a>
) : (
<span
title={hash}
className="font-mono text-xs text-muted-foreground tabular-nums"
>
{truncateHash(hash)}
</span>
)}
</div>
)
}
export { TxStatus, truncateHash }