Carousel

The Carousel component is an interactive image slider built using React (TypeScript/TSX) and Framer Motion for smooth animations. It displays slides containing an image, title, and description, with animated transitions between slides.

framer-motion

Beach

Relax by the sea with soft waves, golden sunsets, and a calming breeze that melts stress away.

Installation

Install the required dependencies:

npm install framer-motion
Link to required files
Follow this link and download the required files. - https://github.com/railav61/data/tree/main/forkui-data/carousel
components/ui/carousel.tsx
"use client";

import { motion, AnimatePresence } from "framer-motion";
import { useState } from "react";

type Slide = {
  image: string;
  title: string;
  desc: string;
};

const slides: Slide[] = [
  {
    image: "/13.jpg",
    title: "Beach",
    desc: "Relax by the sea with soft waves, golden sunsets, and a calming breeze that melts stress away.",
  },
  {
    image: "/mountains.jpg",
    title: "Mountains",
    desc: "Breathe in fresh mountain air while surrounded by towering peaks, misty mornings, and peaceful silence.",
  },
  {
    image: "/amazon-forest.jpg",
    title: "Forest",
    desc: "Immerse yourself in lush greenery, gentle sunlight, and the soothing sounds of nature all around.",
  },
  {
    image: "/desert.jpg",
    title: "Desert",
    desc: "Experience the beauty of endless golden sands, dramatic skies, and the quiet power of vast landscapes.",
  },
  {
    image: "/tokyo.jpg",
    title: "City",
    desc: "Feel the pulse of urban life with glowing skylines, vibrant streets, and endless opportunities.",
  },
];

export default function Carousel() {
  const [index, setIndex] = useState(0);
  const [animate, setAnimate] = useState(0);

  const next = () => {
    setIndex((prev) => (prev + 1) % slides.length);
    setAnimate(1);
  };

  const prev = () => {
    setIndex((prev) => (prev - 1 + slides.length) % slides.length);
    setAnimate(0);
  };

  const slideVariants = {
    enter: (direction: number) => ({
      x: direction === 1 ? 100 : -100,
      opacity: 0,
    }),
    center: {
      x: 0,
      opacity: 1,
    },
    exit: (direction: number) => ({
      x: direction === 1 ? -100 : 100,
      opacity: 0,
    }),
  };

  return (
    <div className="w-full flex justify-center">
      {/* FIXED HEIGHT CONTAINER */}
      <div className="relative w-[50vw] h-[420px] overflow-hidden rounded-2xl bg-black">
        <AnimatePresence mode="wait">
          <motion.div
            key={index}
            className="absolute inset-0"
            custom={animate}
            variants={slideVariants}
            initial="enter"
            animate="center"
            exit="exit"
            transition={{
              duration: 0.45,
              ease: "easeInOut",
            }}
          >
            <img
              src={slides[index].image}
              alt=""
              className="w-full h-full object-cover"
            />

            {/* Overlay */}
            <motion.div
              initial={{ opacity: 0, scale: 0 }}
              animate={{ opacity: 1, scale: 1 }}
              transition={{
                duration: 0.4,
                scale: { type: "spring", visualDuration: 0.4, bounce: 0.2 },
              }}
            >
              <div className="absolute bottom-0 w-full bg-gradient-to-t from-black/70 to-transparent p-6 text-white">
                <h2 className="text-7xl font-bold my-5">{slides[index].title}</h2>
                <p className="text-3xl font-bold opacity-80">{slides[index].desc}</p>
              </div>
            </motion.div>
          </motion.div>
        </AnimatePresence>

        {/* Controls */}
        <button
          onClick={prev}
          className="absolute left-4 top-1/2 font-extrabold text-2xl -translate-y-1/2 bg-white/50 h-16 w-16 px-3 py-1 rounded-full"
        >
        </button>

        <button
          onClick={next}
          className="absolute right-4 top-1/2 font-extrabold text-2xl -translate-y-1/2 bg-white/50 h-16 w-16 px-3 py-1 rounded-full"
        >
        </button>
      </div>
    </div>
  );
}

Usecase

Beach

Relax by the sea with soft waves, golden sunsets, and a calming breeze that melts stress away.

* Mordern carousel example