Components / structure

Carousel

Its keep-or-cut decision is on the v3 plan for week nine, alongside Feed, and it has not been made.

Rendered from the package · open on its own

Summary

A rotating set of slides.

APG patternCarousel
Built onnative elements
Statusstable
Since0.1.0
<Carousel label="Featured work" autoRotate slides={…} />

Anatomy

A data-se="carousel" region with a viewport, slides, controls and dots.

PartElementRequired
controls<div>yes
dot<button>yes
dots<div>yes
label<span>yes
slide<div>yes
viewport<div>yes

Properties

PropertyValuesDefaultWhat it does
slidesCarouselSlide[]requiredThe slides, in rotation order. Each needs a label — it names the slide in the dots and is the only text a reader gets before choosing to go there.
labelstringrequiredNames the carousel region. Required in practice: an unnamed region is one a screen reader can enter and cannot describe.
autoRotatebooleanfalseAdds a Pause control. Rotation always stops on hover and on focus.
intervalnumber5000Milliseconds between slides when autoRotate is on. Rotation stops on hover and on keyboard focus anywhere inside, so this is a ceiling rather than a promise.

States

StateExpressed as
Pressed:active
Disabled:disabled
Focused:focus-visible
Hover:hover
Currentaria-current

Behavior

Rotation is pausable by a visible control and stops on hover and on keyboard focus anywhere inside. A carousel that moves while someone is reading it is worse than no carousel.

Accessibility

The controls carry aria-controls pointing at the slide container, which needed an id it did not have until the upstream port found it.

Each slide is named and counted, so a reader knows there are others and how many.

Reduced motion stops the rotation, through the reset rather than a check here.

Keyboard

None of its own. The previous, next and pause controls are ordinary tab stops; Enter or Space activates them.

Roles, states and properties

AttributeSet by
aria-atomicalways false
aria-controlsset at render
aria-currentset at render
aria-disabledset at render
aria-labelset at render, always Choose slide to display
aria-liveset at render
aria-roledescriptionalways carousel, always slide
rolealways region, always group

Focus

Rotation stops on keyboard focus anywhere inside, and on hover. A carousel that moves while someone is reading it is worse than no carousel. Focus is never moved onto a slide as it rotates.

Screen reader

Not recorded as verified. Stage 4 of the readiness ladder — driving each component with VoiceOver and NVDA — is unstarted across the package, and no component should claim otherwise until docs/journal/ records the session that did it.

Contrast and target size

npm run check:contrast audits every color pair this component uses across all four skins, light and dark, and fails the build on a shortfall. Two waivers are on the record in docs/audit/DEFERRED.md.

It takes the touch floor under (pointer: coarse) — the visual size is unchanged on a desktop pointer.

Tested

  • test/apg/batch-a.test.jsx
  • test/apg/batch-d.test.jsx
  • test/apg/partials-sweep.test.jsx
  • test/browser/upstream-natives.spec.mjs

Known gaps

  • 18 upstream refs — the tablist variant is the tabs pattern

Appearance

TokenUsed for
--se-accentbackground, intent
--se-bgbackground, border-color
--se-borderborder, border-color
--se-border-strongbackground
--se-border-widthborder, border-width
--se-control-hblock-size, inline-size
--se-control-h-lgblock-size, inline-size
--se-control-h-smblock-size, inline-size
--se-duration-instanttransition
--se-ease-standardtransition
--se-focus-coloroutline
--se-focus-offsetoutline-offset
--se-focus-widthoutline
--se-mix-downbackground, border-color
--se-mix-hoverbackground, border-color
--se-mix-lineborder-color
--se-mix-pressbackground
--se-mix-shadebackground, border-color
--se-mix-softbackground
--se-negativeintent
--se-positiveintent
--se-radius-lgborder-radius
--se-radius-pillborder-radius
--se-space-1gap
--se-space-2block-size, gap, inline-size, padding
--se-space-3gap, padding-inline
--se-space-4padding-inline
--se-space-5padding, padding-inline
--se-surface-sunkbackground
--se-target-minblock-size, inline-size, min-block-size, min-inline-size, padding
--se-textintent
--se-text-disabledcolor
--se-text-mdfont-size
--se-text-on-intentcolor
--se-text-xsfont-size

Motion

Slides cross over --se-duration-medium. The dots do not animate.

Content

Each slide's label names it for the dots and for a screen reader — it is the only text a reader gets before choosing to go there.

Usage

Ask whether you need one first. Most carousels exist because nobody would decide what matters most, and readers overwhelmingly see only the first slide. A stack usually serves them better, and a data-se-layout="grid" of cards serves them better still.

The baseline survey rates it high cost, low value, hard accessibility and recommends deferring indefinitely. It is built here, which is a fact about the batch order rather than a recommendation.

Notes

One of four patterns with no upstream test suite, so nothing external will catch a regression.

Its keep-or-cut decision is on the v3 plan for week nine, alongside Feed, and it has not been made.