Elements

Media carousel

View in Figma

Stateful media carousel with full-bleed slides, dot controls, and an optional caption slot.

Install

npx shadcn@latest add @alix/mediaCarousel

Preview

Consultants reviewing project notes at a table

Operations review

Images, controls, and caption content stay in one composed section.

Usage

<MediaCarousel ariaLabel="Operations review images" media={media}>
  <TextTileDefault
    bgColor="default"
    sectionTitle={{
      title: "Operations review",
      description: "Images, controls, and caption content stay together.",
      align: "start",
    }}
    buttonGroup={{}}
  />
</MediaCarousel>

Examples

01

Single slide

A single media item keeps the same frame and caption slot while hiding carousel controls.

Construction site with cranes

Project controls review

A single image can still share the carousel layout when more media may arrive later.
<div className="w-full max-w-2xl">
  <MediaCarousel
    ariaLabel="Site review image"
    media={[
      {
        src: "/brand/construction.webp",
        alt: "Construction site with cranes",
      },
    ]}
    ratio="4/3"
    bgColor="secondary"
  >
    <TextTileDefault
      bgColor="transparent"
      sectionTitle={{
        title: "Project controls review",
        description: "A single image can still share the carousel layout when more media may arrive later.",
        align: "start",
      }}
      buttonGroup={{}}
      leftBorder
    />
  </MediaCarousel>
</div>
02

Flipped caption

Flip the order when the copy should introduce the media before the user reaches the slides.

Consultants reviewing project notes at a table

Client workshop

The controls stay attached to the media even when the caption moves above the slide frame.
<div className="w-full max-w-3xl">
  <MediaCarousel
    ariaLabel="Client workshop images"
    media={media}
    bgColor="primary"
    flip
  >
    <TextTileDefault
      bgColor="transparent"
      sectionTitle={{
        title: "Client workshop",
        description: "The controls stay attached to the media even when the caption moves above the slide frame.",
        align: "start",
      }}
      buttonGroup={{}}
      leftBorder
    />
  </MediaCarousel>
</div>
03

Panel media review

Put the carousel inside a flush Panel when media review sits in a dashboard workspace.

Operational walkthrough

Images reviewed in the weekly steering meeting

Consultants reviewing project notes at a table

Steering evidence

Panel chrome names the workspace while the carousel owns slide state and controls.
<div className="w-full max-w-3xl">
  <Panel
    title="Operational walkthrough"
    description="Images reviewed in the weekly steering meeting"
    flush
  >
    <MediaCarousel
      ariaLabel="Operational walkthrough images"
      media={media}
      bgColor="default"
    >
      <TextTileDefault
        bgColor="transparent"
        sectionTitle={{
          title: "Steering evidence",
          description: "Panel chrome names the workspace while the carousel owns slide state and controls.",
          align: "start",
        }}
        buttonGroup={{}}
        leftBorder
      />
    </MediaCarousel>
  </Panel>
</div>

When to use it

Use it for

  • Image sets where previous, next, and dot controls should stay attached to the media frame.
  • Composed media sections where the caption can be any React node, often a TextTile.
  • Single-slide states that may grow into a carousel without changing the surrounding layout.

Reach for something else

  • Static hero or banner imagery — use MediaBanner instead.
  • A single framed image with no caption or controls — use AspectRatio instead.
  • CMS-ready multimedia sections with locked layout choices — use MultimediaBlock instead.

Props

PropTypeDefaultDescription
mediaMediaContent[]Image or video slide data, discriminated by type; an empty array renders nothing.
ratioAspectRatioToken"16/9"Aspect ratio for every slide frame.
bgColorBgColor"default"Section surface behind the controls and caption; media remains full-bleed.
flipbooleanfalseMirrors caption and media order while keeping controls attached to the media.
ariaLabelstringRequired accessible name for the carousel region.
childrenReactNodeCaption slot rendered beside the controls, not a shadow API for a text tile.

See also