NRVM

Back to Discover
ReactIntermediate

Expandable Card

A layout-animating card that expands to reveal more content smoothly.

Live Preview

Click to Expand

"use client";
import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { ChevronDown } from "lucide-react";

export function ExpandableCard() {
  const [expanded, setExpanded] = useState(false);

  return (
    <motion.div 
      layout
      onClick={() => setExpanded(!expanded)}
      className="w-full max-w-sm rounded-2xl border border-border bg-[#0a0a0a] p-6 cursor-pointer hover:border-[#333333] transition-colors"
    >
      <motion.div layout className="flex items-center justify-between">
        <h3 className="font-medium text-foreground select-none">Click to Expand</h3>
        <motion.div
          animate={{ rotate: expanded ? 180 : 0 }}
          transition={{ duration: 0.2 }}
        >
          <ChevronDown className="h-4 w-4 text-muted-foreground" />
        </motion.div>
      </motion.div>
      <AnimatePresence>
        {expanded && (
          <motion.div
            initial={{ opacity: 0, height: 0 }}
            animate={{ opacity: 1, height: "auto" }}
            exit={{ opacity: 0, height: 0 }}
            transition={{ duration: 0.3, ease: "easeInOut" }}
            className="text-sm text-muted-foreground overflow-hidden"
          >
            <div className="pt-4 select-none">
              This card smoothly expands using Framer Motion's layout prop. The animation feels natural and physically accurate.
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  );
}