ham7a311

Card Wallet

Cards

About

A virtual-card wallet that shows cards as a small physical stack, keeps the full number, expiry and CVC masked until explicitly revealed, hides them again on a visible countdown, and lets a card be frozen or unfrozen.

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Card Wallet to your project and fits it to your theme.

Code

How Card Wallet is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client";
import { CardWallet, type WalletCard } from "@/components/ui/card-wallet";

const CARDS: WalletCard[] = [
  {
    id: "ads",
    nickname: "Ads · Meta & search",
    holder: "Hamza Al-Bulushi",
    last4: "4821",
    expires: "08/29",
    color: "ink",
    limit: 1_500_000,
    spent: 1_342_050,
  },
  {
    id: "saas",
    nickname: "Software",
    holder: "Hamza Al-Bulushi",
    last4: "1907",
    expires: "03/28",
    color: "graphite",
    limit: 300_000,
    spent: 124_000,
  },
  {
    id: "travel",
    nickname: "Team travel",
    holder: "Layla Al-Harthy",
    last4: "6630",
    expires: "11/27",
    color: "moss",
    limit: 800_000,
    spent: 210_475,
  },
  {
    id: "old",
    nickname: "Old contractor card",
    holder: "Omar Said",
    last4: "0412",
    expires: "01/27",
    color: "sand",
    limit: 50_000,
    spent: 0,
    frozen: true,
  },
];
// Test numbers only. A real reveal goes through your server after a step-up check.
const SECRETS: Record<string, { number: string; cvc: string }> = {
  ads: { number: "4000 0012 3456 4821", cvc: "318" },
  saas: { number: "4000 0098 7654 1907", cvc: "502" },
  travel: { number: "4000 0055 5555 6630", cvc: "771" },
  old: { number: "4000 0000 0000 0412", cvc: "090" },
};

// Simulated service: every third freeze change fails, to show the rollback.
let freezeAttempts = 0;

export default function Demo() {
  return (
    <div className="flex min-h-full w-full justify-center bg-[#0b0b0c] px-4 py-10 sm:px-8">
      <div className="w-full max-w-[60rem]">
        <CardWallet
          cards={CARDS}
          theme="dark"
          locale="en-US"
          reveal={(id) =>
            new Promise((resolve) =>
              setTimeout(() => resolve(SECRETS[id]), 600),
            )
          }
          onFreeze={() =>
            new Promise((resolve, reject) =>
              setTimeout(
                () =>
                  ++freezeAttempts % 3 === 0
                    ? reject(new Error("timeout"))
                    : resolve(),
                500,
              ),
            )
          }
        />
      </div>
    </div>
  );
}

More by ham7a311

View all
  • Route Globe

    Route Globe

    12
  • Wave Mesh

    Wave Mesh

    7
  • Uptime Ribbon

    Uptime Ribbon

    6
  • Glass Carousel

    Glass Carousel

    6
  • Glass Tiles

    Glass Tiles

    6
  • Streak Field Stats

    Streak Field Stats

    5
  • Wind Map

    Wind Map

    4
  • Time Window

    Time Window

    4

More in Cards

View all
  • Stats cards with links

    Stats cards with links

    120
  • Course Design Cards

    Course Design Cards

    1.1K
  • Statistics Card 2

    Statistics Card 2

    259
  • Card

    Card

    56
  • Card Studio

    Card Studio

    9
  • The Item one

    The Item one

    3
  • Statistics Card 7

    Statistics Card 7

    289
  • Weather Card

    Weather Card

    54