Carousel
One slide at a time with previous/next controls and a roving dot group.
Rendering Carousel…
Installation
Copy the source into your project with the CLI. It lands under @/components/ui and is yours to edit.
npx mlola-ui add carouselUsage
import { Carousel } from "@/components/ui/carousel";
const slides = ["Plan", "Build", "Ship"].map((title) => (
<div key={title} className="ml-card" data-variant="elevated">
<div className="ml-card-content">{title}</div>
</div>
));
export default function Example() {
return <Carousel label="Release stages" items={slides} itemLabels={["Plan", "Build", "Ship"]} />;
}Styling comes from the engine stylesheet and the nearest theme. Set it once at the root:
<html data-theme="graphite" data-mode="light">HTML
The markup the example above renders, at rest. The interaction lives in the React component; from another framework, set the attributes below as the state changes.
<div class="ml-carousel" role="group" aria-roledescription="carousel" aria-label="Release stages" data-arrows="true" style="--ml-carousel-per-view:1;--ml-carousel-peek:0px;--ml-carousel-min:0px;--ml-carousel-autoplay:0ms">
<div class="ml-carousel-viewport">
<div class="ml-carousel-track" tabindex="0" aria-label="Release stages, use the arrow keys">
<div class="ml-carousel-slide" role="group" aria-roledescription="slide" aria-label="1 of 3: Plan" data-current="true">
<div class="ml-card" data-variant="elevated"><div class="ml-card-content">Plan</div></div>
</div>
<div class="ml-carousel-slide" role="group" aria-roledescription="slide" aria-label="2 of 3: Build">
<div class="ml-card" data-variant="elevated"><div class="ml-card-content">Build</div></div>
</div>
<div class="ml-carousel-slide" role="group" aria-roledescription="slide" aria-label="3 of 3: Ship">
<div class="ml-card" data-variant="elevated"><div class="ml-card-content">Ship</div></div>
</div>
</div>
<button class="ml-carousel-arrow" type="button" data-side="previous" aria-label="Previous slide"><svg class="mlola-glyph" width="1.1em" height="1.1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><path d="m15 18-6-6 6-6" pathLength="1"></path></svg></button>
<button class="ml-carousel-arrow" type="button" data-side="next" aria-label="Next slide"><svg class="mlola-glyph" width="1.1em" height="1.1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="var(--mlola-glyph-stroke, var(--ml-icon-stroke, 1.75))" stroke-linecap="round" stroke-linejoin="round" focusable="false" aria-hidden="true" data-optical-size="default" style="color:var(--mlola-glyph-color, currentColor);scale:var(--mlola-glyph-optical-scale, 1);transform-origin:center"><path d="m9 18 6-6-6-6" pathLength="1"></path></svg></button>
</div>
<div class="ml-carousel-dots" role="group" aria-label="Choose release stages">
<button class="ml-carousel-dot" type="button" data-hit="expand" aria-current="true" aria-label="Plan" tabindex="0"></button>
<button class="ml-carousel-dot" type="button" data-hit="expand" aria-label="Build" tabindex="-1"></button>
<button class="ml-carousel-dot" type="button" data-hit="expand" aria-label="Ship" tabindex="-1"></button>
</div>
</div>Options
| Prop | Values | Default | Description |
|---|---|---|---|
indicators | dotscounternone | dots | Dots under the slides, a counter, or nothing. |
Every prop with a fixed set of values, read from the exported TypeScript types with its doc comment. Open the Code tab above for the rest of the API.
Classes and attributes
A class names each element; data-* and aria-* attributes carry its variant and state. The values listed are the ones the stylesheet draws; the default needs no attribute.
| Class | Attributes |
|---|---|
ml-carousel | data-arrowsdata-playing |
ml-carousel-viewport | — |
ml-carousel-track | — |
ml-carousel-slide | — |
ml-carousel-arrow | data-side="next | previous" |
ml-carousel-dots | — |
ml-carousel-dot | aria-current="true" |
ml-carousel-dot-fill | — |
ml-carousel-counter | — |
Accessibility and theming
- Semantic elements, accessible names and state relationships are part of the contract.
- Keyboard, pointer and touch paths are operable; focus stays visible in every theme.
- Light and dark modes pass WCAG AA contrast in all 5 canonical themes.
- Reduced motion and forced colors keep meaning and operation.
Dependencies
Installed alongside this component. No third-party UI runtime is ever added.
@mlola-ui/behavior@mlola-ui/icons