suiss/ui · Component
Carousel
A swipeable track of slides with buttons, dots and optional autoplay, built on Embla Carousel.
Carousel is an open-source component from suiss/ui for React, React Native, SwiftUI and Jetpack Compose. The @esuiss/ui CLI copies its source into your project, so you own the code.
Carousel is built on embla-carousel-react. A Carousel root holds a CarouselContent track whose children are CarouselItem slides. Add CarouselPrevious and CarouselNext to page through slides; on their own they float outside the track's edges. To lay controls out in a row below the track instead, place them in a CarouselControls container, along with CarouselDots for per-slide indicators and CarouselPlayButton for autoplay.
Use a carousel for featured content, product shelves, testimonials and galleries where people browse a set of peers one at a time. For content everyone must see, prefer a static layout.
Installation
CLI
Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:
Manual
- Install the dependencies and add the
cnhelper:
- Update the import paths to match your project.
Usage
Carousel accepts opts (Embla options such as align, loop and dragFree), plugins, orientation (horizontal or vertical) and setApi, which receives the Embla API so you can read or drive the carousel from outside. The scroll direction follows the surrounding DirectionProvider.
Set the width of each slide with a basis-* class on CarouselItem, for example basis-1/2 to show two at a time. The track uses negative margin and slides use start padding for gutters; adjust both together, as in -ms-3 with ps-3.
Set autoplay to true for a 5-second interval, or to a number of milliseconds. Autoplay pauses while the pointer hovers the carousel, while it has keyboard focus, and while the page is hidden, and starts paused when the user prefers reduced motion. CarouselPlayButton renders only when autoplay is enabled, and the active dot fills as a progress bar.
Use the useCarousel hook inside a Carousel to build custom controls.
Examples
Multiple items
Shows two slides at a time with basis-1/2.
Loop
Wraps from the last slide back to the first with opts={{ loop: true }}.
Vertical
Scrolls vertically, with the buttons above and below the track.
Featured
Large cards that peek at the next slide, with plain dots below.
Spotlight
A looping hero with dots and a next button in a centered control bar.
Shelf
A drag-free product shelf with no visible buttons.
Testimonials
Quotes with dots and large previous and next buttons in a control row.
Gallery
Tall cards with controls aligned to the end below the track.
Featured autoplay
The featured layout advancing every four seconds.
Spotlight autoplay
The spotlight layout with autoplay and a pause button in place of the next button.
Shelf autoplay
The shelf advancing every three seconds and looping.
Testimonials autoplay
Testimonials advancing every six seconds.
API Reference
Carousel
The root region that owns the Embla instance, keyboard handling and autoplay state.
| Prop | Type | Default | Description |
|---|---|---|---|
opts | CarouselOptions | - | Options passed to Embla Carousel. |
plugins | CarouselPlugin | - | Embla Carousel plugins. |
orientation | "horizontal" | "vertical" | "horizontal" | The scroll direction. |
setApi | (api: CarouselApi) => void | - | Receives the Embla Carousel API once it is ready. |
autoplay | boolean | number | false | Advances the slides automatically; a number sets the delay in milliseconds. |
Also accepts the props of React.ComponentProps<"div">, CarouselProps.
CarouselContent
The clipping viewport and the flex track that holds the slides.
Also accepts the props of React.ComponentProps<"div">.
CarouselItem
A single slide.
Also accepts the props of React.ComponentProps<"div">.
CarouselPrevious
A button that scrolls to the previous slide, disabled at the start.
Also accepts the props of React.ComponentProps<typeof Button>.
CarouselNext
A button that scrolls to the next slide, disabled at the end.
Also accepts the props of React.ComponentProps<typeof Button>.
CarouselControls
A row that lays out buttons, dots and the play button below the track.
Also accepts the props of React.ComponentProps<"div">.
CarouselDots
One button per snap point that jumps to that slide and marks the current one.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "plain" | "default" | default places the dots on a blurred pill background; plain removes the background and padding. |
Also accepts the props of React.ComponentProps<"div">.
CarouselPlayButton
Toggles autoplay between playing and paused.
Also accepts the props of React.ComponentProps<typeof Button>.
Accessibility
- The root renders with
role="region"andaria-roledescription="carousel"; eachCarouselItemhasrole="group"andaria-roledescription="slide". Add anaria-labelto the root to name it. - Arrow keys move between slides while focus is inside the carousel: left and right for horizontal (reversed in right-to-left layouts), up and down for vertical.
CarouselPreviousandCarouselNextinclude visually hidden labels,Previous slideandNext slide. When one becomes disabled while focused, focus moves to the other.- Each dot is labelled
Go to slide N, and the current dot hasaria-current="true". CarouselPlayButtonis labelledPause slideshoworPlay slideshowto match its state.
Notes
- Styling hooks:
data-slotvaluescarousel,carousel-content,carousel-item,carousel-previous,carousel-next,carousel-controls,carousel-dotsandcarousel-play-button. - The root sets
data-playingwhile autoplay is running. Dots exposedata-activeon the current dot, and the dots container setsdata-variantanddata-autoplay. CarouselPreviousandCarouselNextdefault to thesecondaryvariant andiconsize;CarouselPlayButtondefaults tosecondaryandicon-sm.- In vertical carousels, standalone previous and next buttons are rotated 90 degrees; inside
CarouselControlsthey are not.
Web preview
Carousel wraps a scroll view that snaps to each CarouselItem. It scrolls horizontally by default or vertically with orientation="vertical". CarouselPrevious and CarouselNext are round Buttons that sit outside the slides, or inline when placed in CarouselControls.
CarouselDots shows one dot per snap point, with the active dot stretched into a pill; with autoplay on, the active dot fills up as a timer. CarouselPlayButton pauses and resumes autoplay.
Installation
The CLI also adds what it builds on: Button, Icon. On React Native it also adds the animated view components/ui/animated-view.tsx.
Manual
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, and the primitives
components/primitives/carousel.tsx,components/primitives/use-render.tsx, and the animated viewcomponents/ui/animated-view.tsxfrom the next step. -
Copy the animated view into
components/ui/animated-view.tsx:
- Copy the source into
components/ui/carousel.tsx:
- Update the import paths to match your project.
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, and the primitives
components/primitives/carousel.tsx,components/primitives/use-render.tsx, and the animated viewcomponents/ui/animated-view.tsxfrom the next step. -
Copy the animated view into
components/ui/animated-view.tsx:
- Copy the source into
components/ui/carousel.tsx:
- Update the import paths to match your project.
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, and the primitives
components/primitives/carousel.tsx,components/primitives/use-render.tsx, and the animated viewcomponents/ui/animated-view.tsxfrom the next step. -
Copy the animated view into
components/ui/animated-view.tsx:
- Copy the source into
components/ui/carousel.tsx:
- Update the import paths to match your project.
-
Target iOS 17 or later.
-
Add the Swift package to your app:
- Copy the theme files every view uses:
- Copy the source and every file it uses:
- Add the files to your app target.
- Set
minSdkto 24 or higher and add the dependencies:
- Copy the theme files every view uses:
- Copy the source and every file it uses:
- Update the
com.esuiss.uipackage names to match your project.
Usage
Set each slide's width with basis on CarouselItem, as a fraction of the viewport (for example 0.5 for two per view). Use opts for loop, align (start or center) and dragFree scrolling without snapping.
Pass autoplay as true for the default 5-second delay, or as a number of milliseconds. Put CarouselDots, CarouselPlayButton and nav buttons inside CarouselControls to show them in a row below the slides; CarouselDots takes variant="plain" to drop its background.
Use setApi to get a CarouselApi for scrolling from outside, or call useCarousel() inside the carousel to read the selected index and scroll state.
Examples
Multiple items
Two slides per view with basis={0.5}.
Web preview
Loop
Wraps around from the last slide to the first.
Web preview
Vertical
A vertical carousel with arrows above and below.
Web preview
With page indicator
Full-width cards with a page indicator below.
Web preview
Featured
Peeking cards with plain dots and a play button.
Web preview
Spotlight
A looping showcase with dots and an inline next button.
Web preview
Autoplay
Advances every four seconds, with progress dots and a play button.
Web preview
Shelf
A free-scrolling shelf of small cards with dragFree.
Web preview
API Reference
Carousel
Root that holds the scroll state and options.
Also accepts the props of React.ComponentProps<typeof CarouselPrimitive.Root>.
CarouselContent
Scrolling track for the slides.
Also accepts the props of React.ComponentProps<typeof CarouselPrimitive.Content>.
CarouselItem
One slide.
Also accepts the props of React.ComponentProps<typeof CarouselPrimitive.Item>.
CarouselPrevious
Button that scrolls to the previous slide.
Also accepts the props of React.ComponentProps<typeof Button>.
CarouselNext
Button that scrolls to the next slide.
Also accepts the props of React.ComponentProps<typeof Button>.
CarouselControls
Row that lays out dots and buttons below the slides.
Also accepts the props of ViewProps.
CarouselDots
One pressable dot per snap point.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "plain" | "default" | default (on a control background) or plain. |
Also accepts the props of ViewProps.
CarouselPlayButton
Toggles autoplay.
Also accepts the props of React.ComponentProps<typeof Button>.
Accessibility
- Previous and next buttons have the
buttonrole and are labelled "Previous slide" and "Next slide", with a disabled state at the ends. - Each dot is labelled "Go to slide N" and marks the current slide as selected.
- The play button is labelled "Pause slideshow" or "Play slideshow".
Notes
- Arrow icons are mirrored in right-to-left layouts.
- Dot and progress animations respect the system Reduce Motion setting.
- Uses
bg-secondary,bg-foregroundandbg-muted-foregroundtokens; light and dark follow the system appearance.