Carousel
A scroll-snap track of slides with prev/next controls, dots, keyboard, and opt-in autoplay.
Live demo
Carousel lays its slotted children out as a horizontal scroll-snap track: each child is a slide, and the browser's own scrolling does the paging, so the track is swipeable and keyboard-scrollable with no JavaScript at all. When the runtime is present it grows a control bar, prev and next buttons (drawn with the chevron icons), a row of pagination dots that track and drive the active slide, and arrow-key and Home/End navigation, all wired over the same native scroll.
An opt-in autoplay advances the track on an interval, pausing on hover and focus and standing still entirely under prefers-reduced-motion; loop wraps the ends seamlessly, scrolling into an inert clone of the far slide and then silently snapping to the real one so the wrap never rewinds. The transition prop swaps the paging model: slide keeps the scroll-snap track, while fade, scale, and flip stack the slides and cross-fade the active one, so a testimonial or hero rotator can dissolve rather than slide. It is content-agnostic: the slides can be Images, Cards, or any markup, and it exposes itself as a labelled carousel region with each slide named for assistive tech.
Everything the carousel draws — the viewport, the track, the control bar, the arrows, the dots, and the play toggle — is its fragment's markup, so a mod can restyle or restructure the chrome (swap the chevrons for arrows, turn the dots into thumbnails, move the bar) without touching the scroll math, the keyboard, or the loop. The slides themselves are never re-authored: the fill's track is filled with the consumer's own nodes, so framework content stays live.
When to use
How this component composes with the rest of the set.
Props
10 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
Anatomy
The named parts that make up the component, with their selectors.
viewport
The clipping frame around the track. It sets the vertical carousel's height from --carousel-height.
track
The scroll-snap container that holds and pages the slides. The consumer's slides are relocated into it, so they stay the same live nodes they were authored as.
controls
The bar the arrows, dots, and play toggle sit in, below the track — or floated over the slides under controls="overlay".
nav
The prev/next buttons, each drawn with the chevron pointing the way the track advances.
play
The play/pause toggle an autoplay carousel grows, so the motion can always be stopped outright.
dots
The pagination dots; the active one takes the accent. When the theme's --selection-cue resolves to marker, the active dot also elongates into a pill so the current slide reads by shape, not color alone.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xtyle-default register
(derive(xtyleDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--accent
--bg-1
--bg-2
--bg-3
--border-thick
--border-thin
--duration-fast
--duration-slow
--ease-emphasized
--ease-standard
--elevation-2
--fg-1
--fg-2
--fg-3
--line-2
--radius-full
--ring
--selection-cue
--space-2
--space-3
--space-6
--surface-overlay
--surface-overlay-border
Slots
The slides. Each direct child becomes one slide in the track (an Image, a Card, or any markup).
Accessibility
Code
Image gallery
A few slides in a scroll-snap track with prev/next controls and dots.
<xtyle-carousel label="Product photos">
<img src="/a.jpg" alt="Front" />
<img src="/b.jpg" alt="Side" />
<img src="/c.jpg" alt="Back" />
</xtyle-carousel>
<script lang="ts">
import { Carousel } from "@xtyle/svelte";
</script>
<Carousel label="Product photos">
<img src="/a.jpg" alt="Front" />
<img src="/b.jpg" alt="Side" />
</Carousel>
---
import Carousel from "@xtyle/astro/Carousel.astro";
import Image from "@xtyle/astro/Image.astro";
---
<Carousel label="Gallery">
<Image src="/a.jpg" alt="First" ratio="16/9" />
<Image src="/b.jpg" alt="Second" ratio="16/9" />
</Carousel>
Autoplay and loop
An auto-advancing, looping track that pauses on hover or focus.
<xtyle-carousel label="Highlights" autoplay interval="4000" loop>
<div>Slide one</div>
<div>Slide two</div>
<div>Slide three</div>
</xtyle-carousel>
<script lang="ts">
import { Carousel } from "@xtyle/svelte";
</script>
<Carousel label="Highlights" autoplay interval={4000} loop>
<div>Slide one</div>
<div>Slide two</div>
</Carousel>
---
import Carousel from "@xtyle/astro/Carousel.astro";
---
<Carousel label="Highlights" autoplay interval={4000} loop>
<div>Slide one</div>
<div>Slide two</div>
</Carousel>
Fade transition
A stacked cross-fade instead of a sliding track, for a testimonial or hero rotator.
<xtyle-carousel label="Featured" transition="fade" autoplay loop>
<div>First</div>
<div>Second</div>
<div>Third</div>
</xtyle-carousel>
<Carousel label="Featured" transition="fade" autoplay loop>
<div>First</div>
<div>Second</div>
<div>Third</div>
</Carousel>
<Carousel label="Featured" transition="fade" autoplay loop>
<div>First</div>
<div>Second</div>
<div>Third</div>
</Carousel>