Carousel
Browse a row of slides by dragging, flicking, or arrowing through them.
carouselslidergallery
Preview
Carousel preview
Live · keyboard ready
When to use
- A short set of peer items where neighbouring slides hint at more.
- Galleries browsed by drag, flick, trackpad swipe, or keys.
- Rotating highlights with a visible pause control, via interval.
When not to use
- Use cover-flow for a showpiece gallery and photo-grid to show everything at once.
- Use card-stack for deciding on items one at a time.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "carousel",
"type": "registry:ui",
"title": "Carousel",
"description": "Browse a row of slides by dragging, flicking, or arrowing through them.",
"categories": [
"data"
],
"dependencies": [
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/carousel/carousel.tsx",
"type": "registry:component",
"target": "@components/manicat/carousel/carousel.tsx"
},
{
"path": "registry/components/carousel/carousel.module.css",
"type": "registry:component",
"target": "@components/manicat/carousel/carousel.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/carousel",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/carousel",
"markdown": "https://uiarc.dev/components/carousel/markdown",
"tags": [
"carousel",
"slider",
"gallery"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { Carousel } from "@/components/manicat/carousel/carousel";
const slides = [
{ title: "Harbour suites", tone: "from-sky-400 to-blue-600" },
{ title: "Old town lofts", tone: "from-rose-400 to-red-600" },
{ title: "Wine cellar stay", tone: "from-amber-400 to-orange-600" },
{ title: "Hilltop villa", tone: "from-emerald-400 to-green-600" },
{ title: "Lakeside cabin", tone: "from-indigo-400 to-violet-600" },
];
export function CarouselExample() {
return (
<Carousel label="From the Harbour suites" slideSize="72cqw">
{slides.map((slide) => (
<div
key={slide.title}
className={`flex aspect-[4/3] items-center justify-center rounded-[var(--radius-panel)] bg-gradient-to-br ${slide.tone}`}
>
<p className="font-medium text-white">{slide.title}</p>
</div>
))}
</Carousel>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Property gallery Drag, swipe or use the arrows; slides snap to a fixed width so the next one peeks in.
Property gallery
Drag, swipe or use the arrows; slides snap to a fixed width so the next one peeks in. preview
Live · keyboard ready
property-gallery-drag-swipe-or-use-the-arrows-slides-snap-to-a-fixed-width-so-the-next-one-peeks-in-.tsxtsx
"use client";
import { Carousel } from "@/components/manicat/carousel/carousel";
const stays = [
{ title: "Harbour suites", tone: "from-sky-400 to-blue-600" },
{ title: "Old town lofts", tone: "from-rose-400 to-red-600" },
{ title: "Wine cellar stay", tone: "from-amber-400 to-orange-600" },
{ title: "Hilltop villa", tone: "from-emerald-400 to-green-600" },
];
export function CarouselGalleryExample() {
return (
<div className="w-full max-w-xl">
<Carousel label="Featured stays" slideSize="72cqw">
{stays.map((stay) => (
<div
key={stay.title}
className={`flex aspect-[4/3] items-center justify-center rounded-[var(--radius-panel)] bg-gradient-to-br ${stay.tone}`}
>
<p className="font-medium text-white">{stay.title}</p>
</div>
))}
</Carousel>
</div>
);
}
Keyboard interactions
| Keys | Action |
|---|---|
| ArrowLeft / ArrowRight | Moves to the previous or next slide. |
| Home / End | Jumps to the first or last slide. |
| Tab | Moves between the slide area, play control, active indicator, and arrows. |
Accessibility
- The root is a section with aria-roledescription="carousel"; slides are labelled tabpanels and the indicators a role="tablist".
- Inactive slides are inert, so their links are not focusable.
- Slide changes are announced in a polite live region.
- Rotation pauses on hover, keyboard focus, and drag, and has a visible pause control.
Motion
- Slides follow the finger and settle with momentum; neighbors shrink and dim with distance.
- The indicator stretches into a pill that tracks the slides, and drains to show rotation time.
- Reduced motion jumps between slides and disables rotation.
Responsive behavior
- Slides default to min(80cqw, 340px), so they size to the carousel's container rather than the viewport.
- Controls tighten when the container is under 340px.
Performance
- All slides stay mounted; inactive ones are inert, so keep the set short.
- Rotation pauses offscreen via IntersectionObserver and in hidden tabs via visibilitychange.
Notes for AI
- Use for a short set of peer items where neighbors should hint at more. Use cover-flow for a showpiece gallery and photo-grid to show everything at once.
- Give each slide a stable key if the list can change, and write a specific label.
- Keep autoplay off unless rotation is essential.