Preview
Design guidance
Use a carousel when related cards share one reading order and users need to focus on one or a few at a time. Give the region a concise aria-label. Slides retain their content semantics; offscreen slides are temporarily inert so their controls do not enter the Tab order. Previous and next buttons follow the engine's actual boundary state.
Installation
The component uses embla-carousel-react 8.6.0. Install it with the Ghost UI source bundle when using a local/manual source install. The nested editing example also composes the input registry item.
Basic usage
Structures
Content owns the viewport and its direct Item children. Navigation and status parts can sit beside it inside the root. Give each slide a stable key when the collection changes.
Examples
Multiple visible cards
Set item basis to show part of the next card and signal that more content follows.
Vertical with a fixed viewport
Vertical carousels need an explicit content height so the viewport has a useful size.
Direct slide indicators
Indicators call the engine's scrollTo method and expose a โGo to slide Nโ name.
Looping
Enable opts.loop when the ordered collection is useful as a continuous sequence.
Loop from the last card
Start at the last draft to show that previous and next navigation wrap across the collection boundary.
Empty and single slide
An empty collection reports 0 / 0; a single item keeps both navigation controls disabled.
No drafts yet
Focusable and nested controls
Controls inside the current slide remain usable. Offscreen slide controls are removed from keyboard focus until their slide is visible.
Inherited RTL direction
The Embla direction follows the rendered region or its nearest dir ancestor.
Changing drafts
Add or remove a follow-up draft while retaining the current collection.
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
opts | EmblaOptionsType | Embla options such as loop and align. Axis follows orientation and direction follows the rendered dir. | |
orientation | 'horizontal' | 'vertical' | 'horizontal' | Selects the Embla axis. Vertical content needs a caller supplied viewport height. |
aria-label | string | Native region label. Supply a concise name for the carousel. | |
className / style / native props | HTMLAttributes<HTMLElement> | Forwarded to the native section region. |
| Prop | Type | Default | Description |
|---|---|---|---|
Content children | ReactNode | Direct Carousel.Item children; reinitializes Embla when the item count changes. | |
Content native props | HTMLAttributes<HTMLDivElement> | Forwarded to the Embla container. The library attaches its viewport ref to the outer viewport. | |
Item children | ReactNode | Caller-owned slide content. | |
Item native props | HTMLAttributes<HTMLDivElement> | Forwarded to the slide group. Offscreen slides become inert until visible. |
| Prop | Type | Default | Description |
|---|---|---|---|
Previous / Next | IconButton props | Canonical icon buttons, outline by default; native IconButton props can override the style. Disabled at empty, single-slide, or non-loop boundaries. Native button keyboard behavior is preserved. | |
Count | HTMLAttributes<HTMLSpanElement> | Polite live count of the current scroll snap and snap total. | |
Indicators | HTMLAttributes<HTMLDivElement> | Renders one named native button per scroll snap; each calls Embla scrollTo. |
Carousel navigation uses Embla Carousel React 8.6.0 and no autoplay. Reduced-motion users receive immediate engine navigation.
useCarousel() exposes the current Embla api, selected snap, snap count, visible slide indexes, orientation and reading direction to custom parts inside the root. Arrow keys act only while the viewport itself has focus; controls inside a slide retain their own keyboard behavior.