A composable card carousel with horizontal scroll, keyboard and button navigation.
"use client";
import { Palette, Plus, Shield, Users, Zap } from "lucide-react";
import { Button } from "@/components/ui/button/button";
import {
  Card,
  CardDescription,
  CardIcon,
  CardTitle,
} from "@/components/ui/card/card";
import { Carousel } from "@/components/ui/carousel/carousel";
import styles from "./carousel-demo.module.css";
export default function CarouselDemo() {
  const features = [
    {
      id: "performance",
      icon: <Zap className={styles.icon} strokeWidth={1.5} />,
      title: "Performance",
      description:
        "Instant loading and millisecond response times for optimal user experience.",
    },
    {
      id: "security",
      icon: <Shield className={styles.icon} strokeWidth={1.5} />,
      title: "Security",
      description:
        "Bank-level encryption keeps your data protected and compliant.",
    },
    {
      id: "customization",
      icon: <Palette className={styles.icon} strokeWidth={1.5} />,
      title: "Customize",
      description:
        "Tailor every aspect to match your brand with flexible theming and configuration options.",
    },
    {
      id: "collaboration",
      icon: <Users className={styles.icon} strokeWidth={1.5} />,
      title: "Collaboration",
      description:
        "Work together seamlessly with real-time collaboration tools.",
    },
  ];
  return (
    <Carousel.Bleed>
      <Carousel.Root
        align="start"
        className={styles.carouselRoot}
        gap={8}
        totalItems={features.length}
        variant="inset"
      >
        <Carousel.Viewport>
          <Carousel.Content>
            {features.map((feature, index) => (
              <Carousel.Item index={index} key={feature.id}>
                <Card id={styles.card}>
                  <div className={styles.iconSection}>
                    <CardIcon id={styles.icon}>{feature.icon}</CardIcon>
                  </div>
                  <div className={styles.cardContent}>
                    <div className={styles.contentText}>
                      <CardTitle className={styles.cardTitle}>
                        {feature.title}
                      </CardTitle>
                      <CardDescription>{feature.description}</CardDescription>
                    </div>
                    <Button
                      className={`${styles.button} hit-area-extend`}
                      size="icon"
                      variant="outline"
                    >
                      <Plus strokeWidth={1.5} />
                    </Button>
                  </div>
                </Card>
              </Carousel.Item>
            ))}
          </Carousel.Content>
        </Carousel.Viewport>
        <Carousel.Navigation>
          <Carousel.Previous />
          <Carousel.Next />
        </Carousel.Navigation>
      </Carousel.Root>
    </Carousel.Bleed>
  );
}
npx shadcn@latest add https://roiui.com/r/carousel.jsonimport { Carousel } from "@/components/ui/carousel";
<Carousel.Bleed>
<Carousel.Root totalItems={3} gap={16} variant="inset" align="center">
  <Carousel.Viewport>
    <Carousel.Content>
      <Carousel.Item index={0}>
        <div>Item 1</div>
      </Carousel.Item>
      <Carousel.Item index={1}>
        <div>Item 2</div>
      </Carousel.Item>
      <Carousel.Item index={2}>
        <div>Item 3</div>
      </Carousel.Item>
    </Carousel.Content>
  </Carousel.Viewport>
  <Carousel.Navigation />
</Carousel.Root>
</Carousel.Bleed>
The main carousel component that manages state and provides context.
totalItemsnumbergapnumber16variant"default" | "inset""default"align"start" | "center""start"indexnumberdefaultIndexnumber0onIndexChangefunctionclassNamestringWrapper that extends carousel to full viewport width.
classNamestringScrollable viewport container with hidden scrollbars.
classNamestringFlex container for horizontal layout with pseudo elements for spacing.
classNamestringindexnumberclassNamestringContainer for navigation buttons with default Previous/Next rendering.
classNamestringchildrenReactNodePrevious button that auto-disables at start.
classNamestringchildrenReactNodeNext button that auto-disables at end.
classNamestringchildrenReactNodeDot indicators for each item (hidden when only one item).
classNamestring