Carousel
Build horizontally scrollable rows of cards, steps, or media with Reactberry's Carousel block.
Carousel is a client component that renders a horizontally scrollable row with scroll snapping and optional arrow controls. Use it for feature cards, onboarding steps, media previews and other sequences that people browse sideways, especially on small screens.
Starter
One project and community support.
Team
Unlimited projects and shared workspaces.
Business
SSO, audit logs and priority support.
Enterprise
Custom contracts and a dedicated manager.
Import#
import { Carousel } from "@reactberry/system/blocks";
Usage#
import { Carousel } from "@reactberry/system/blocks";
import { Box, Text } from "@reactberry/system/elements";
const items = ["Starter", "Team", "Business"].map((plan) => (
<Box key={plan} width="16rem" p="m" skin="surface" shape="rounded">
<Text fontWeight="700">{plan}</Text>
</Box>
));
export default function Plans() {
return <Carousel items={items} gap="m" />;
}
Examples#
Track the current slide#
onScroll receives the current slide index, so outside UI can follow along. Here the arrows are hidden and the scrollbar is shown.
Select a slide and fade the edges#
Pass activeIndex to scroll a slide into view when your own state changes. withMask fades whichever edge still has slides behind it.
API#
Carousel#
| Prop | Type | Default | Description |
|---|---|---|---|
items* | ReactNode[] | — | Slides, each wrapped in a snap item. |
gap | string | number | s | Space between slides. |
onScroll | ((index: number) => void) | — | Called with the index of the current slide while the track scrolls. |
showScrollbar | boolean | false | Shows the horizontal scrollbar. |
showArrows | boolean | true | Shows the previous/next arrow controls under the track when there is more than one item. |
containerProps | { [key: string]: any; } | — | Props spread onto the scroll container, after its defaults. |
activeIndex | number | — | Brings an item into view when the caller owns the selection. Scrolling by hand is left alone: only a change the caller makes moves the track. |
align | "start""center" | "start" | Where an item comes to rest. |
withMask | boolean | false | Fades whichever end still has items behind it. Off by default so an existing track keeps its hard edges. |
maskWidth | string | 3rem | How far the fade reaches in from a faded edge, as any CSS length. |
No other props are accepted. Use containerProps for layout and style props on the scroll container.
Accessibility#
- The scroll container is a plain
divwith no role or label. - The arrow controls are
divelements (see Controls) with no role and notabindex, so they can't be reached with the keyboard. Slides are only reachable through focusable content inside them.
Notes#
- Give each slide a stable width. Slides don't shrink, and each one is a mandatory snap point.
- The arrows scroll by 300px per click, not by one slide. The left arrow is hidden on the first slide; the right arrow fades to 30% opacity on the last one.
- With
align="start", the current index is calculated from the first slide's width and a fixed 16px gap, so it can drift when slides have different widths orgapis not 16px. onScrollfires on every scroll change, not only when the index changes.- The scroll container has
p="xs"and a0.5remscroll padding by default.containerPropscan override the padding. - On mount the track scrolls back to the start (unless
activeIndexis set), andhistory.scrollRestorationis set to"manual"until the carousel unmounts.