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#

typescript
import { Carousel } from "@reactberry/system/blocks";

Usage#

typescript
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.

Step 1 of 4
Step 1Create an account
Step 2Invite your team
Step 3Connect a repository
Step 4Deploy your first app

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#

PropTypeDefaultDescription
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. center needs the caller to make room at both ends (an inline padding of half the viewport less half an item), so the first and last items can reach the middle too.

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 div with no role or label.
  • The arrow controls are div elements (see Controls) with no role and no tabindex, 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 or gap is not 16px.
  • onScroll fires on every scroll change, not only when the index changes.
  • The scroll container has p="xs" and a 0.5rem scroll padding by default. containerProps can override the padding.
  • On mount the track scrolls back to the start (unless activeIndex is set), and history.scrollRestoration is set to "manual" until the carousel unmounts.