Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions components/ui/murphy/Txn-Feedback/inline-txn-status.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"use client";

import { CheckCircle, XCircle, Loader2, Clock } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import { TransactionStatus } from "@/types/transaction";

interface InlineTxnStatusProps {
status: TransactionStatus["status"];
size?: "sm" | "md" | "lg";
showText?: boolean;
className?: string;
}

export function InlineTxnStatus({
status,
size = "md",
showText = true,
className,
}: InlineTxnStatusProps) {
const getStatusConfig = () => {
switch (status) {
case "success":
return {
icon: CheckCircle,
text: "Success",
variant: "default" as const,
className:
"bg-green-100 text-green-800 border border-green-200 dark:bg-green-900 dark:text-green-100 dark:border-green-700",
};
case "error":
return {
icon: XCircle,
text: "Failed",
variant: "destructive" as const,
className:
"bg-red-100 text-red-800 border border-red-200 dark:bg-red-900 dark:text-red-100 dark:border-red-700",
};
case "preparing":
case "signing":
case "sending":
case "confirming":
return {
icon: Loader2,
text: "Processing",
variant: "secondary" as const,
className:
"bg-blue-100 text-blue-800 border border-blue-200 dark:bg-blue-900 dark:text-blue-100 dark:border-blue-700",
animate: true,
};
default:
return {
icon: Clock,
text: "Pending",
variant: "outline" as const,
className:
"bg-gray-100 text-gray-800 border border-gray-200 dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700",
};
}
};

const config = getStatusConfig();
const Icon = config.icon;

const iconSize = {
sm: "w-3 h-3",
md: "w-4 h-4",
lg: "w-5 h-5",
}[size];

const textSize = {
sm: "text-xs",
md: "text-sm",
lg: "text-base",
}[size];

return (
<Badge
variant={config.variant}
className={cn(
"inline-flex items-center gap-1.5",
config.className,
className
)}
>
<Icon className={cn(iconSize, config.animate && "animate-spin")} />
{showText && <span className={textSize}>{config.text}</span>}
</Badge>
);
}
6 changes: 4 additions & 2 deletions components/ui/murphy/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import CandyMachineForm from "./candy-machine-form";
import CoreCandyMachineForm from "./core-candy-machine-form";
import BubblegumLegacyForm from "./bubblegum-legacy-form";
import ImprovedCNFTManager from "./improved-cnft-manager";
import CompressedNFTViewer from "./compressed-nft-viewer"
import CompressedNFTViewer from "./compressed-nft-viewer";
import { CreateMerkleTree } from "./create-merkleTree-form";
import { TokenList } from "./token-list";
import { StakeForm } from "./stake-token-form";
Expand All @@ -37,6 +37,7 @@ import { CoreAssetLaunchpad } from "./core-asset-launchpad";
import { HydraFanoutForm } from "./hydra-fanout-form";
import { MPLHybridForm } from "./mpl-hybrid-form";
import { TokenMetadataViewer } from "./token-metadata-viewer";
import { InlineTxnStatus } from "./Txn-Feedback/inline-txn-status";

export {
ConnectWalletButton,
Expand Down Expand Up @@ -78,5 +79,6 @@ export {
TMLaunchpadForm,
HydraFanoutForm,
MPLHybridForm,
TokenMetadataViewer
TokenMetadataViewer,
InlineTxnStatus,
};
178 changes: 178 additions & 0 deletions content/docs/onchainkit/Txn-Feedback/inline-txn-status.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
---
title: Inline Transaction Status
description: Small status indicators for transaction states in lists and UIs
icon: Activity
---

<PreviewComponent name={"Inline Transaction Status"} v0JsonFileName={"inline-txn-status"}>
<div className="w-full space-y-6 bg-white text-black dark:bg-black dark:text-white p-4 rounded-lg border border-gray-200 dark:border-gray-700">

<div className="space-y-3">
<h4 className="font-medium">Different Status States</h4>
<div className="flex flex-wrap gap-3">
<InlineTxnStatus status="success" />
<InlineTxnStatus status="error" />
<InlineTxnStatus status="confirming" />
<InlineTxnStatus status="idle" />
</div>
</div>

<div className="space-y-3">
<h4 className="font-medium">Different Sizes</h4>
<div className="flex flex-wrap items-center gap-3">
<InlineTxnStatus status="success" size="sm" />
<InlineTxnStatus status="success" size="md" />
<InlineTxnStatus status="success" size="lg" />
</div>
</div>

<div className="space-y-3">
<h4 className="font-medium">Icon Only</h4>
<div className="flex flex-wrap gap-3">
<InlineTxnStatus status="success" showText={false} />
<InlineTxnStatus status="error" showText={false} />
<InlineTxnStatus status="confirming" showText={false} />
</div>
</div>

</div>
</PreviewComponent>

## Installation

<Steps>
<Step>
Install Inline Transaction Status
<InstallationCommands
packageUrl={`${process.env.NEXT_PUBLIC_BASE_URL}/r/inline-txn-status.json`}
/>
</Step>

</Steps>

## Basic Usage

```tsx
"use client";
import { InlineTxnStatus } from "@/components/ui/murphy/Txn-Feedback/inline-txn-status";

export default function MyPage() {
return (
<div className="space-y-4 p-6">
<InlineTxnStatus status="success" size="sm" />
<InlineTxnStatus status="confirming" size="sm" />
<InlineTxnStatus status="error" size="sm" />
</div>
);
}
```

## Props

<TypeTable
type={{
status: {
description: "Current transaction status",
type: "'idle' | 'preparing' | 'signing' | 'sending' | 'confirming' | 'success' | 'error'",
default: "required",
},
size: {
description: "Size of the status indicator",
type: "'sm' | 'md' | 'lg'",
default: "'md'",
},
showText: {
description: "Whether to show status text alongside icon",
type: "boolean",
default: "true",
},
className: {
description: "Additional CSS classes",
type: "string",
default: "undefined",
},
}}
/>

## Status States

### Success State

- **Icon**: CheckCircle (green)
- **Text**: "Success"
- **Use**: Completed transactions
- **Color**: Green theme

### Error State

- **Icon**: XCircle (red)
- **Text**: "Failed"
- **Use**: Failed transactions
- **Color**: Red theme

### Processing States

- **Icon**: Loader2 (blue, animated)
- **Text**: "Processing"
- **Use**: preparing, signing, sending, confirming
- **Color**: Blue theme
- **Animation**: Spinning loader

### Idle State

- **Icon**: Clock (gray)
- **Text**: "Pending"
- **Use**: Queued or idle transactions
- **Color**: Gray theme

## Size Variations

### Small (sm)

- Icon: 12px (w-3 h-3)
- Text: text-xs
- Use: Table cells, compact lists

### Medium (md) - Default

- Icon: 16px (w-4 h-4)
- Text: text-sm
- Use: General purpose, cards

### Large (lg)

- Icon: 20px (w-5 h-5)
- Text: text-base
- Use: Prominent displays, headers

## Customization

### Custom Colors

```tsx
// Custom status colors via CSS classes
<InlineTxnStatus
status="success"
className="bg-emerald-100 text-emerald-800 border-emerald-200"
/>
```

### Custom Icons

```tsx
// You can extend the component to use custom icons
const CustomInlineStatus = ({ status, customIcon }) => {
return (
<Badge className="inline-flex items-center gap-1.5">
{customIcon || <DefaultIcon />}
<span>Custom Status</span>
</Badge>
);
};
```

### Responsive Sizing

```tsx
<InlineTxnStatus status="success" className="text-xs md:text-sm" size="sm" />
```
3 changes: 2 additions & 1 deletion content/docs/onchainkit/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"Metaplex",
"Meteora-DBC",
"ZK-Compression",
"Jupiter-Recurring"
"Jupiter-Recurring",
"Txn-Feedback"
]
}
18 changes: 18 additions & 0 deletions public/r/inline-txn-status.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "inline-txn-status",
"type": "registry:block",
"title": "Inline icon or badge to show transaction status (loading, success, error).",
"dependencies": [
"lucide-react"
],
"registryDependencies": [],
"files": [
{
"path": "components/ui/murphy/Txn-Feedback/inline-txn-status.tsx",
"content": "\"use client\";\r\n\r\nimport { CheckCircle, XCircle, Loader2, Clock } from \"lucide-react\";\r\nimport { Badge } from \"@/components/ui/badge\";\r\nimport { cn } from \"@/lib/utils\";\r\nimport { TransactionStatus } from \"@/types/transaction\";\r\n\r\ninterface InlineTxnStatusProps {\r\n status: TransactionStatus[\"status\"];\r\n size?: \"sm\" | \"md\" | \"lg\";\r\n showText?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport function InlineTxnStatus({\r\n status,\r\n size = \"md\",\r\n showText = true,\r\n className,\r\n}: InlineTxnStatusProps) {\r\n const getStatusConfig = () => {\r\n switch (status) {\r\n case \"success\":\r\n return {\r\n icon: CheckCircle,\r\n text: \"Success\",\r\n variant: \"default\" as const,\r\n className:\r\n \"bg-green-100 text-green-800 border border-green-200 dark:bg-green-900 dark:text-green-100 dark:border-green-700\",\r\n };\r\n case \"error\":\r\n return {\r\n icon: XCircle,\r\n text: \"Failed\",\r\n variant: \"destructive\" as const,\r\n className:\r\n \"bg-red-100 text-red-800 border border-red-200 dark:bg-red-900 dark:text-red-100 dark:border-red-700\",\r\n };\r\n case \"preparing\":\r\n case \"signing\":\r\n case \"sending\":\r\n case \"confirming\":\r\n return {\r\n icon: Loader2,\r\n text: \"Processing\",\r\n variant: \"secondary\" as const,\r\n className:\r\n \"bg-blue-100 text-blue-800 border border-blue-200 dark:bg-blue-900 dark:text-blue-100 dark:border-blue-700\",\r\n animate: true,\r\n };\r\n default:\r\n return {\r\n icon: Clock,\r\n text: \"Pending\",\r\n variant: \"outline\" as const,\r\n className:\r\n \"bg-gray-100 text-gray-800 border border-gray-200 dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700\",\r\n };\r\n }\r\n };\r\n\r\n const config = getStatusConfig();\r\n const Icon = config.icon;\r\n\r\n const iconSize = {\r\n sm: \"w-3 h-3\",\r\n md: \"w-4 h-4\",\r\n lg: \"w-5 h-5\",\r\n }[size];\r\n\r\n const textSize = {\r\n sm: \"text-xs\",\r\n md: \"text-sm\",\r\n lg: \"text-base\",\r\n }[size];\r\n\r\n return (\r\n <Badge\r\n variant={config.variant}\r\n className={cn(\r\n \"inline-flex items-center gap-1.5\",\r\n config.className,\r\n className\r\n )}\r\n >\r\n <Icon className={cn(iconSize, config.animate && \"animate-spin\")} />\r\n {showText && <span className={textSize}>{config.text}</span>}\r\n </Badge>\r\n );\r\n}\r\n",
"type": "registry:file",
"target": "components/ui/murphy/Txn-Feedback/inline-txn-status.tsx"
}
]
}
16 changes: 16 additions & 0 deletions registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,22 @@
}
]
},
{
"name": "inline-txn-status",
"type": "registry:block",
"title": "Inline icon or badge to show transaction status (loading, success, error).",
"registryDependencies": [],
"dependencies": [
"lucide-react"
],
"files": [
{
"path": "components/ui/murphy/Txn-Feedback/inline-txn-status.tsx",
"type": "registry:file",
"target": "components/ui/murphy/Txn-Feedback/inline-txn-status.tsx"
}
]
},
{
"name": "mint-cnft-form",
"type": "registry:block",
Expand Down
14 changes: 14 additions & 0 deletions registry/components/inline-txn-status.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "inline-txn-status",
"type": "registry:block",
"title": "Inline icon or badge to show transaction status (loading, success, error).",
"registryDependencies": [],
"dependencies": ["lucide-react"],
"files": [
{
"path": "components/ui/murphy/Txn-Feedback/inline-txn-status.tsx",
"type": "registry:file",
"target": "components/ui/murphy/Txn-Feedback/inline-txn-status.tsx"
}
]
}
27 changes: 27 additions & 0 deletions types/transaction/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export interface TransactionStatus {
status:
| "idle"
| "preparing"
| "signing"
| "sending"
| "confirming"
| "success"
| "error";
signature?: string;
error?: string;
step?: number;
totalSteps?: number;
}

export interface TxnStep {
id: string;
title: string;
description?: string;
status: "pending" | "active" | "completed" | "error";
}

export interface TxnFeedbackProps {
status: TransactionStatus;
onRetry?: () => void;
onClose?: () => void;
}