Token Swap Card
Blocks & SlicesA demo-grade crypto swap card with two token fields (searchable keyboard-driven picker + amount input) whose amounts derive from the USD price ratio, a center button that flips 180° and swaps the sides on a spring, a live rate line, and a Swap button that runs an inline pending → done animation. The flip, card cross, and spinner drop to instant state swaps under prefers-reduced-motion.
Inspired by Skiper UI — Aave token swap (pattern) — independently built, not affiliated. Attribution policy
Swap
demoETH
$4,680.66
USDC
$4,680.66
Rate1 ETH ≈ 3,120.44 USDC
Installation
npx shadcn@latest add https://parable-three.vercel.app/r/token-swap-card.jsonRuns the shadcn CLI — the component source is copied intocomponents/parable/token-swap-card.tsx. You own it from there.
Usage
The exact code rendering the preview above.
<div className="w-full max-w-sm">
<TokenSwapCard
defaultFrom="ETH"
defaultTo="USDC"
defaultAmount="1.5"
tokens={[
{ symbol: "ETH", name: "Ethereum", price: 3120.44, icon: <div className="size-full rounded-full bg-gradient-to-br from-indigo-400 to-violet-600" /> },
{ symbol: "USDC", name: "USD Coin", price: 1, icon: <div className="size-full rounded-full bg-gradient-to-br from-sky-400 to-blue-600" /> },
{ symbol: "SOL", name: "Solana", price: 176.9, icon: <div className="size-full rounded-full bg-gradient-to-br from-fuchsia-400 to-purple-600" /> },
{ symbol: "WBTC", name: "Wrapped Bitcoin", price: 68420, icon: <div className="size-full rounded-full bg-gradient-to-br from-amber-400 to-orange-500" /> },
{ symbol: "ARB", name: "Arbitrum", price: 0.82, icon: <div className="size-full rounded-full bg-gradient-to-br from-cyan-400 to-blue-500" /> },
]}
/>
</div>Props
TokenSwapCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "onSubmit">
| Prop | Type | Default | Description |
|---|---|---|---|
| tokens* | SwapToken[] | — | Tokens offered on both sides. Needs at least two distinct symbols. |
| defaultFrom | string | — | Symbol pre-selected in the "You pay" field. Defaults to `tokens[0]`. |
| defaultTo | string | — | Symbol pre-selected in the "You receive" field. Defaults to `tokens[1]`. |
| defaultAmount | string | "1" | Amount pre-filled in the "You pay" field. Defaults to `"1"`. |
| onSwap | (payload: TokenSwapPayload) => Promise<void> | void | — | Runs when "Swap" is pressed. Resolve to reach the done state, throw to fall back to idle. Defaults to a fake ~1.1s settle so the card demos itself. |
| accent | string | "#8b5cf6" | Accent hex — button, focus ring, active option. Default Parable violet. |
npm dependencies
- motion