Basel Standard / Docs
Carousel
Embla-powered carousel primitives for horizontal or vertical sequences with Swiss-styled controls.
Slide 01
Slide 02
Slide 03
Use the carousel when content belongs in a deliberate sequence, not when the layout is simply too crowded. The Swiss wrapper keeps Embla's interaction model and adds shared navigation buttons, orientation support, and structure for slides that still feel like normal layout blocks.
Installation
Purchase access, then open /account/install to issue a registry token.Usage
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel"
<Carousel>
<CarouselContent>
<CarouselItem>Slide one</CarouselItem>
<CarouselItem>Slide two</CarouselItem>
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
Why This Primitive Exists
The carousel gives the system a reusable sequence container without making every team wire Embla by hand.
- Use it for related frames such as product cards, launch steps, or media highlights.
- Prefer it when people should move forward and backward through a curated set.
- Avoid it for critical content that must stay visible all at once.
Examples
Basic Sequence
The root sets up the carousel region and keyboard handling, while CarouselContent and CarouselItem establish the slide track.
Slide 01
Slide 02
Slide 03
<Carousel>
<CarouselContent>
<CarouselItem>Slide one</CarouselItem>
<CarouselItem>Slide two</CarouselItem>
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
Multi-Item Shelf
Change each CarouselItem basis to show more than one card at a time. This pattern works well for product shelves or related content rails where each slide is still self-contained.
Sampling
Material review for the spring collection.
Capture
Photography queue and image approvals.
Launch
Merchandising copy, pricing, and shelf order.
Aftercare
Support notes and replacement stock.
<Carousel opts={{ align: "start" }}>
<CarouselContent>
<CarouselItem className="md:basis-1/2 lg:basis-1/3">{/* ... */}</CarouselItem>
</CarouselContent>
</Carousel>
In Context
Carousels become much more legible when the surrounding card or section explains what the sequence is about and why the user should move through it.
Editorial rail
<Carousel opts={{ loop: true }}>
<CarouselContent>{/* editorial or product frames */}</CarouselContent>
</Carousel>
Guidance
Use Sequence Intentionally
- Put content in a carousel only when order matters.
- Keep each slide meaningful on its own so the user can stop anywhere.
- If readers need to compare all items at once, a grid is usually better.
Control Slide Width On The Item
CarouselItemdefaults tobasis-full, so one slide fills the viewport.- Override with width utilities like
md:basis-1/2orlg:basis-1/3to create shelves. - Keep slide padding consistent because the wrapper uses negative margins on the content track.
Choose Navigation Placement Deliberately
- The built-in previous and next controls are absolutely positioned by default.
- Override with
className="static translate-x-0 translate-y-0"when controls should sit in a footer or toolbar row. - The root already supports left and right arrow key navigation, so avoid duplicating custom keyboard logic unless the interaction truly changes.
API Reference
Core Exports
| Export | Renders | Notes |
|---|---|---|
Carousel | div | Creates the Embla context, region semantics, and keyboard navigation. |
CarouselContent | div | Viewport and track wrapper; applies orientation-aware spacing. |
CarouselItem | div | Individual slide with role="group" and aria-roledescription="slide". |
CarouselPrevious | Button | Scrolls backward and disables automatically when the start is reached. |
CarouselNext | Button | Scrolls forward and disables automatically when the end is reached. |
Carousel Props
| Prop | Type | Default | Notes |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" | Maps to Embla's axis option. |
opts | CarouselOptions | undefined | Passed directly to useEmblaCarousel. |
plugins | CarouselPlugin | undefined | Lets you add Embla plugins. |
setApi | (api: CarouselApi) => void | undefined | Exposes the Embla API to parent code. |
Types
The module also exports CarouselApi, which is the Embla API instance type returned through setApi.