Skip to main content

Installation

npx shadcn@latest add @kokonutui/currency-transfer

Usage

import CurrencyTransfer from "@/components/kokonutui/currency-transfer";

export default function Example() {
  return <CurrencyTransfer />;
}

Features

  • Multi-Step Animation: Progress → Completion states
  • Spring Physics: Smooth motion transitions
  • Status Icons: Rotating spinner and checkmark
  • Card Merging: From/To cards merge on completion
  • Exchange Rate Display: Real-time rate information
  • Transaction ID: Unique identifier display
  • Glow Effects: Ambient emerald glow on success
  • Tooltip Integration: Additional info on hover
  • Automatic Progression: 1.5s timer from start to complete

Animation States

In Progress (0-1.5s)

  • Rotating spinner icon
  • Separated From/To cards
  • “Processing Transaction…” status
  • “Calculating exchange rate…” message
  • Pulsing glow effect
  • Reduced opacity on amounts

Completed (After 1.5s)

  • Check icon with entrance rotation
  • Merged From/To cards (rounded corners adjusted)
  • “Transfer Completed” status
  • Transaction ID displayed
  • Exchange rate shown
  • Full opacity on amounts

Component Structure

Main Container

<Card className="h-[420px] w-full max-w-sm">
  <CardContent>
    {/* Status Icon */}
    {/* Title & Transaction ID */}
    {/* From/To Cards */}
    {/* Exchange Rate */}
  </CardContent>
</Card>

Animation Details

Card Merging

animate={{
  gap: isCompleted ? "0px" : "12px",
}}
// Rounds: normal → rounded-b-none & rounded-t-none

Spinner Rotation

animate={{
  rotate: 360,
  scale: [1, 1.02, 1]
}}
transition={{
  rotate: { duration: 3, repeat: Infinity },
  scale: { duration: 2, repeat: Infinity }
}}

Check Icon

initial={{ opacity: 0, rotate: -180 }}
animate={{ opacity: 1, rotate: 0 }}
transition={{ duration: 0.6 }}

Currency Information

From (USD)

  • Amount: 500.00 USD
  • Account: Chase Bank ••••4589
  • Icon: Dollar sign ($)

To (EUR)

  • Amount: 460.00 EUR
  • Account: Deutsche Bank ••••7823
  • Icon: Euro sign (€)

Exchange Rate

  • Rate: 1 USD = 0.92 EUR
  • Updates: Real-time (shown on completion)

Customization Example

// Modify transaction details
const CustomTransfer = () => {
  return (
    <Card className="h-[420px] w-full max-w-sm">
      {/* From: GBP */}
      <div>
        <span>£</span>
        <span>1000.00 GBP</span>
        <span>Barclays ••••1234</span>
      </div>
      
      {/* To: JPY */}
      <div>
        <span>¥</span>
        <span>187500 JPY</span>
        <span>MUFG Bank ••••5678</span>
      </div>
      
      {/* Rate */}
      <span>1 GBP = 187.50 JPY</span>
    </Card>
  );
};

Timing Configuration

useEffect(() => {
  const timer = setTimeout(() => {
    setIsCompleted(true);
  }, 1500);  // 1.5 seconds
  
  return () => clearTimeout(timer);
}, []);

Icon Components

Progress State

  • ArrowUpDown: Main icon (emerald-500)
  • ArrowUpIcon: From indicator
  • ArrowDownIcon: To indicator

Completed State

  • Check: Checkmark (emerald-500, strokeWidth 3.5)
  • Border ring around check icon

Glow Effect

<motion.div
  animate={{ opacity: [0, 1, 0.8] }}
  className="absolute inset-0 rounded-full bg-emerald-500/10 blur-2xl"
  transition={{ duration: 1.5, times: [0, 0.5, 1] }}
/>

Hover States

Amount Cards

  • Border color transition
  • Emerald accent on hover (when not completed)
  • Disabled hover when merged

Info Tooltip

  • Icon: InfoIcon (3x3 size)
  • Content: Rate update time or “Please wait…”
  • Position: Next to exchange rate

Dependencies

  • motion (Framer Motion)
  • @/components/ui/card (shadcn)
  • @/components/ui/tooltip (shadcn)
  • lucide-react (Icons)
  • @/lib/utils (cn helper)

Easing Functions

ease: [0.22, 1, 0.36, 1]  // Custom cubic-bezier
ease: [0.32, 0.72, 0, 1]   // Card merge easing

Responsive Design

  • Fixed height: 420px
  • Max width: sm (384px)
  • Padding: 24px (p-6)
  • Mobile-friendly tap targets
  • Touch-friendly spacing

Build docs developers (and LLMs) love