Carousel
A horizontally or vertically scrolling set of slides with prev/next controls.
@garn/ui/carouselDefault
Five numbered slides with prev/next.
Installation
garn is copy-in — the garn CLI writes this component's source into your project, so you own and can edit it. It resolves any base files and installs the npm dependencies below for you.
npx garn-ui add carousel- Registry
carousel- Source
- carousel.tsx
- Deps
embla-carousel-reactlucide-react- Registry deps
buttonutils
Import
import { Carousel } from "@garn/ui/carousel";Props
Generated from the component's TypeScript types.
opts- Description
- No description.
- Type
Partial<OptionsType>
orientation- Description
- No description.
- Type
"horizontal" | "vertical"
plugins- Description
- No description.
- Type
CreatePluginType<LoosePluginType, {}>[]
setApi- Description
- No description.
- Type
(api: CarouselApi) => void
Plus 280 inherited native HTML attributes.
Styling
Target these data-slots and remap these tokens to restyle without forking the component.
[data-slot="carousel"]Overview
Carousel shows a set of peer items — images, cards, testimonials — in a swipeable/steppable track when they don't all fit at once. Carousel is the Embla-backed region (sets orientation/options, handles arrow keys), CarouselContent the track, CarouselItem each slide, with CarouselPrevious/CarouselNext auto-disabling at the ends. Use it for browsable peer media; for content users must not miss, lay it out directly — carousels hide everything but the current slide.
Guidelines
Use a carousel only for genuinely optional, peer content. Anything important shouldn't depend on a user swiping to find it — carousels have low engagement past the first slide. A short, equally-weighted set (a gallery, featured cards) is the sweet spot.
Make navigation obvious and keyboard-operable. Show prev/next controls and position indicators; the track responds to arrow keys and the buttons disable at the ends — don't hide the only way to advance behind a hover. Let users control the pace.
Avoid aggressive autoplay. If it auto-advances, make it slow, pausable, and stopped on focus/hover; honor reduced-motion. Each slide is announced as one of N — keep slides self-contained so they make sense out of sequence.
Best practices
- Give the Carousel an aria-label; keep prev/next reachable.
- If you autoplay, provide a pause/stop control (and respect reduced motion).
- Grab the Embla
apiviasetApiwhen you need programmatic control or a dot indicator.
- Don't bury important content in later slides.
- Don't autoplay without a way to pause.
- Don't use a carousel where the items should all be visible (use a grid).
Content guidelines
- Give every slide a concise caption or alt text — don't rely on position alone.
- Label the previous/next controls and any slide indicators for assistive tech.
Accessibility
- Role
region
Keyboard
| ArrowLeft | Previous slide (when the carousel has focus). |
| ArrowRight | Next slide (when the carousel has focus). |
- • Root is role=region aria-roledescription="carousel"; each item is role=group aria-roledescription="slide".
- • Give the carousel an accessible name (aria-label) describing what it contains.
- • Prev/Next have sr-only labels and disable at the ends so state is conveyed without color.
- Status
- Stable
- Version
v0.3.0- Introduced
v0.1.0
garn doesn't yet record a per-release version history. This reflects the component's current lifecycle state; full changelog entries will appear once the metadata pipeline emits a lifecycle.history field.