ham7a311

Fan Deck Card

Cards

About

A stack of itinerary/content cards that behaves like a hand of cards: resting as a tidy pile, fanning into an arc on hover or focus, and letting you pick a card to bring it to the top with swipe, click or arrow-key support.

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

Code

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

Usage.tsx

"use client";

import { FanDeckCard, type DeckCard } from "@/components/ui/fan-deck-card";

const CARDS: DeckCard[] = [
  {
    id: "akhdar",
    title: "Jabal Akhdar",
    meta: "2 days · from OMR 85",
    tint: "#3f8f5a",
    blurb:
      "Rose terraces at dawn, a night in the clouds and the walk along the canyon rim.",
    art: (
      <svg viewBox="0 0 200 140" preserveAspectRatio="xMidYMid slice">
        <defs>
          <linearGradient id="fa1" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0" stopColor="#bfe3f0" />
            <stop offset="1" stopColor="#f6e2c8" />
          </linearGradient>
        </defs>
        <rect width="200" height="140" fill="url(#fa1)" />
        <path
          d="M0 100 L40 58 L70 82 L110 40 L150 76 L200 50 V140 H0Z"
          fill="#6b8f7a"
        />
        <path
          d="M0 120 L50 88 L90 108 L140 80 L200 104 V140 H0Z"
          fill="#3f6b50"
        />
        {[0, 1, 2, 3].map((i) => (
          <path
            key={i}
            d={`M0 ${124 + i * 5} Q100 ${112 + i * 5} 200 ${124 + i * 5}`}
            stroke="#e98aa5"
            strokeWidth="1.6"
            fill="none"
            opacity="0.7"
          />
        ))}
      </svg>
    ),
  },
  {
    id: "shab",
    title: "Wadi Shab",
    meta: "1 day · from OMR 30",
    tint: "#1c9aa6",
    blurb:
      "Wade the turquoise pools, swim through the gap, and find the waterfall in the cave.",
    art: (
      <svg viewBox="0 0 200 140" preserveAspectRatio="xMidYMid slice">
        <rect width="200" height="140" fill="#e8c9a0" />
        <path d="M0 0 H70 L60 140 H0Z" fill="#c98f5e" />
        <path d="M200 0 H130 L142 140 H200Z" fill="#b97a4a" />
        <path d="M64 140 Q100 90 136 140Z" fill="#2fc4c8" />
        <path d="M70 140 Q100 104 130 140Z" fill="#7fe3e0" opacity="0.6" />
      </svg>
    ),
  },
  {
    id: "wahiba",
    title: "Wahiba Sands",
    meta: "2 days · from OMR 110",
    tint: "#d9682f",
    blurb:
      "Dune bashing at sunset, a Bedouin camp and more stars than you knew there were.",
    art: (
      <svg viewBox="0 0 200 140" preserveAspectRatio="xMidYMid slice">
        <rect width="200" height="140" fill="#ffb877" />
        <circle cx="150" cy="50" r="18" fill="#fff1cf" />
        <path d="M0 92 Q60 60 120 86 T200 78 V140 H0Z" fill="#e9864a" />
        <path d="M0 116 Q80 84 160 112 T200 108 V140 H0Z" fill="#c2602f" />
      </svg>
    ),
  },
  {
    id: "jinz",
    title: "Ras al Jinz",
    meta: "1 night · from OMR 60",
    tint: "#5a5fd6",
    blurb:
      "Walk the beach at night with a ranger and watch green turtles come ashore to nest.",
    art: (
      <svg viewBox="0 0 200 140" preserveAspectRatio="xMidYMid slice">
        <rect width="200" height="140" fill="#141a44" />
        <circle cx="148" cy="38" r="14" fill="#f4efd8" />
        {Array.from({ length: 20 }, (_, i) => (
          <circle
            key={i}
            cx={(i * 47) % 200}
            cy={(i * 29) % 70}
            r="0.9"
            fill="#fff"
            opacity="0.7"
          />
        ))}
        <rect y="88" width="200" height="22" fill="#1f2a66" />
        <path d="M0 110 H200 V140 H0Z" fill="#c8b48e" />
        <ellipse cx="80" cy="120" rx="12" ry="6" fill="#3a3a2a" />
      </svg>
    ),
  },
  {
    id: "muscat",
    title: "Old Muscat",
    meta: "Half day · from OMR 20",
    tint: "#b04a4a",
    blurb:
      "The forts either side of the harbour, the palace gates and coffee in Mutrah souq.",
    art: (
      <svg viewBox="0 0 200 140" preserveAspectRatio="xMidYMid slice">
        <rect width="200" height="140" fill="#f4dcc0" />
        <path
          d="M0 96 L30 70 L52 84 L80 60 L110 88 L140 64 L170 82 L200 70 V140 H0Z"
          fill="#a8786a"
        />
        <path
          d="M20 140 V104 h12 v-6 h6 v6 h4 v-8 h8 v8 h4 v-6 h6 v6 h12 V140Z"
          fill="#7a3b33"
        />
        <rect y="118" width="200" height="22" fill="#4f8fb0" />
      </svg>
    ),
  },
];

export default function Demo() {
  return (
    <div className="flex min-h-full w-full items-center justify-center overflow-hidden px-4 py-12 bg-background text-foreground">
      <FanDeckCard cards={CARDS} theme="paper" />
    </div>
  );
}

More by ham7a311

View all
  • Wave Mesh

    Wave Mesh

    137
  • Route Globe

    Route Globe

    125
  • Glass Tiles

    Glass Tiles

    109
  • Glyph Swell

    Glyph Swell

    50
  • Orbit Ring Stats

    Orbit Ring Stats

    47
  • Ask Bar

    Ask Bar

    38
  • Glass Ribbons

    Glass Ribbons

    30
  • Intent Label

    Intent Label

    29

More in Cards

View all
  • Stats cards with links

    Stats cards with links

    40
  • Course Design Cards

    Course Design Cards

    1.2K
  • Interactive Tech Stack Bento Grid with Hover Effects

    Interactive Tech Stack Bento Grid with Hover Effects

    449
  • Card Studio

    Card Studio

    36
  • Statistics Card 7

    Statistics Card 7

    312
  • Statistics Card 2

    Statistics Card 2

    293
  • The Item one

    The Item one

    3
  • Testimonial

    Testimonial

    70