Carousel
A carousel is a region component for cycling through a set of slides or content items, such as image galleries, product showcases, or testimonial rotators. It provides the semantic container with appropriate ARIA roledescription so assistive technologies announce it as a carousel.
The consumer is responsible for providing the slide content as children and implementing navigation controls (previous/next buttons, pagination dots, autoplay logic, etc.). This headless approach gives full control over navigation behavior, animation, and layout while ensuring accessibility compliance.
Implementation Notes
- Renders a
<div>withrole="region"andaria-roledescription="carousel"to communicate the carousel pattern to screen readers. - The
aria-labelprop provides an accessible name for the region. - Slide content is passed via the
childrenslot, allowing any markup structure. - Spreads
restPropsonto the container for consumer customization. - No internal state management for active slide; consumers manage slide state externally.
Props
label: string (required) -- accessible name for the carousel region, applied viaaria-label.children: slot (required) -- slide content to render inside the carousel container....restProps: unknown -- additional attributes spread onto the container<div>.
Usage
<Carousel label="Customer testimonials">
<div role="group" aria-roledescription="slide" aria-label="Slide 1 of 3">
<blockquote>
<p>"The service transformed how we manage patient records."</p>
<cite>Dr Sarah Mitchell, GP</cite>
</blockquote>
</div>
<div role="group" aria-roledescription="slide" aria-label="Slide 2 of 3">
<blockquote>
<p>"Setup took less than a day and the team was incredibly helpful."</p>
<cite>James O'Brien, Practice Manager</cite>
</blockquote>
</div>
<div role="group" aria-roledescription="slide" aria-label="Slide 3 of 3">
<blockquote>
<p>"We reduced administrative time by 40% in the first month."</p>
<cite>Nurse Karen Phillips</cite>
</blockquote>
</div>
</Carousel>
<Carousel label="Featured articles">
<div role="group" aria-roledescription="slide" aria-label="Slide 1 of 2">
<Image src="/images/article-1.jpg" alt="Accessible design patterns" />
<h3>Building Accessible Forms</h3>
<p>Learn how to create forms that work for everyone.</p>
</div>
<div role="group" aria-roledescription="slide" aria-label="Slide 2 of 2">
<Image src="/images/article-2.jpg" alt="Component composition" />
<h3>Component Composition Patterns</h3>
<p>How to combine headless components for complex UIs.</p>
</div>
</Carousel>
Keyboard Interactions
None -- this component is a passive container. The consumer should implement keyboard navigation for slide controls (e.g., previous/next buttons respond to Enter and Space, arrow keys for slide navigation).
ARIA
role="region"-- identifies the carousel as a landmark region so screen readers can navigate to it.aria-roledescription="carousel"-- overrides the default "region" announcement with "carousel" for clearer context.aria-label-- provides an accessible name describing the carousel content.
When to Use
- Use for cycling through a set of related content items, such as testimonials, featured articles, or image galleries
- Use when screen space is limited and content can be browsed sequentially
- Use for showcasing a curated set of promotions, portfolio pieces, or product highlights
- Use when the content items are of equal importance and none is critical on its own
When Not to Use
- Do not use for critical content that users must not miss -- carousels are often ignored or skipped
- Do not use when all items need to be visible simultaneously -- use a grid of Cards instead
- Do not use for navigation -- use TabBar or ContentsNav for switching between content panels
- Do not use for a single content item -- use Hero or Card instead
Headless
This headless Carousel component provides the semantic container with role="region", aria-roledescription="carousel", and aria-label for screen reader identification. The consumer provides all visual styling, slide navigation controls (previous/next buttons, pagination dots), autoplay logic, transition animations, and slide layout.
Styles
The consumer provides all CSS styling. The component renders with a .carousel class for targeting. No default styles are included — this is a fully headless component.
Testing
- Verify the component renders a
<div>element with classcarousel - Verify role="region"` -- identifies the carousel as a landmark region so screen readers can navigate to it.
- Verify aria-label` -- provides an accessible name describing the carousel content.
- Verify pass-through attributes are applied
Advice
- Designers: Provide clear navigation indicators (dots or arrows) so users understand there is more content to view. Avoid autoplay or provide a visible pause control.
- Developers: Mark each slide with
role="group"andaria-roledescription="slide"with anaria-labelindicating position (e.g., "Slide 1 of 5"). Implement keyboard navigation for slide controls.
Related components
photo-pack— see components.tsvscroller— see components.tsvhorizontal-scroller— see components.tsvimage— an image element with alt text
References
- WAI-ARIA Carousel Pattern: https://www.w3.org/WAI/ARIA/apg/patterns/carousel/
- WAI-ARIA Authoring Practices Carousel: https://www.w3.org/WAI/tutorials/carousels/