Carousel
A carousel with motion and slide effects built on Embla.
When to use
A carousel suits browsable, order-agnostic content: screenshots, onboarding slides, a strip of promo cards on a dashboard. Anything a user must not miss or needs to compare goes in a DataTable or a wrapped grid, and a long list of peers scrolls better inside a ScrollArea.
Platform notes
Autoplay is out of bounds: the motion contract in DESIGN.md rules out auto-rotating carousels, so do not add embla-carousel-autoplay, and slides move only on a click, swipe or arrow key. Embla animates with JavaScript transforms, which the theme's CSS prefers-reduced-motion block cannot neutralise, so pass opts.duration: 0 when that query matches. The sr-only labels on CarouselPrevious and CarouselNext are English literals in the vendored file and are the only names a screen reader gets, so replace them with i18next messages. Watch the geometry too: the arrows sit at -left-12 and -right-12, outside the frame, so give the wrapper horizontal room or move them inside at small breakpoints.
Install
npx shadcn@latest add carouselCode
"use client";
import { Card, CardContent } from "@/components/ui/card";
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel";
export function CarouselDemo() {
return (
<Carousel className="w-full max-w-xs">
<CarouselContent>
{[1, 2, 3, 4, 5].map((slideNumber) => (
<CarouselItem key={slideNumber}>
<div className="p-1">
<Card>
<CardContent className="flex aspect-square items-center justify-center p-6">
<span className="text-3xl font-semibold">{slideNumber}</span>
</CardContent>
</Card>
</div>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
);
}