About
AnimatedJobCard This component displays job posting information with a subtle, interactive 3D tilt animation on hover. It's designed to be highly reusable, accepting props for content and color variants.
Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Animated Card to your project and fits it to your theme.
Code
How Animated Card is used: the demo's code. The component's own source comes with a free account.
Usage.tsx
import React, { useState } from "react";
import { AnimatedJobCard, JobCardProps } from "@/components/ui/animated-card";
import { cn } from "@/lib/utils";
// --- SVG ICONS FOR DEMO ---
const SlackIcon = () => (
<svg viewBox="0 0 2447.6 2452.5"><g clip-rule="evenodd" fill-rule="evenodd"><path d="m897.4 0c-135.3.1-244.8 109.9-244.7 245.2-.1 135.3 109.5 245.1 244.8 245.2h244.8v-245.1c.1-135.3-109.5-245.1-244.9-245.3.1 0 .1 0 0 0m0 654h-652.6c-135.3.1-244.9 109.9-244.8 245.2-.2 135.3 109.4 245.1 244.7 245.3h652.7c135.3-.1 244.9-109.9 244.8-245.2.1-135.4-109.5-245.2-244.8-245.3z" fill="#36c5f0"/><path d="m2447.6 899.2c.1-135.3-109.5-245.1-244.8-245.2-135.3.1-244.9 109.9-244.8 245.2v245.3h244.8c135.3-.1 244.9-109.9 244.8-245.3zm-652.7 0v-654c.1-135.2-109.4-245-244.7-245.2-135.3.1-244.9 109.9-244.8 245.2v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.3z" fill="#2eb67d"/><path d="m1550.1 2452.5c135.3-.1 244.9-109.9 244.8-245.2.1-135.3-109.5-245.1-244.8-245.2h-244.8v245.2c-.1 135.2 109.5 245 244.8 245.2zm0-654.1h652.7c135.3-.1 244.9-109.9 244.8-245.2.2-135.3-109.4-245.1-244.7-245.3h-652.7c-135.3.1-244.9 109.9-244.8 245.2-.1 135.4 109.4 245.2 244.7 245.3z" fill="#ecb22e"/><path d="m0 1553.2c-.1 135.3 109.5 245.1 244.8 245.2 135.3-.1 244.9-109.9 244.8-245.2v-245.2h-244.8c-135.3.1-244.9 109.9-244.8 245.2zm652.7 0v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.2v-653.9c.2-135.3-109.4-245.1-244.7-245.3-135.4 0-244.9 109.8-244.8 245.1 0 0 0 .1 0 0" fill="#e01e5a"/></g></svg>
);
const GoogleIcon = () => (
<svg viewBox="0 0 256 262" preserveAspectRatio="xMidYMid"><path d="M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622 38.755 30.023 2.685.268c24.659-22.774 38.875-56.282 38.875-96.027" fill="#4285F4"/><path d="M130.55 261.1c35.248 0 64.839-11.605 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257 13.055-34.523 0-63.824-22.773-74.269-54.25l-1.531.13-40.298 31.187-.527 1.465C35.393 231.798 79.49 261.1 130.55 261.1" fill="#34A853"/><path d="M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82 0-8.994 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644 0 109.517 0 130.55s5.077 40.905 13.925 58.602l42.356-32.782" fill="#FBBC05"/><path d="M130.55 50.479c24.514 0 41.05 10.589 50.479 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0 79.49 0 35.393 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251 74.414-54.251" fill="#EB4335"/></svg>
);
// --- INITIAL DEMO DATA ---
const initialJobs: JobCardProps[] = [
{
companyLogo: <SlackIcon />,
companyName: "Slack",
jobTitle: "Senior UI Designer",
salary: "$3,500-5,500 net",
tags: ["Project Based", "Remote"],
postedDate: "Posted 2 Day Ago",
variant: "pink",
},
{
companyLogo: <GoogleIcon />,
companyName: "Google",
jobTitle: "Lead UX Designer",
salary: "$4,000-6,000 net",
tags: ["Full Time", "B2B"],
postedDate: "Posted Yesterday",
variant: "yellow",
},
{
companyLogo: <SlackIcon />,
companyName: "Slack",
jobTitle: "Lead Product Designer",
salary: "$3,500-5,500 net",
tags: ["Full Time", "Remote"],
postedDate: "Posted 2 Day Ago",
variant: "blue",
},
];
// --- DEMO COMPONENT ---
export default function AnimatedJobCardDemo() {
const [cards, setCards] = useState(initialJobs);
const cardTransforms = [
"rotate-[-8deg] translate-x-[-30%] translate-y-[10%] z-0",
"rotate-[0deg] translate-y-[-5%] z-20",
"rotate-[8deg] translate-x-[30%] translate-y-[10%] z-10",
];
const handleCardClick = (index: number) => {
if (index === 1) return;
const newCards = [...cards];
const clickedCard = newCards.splice(index, 1)[0];
newCards.splice(1, 0, clickedCard);
setCards(newCards);
};
return (
<div className="relative flex h-[500px] w-full items-center justify-center bg-background">
<div className="relative h-full w-full" style={{ perspective: "1000px" }}>
{cards.map((job, index) => (
<AnimatedJobCard
key={job.jobTitle + job.companyName}
{...job}
onClick={() => handleCardClick(index)}
className={cn(
"absolute left-0 right-0 top-1/4 mx-auto",
"w-96",
cardTransforms[index]
)}
/>
))}
</div>
</div>
);
}















