Carousel

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.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 className={styles.card}>
                <div className={styles.iconSection}>
                  <CardIcon className={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>
  );
}

npx shadcn@latest add @roiui/carousel
npx shadcn@latest add @roiui/carousel-tailwind

anatomy
import { 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.

Prop
Type
Default

Wrapper that extends carousel to full viewport width.

Prop
Type
Default

Scrollable viewport container with hidden scrollbars.

Prop
Type
Default

Flex container for horizontal layout with pseudo elements for spacing.

Prop
Type
Default

Prop
Type
Default

Container for navigation buttons with default Previous/Next rendering.

Prop
Type
Default

Previous button that auto-disables at start.

Prop
Type
Default

Next button that auto-disables at end.

Prop
Type
Default

Dot indicators for each item (hidden when only one item).

Prop
Type
Default