A looping carousel with neighbours peeking in and a progress dot per card: autoplay pauses on interaction and off screen, and waits for Play with reduced motion.
Installation
Add it with the shadcn CLI, or copy the source by hand.
$ pnpm dlx shadcn@latest add @ssntl/carouselAPI reference
Carousel
duration?Type:numberHow long each card stays up during autoplay, in ms.Default:5000
Also takes every prop of <div>.
CarouselTabList
aria-labelrequiredType:stringNames the set: “Our clients' businesses”.Default:—
Also takes every prop of <div>.
CarouselPlayButton
playLabel?Type:stringDefault:"Play carousel"pauseLabel?Type:stringDefault:"Pause carousel"
Also takes every prop of Button.
No props of their own: each passes every prop to the element on the right.
CarouselContent<div>CarouselItem<li>CarouselControls<div>CarouselTab<button>
useCarouselItem()
The enclosing item's state. Content also renders in clones: check isClone before playing media or tracking impressions.
Returns
indexType:numberThe item's position among the items in CarouselContent.isCurrentType:booleanWhether this item is the one being shown.isCloneType:booleanWhether this copy is a clone that keeps the loop seamless.
Rules
What this component expects from you, as it ships in components/ui/carousel.md next to the code. The full file adds when to use it, keyboard, the UI foundations it applies and every shared rule.
## Rules for Carousel
- **Pausing.** Autoplay has a play button (WCAG 2.2.2) and pauses by itself when people scroll, swipe, focus a dot or the carousel leaves the screen.
- **Reduced motion.** No autoplay until Play is pressed, and cards jump instead of sliding.
- One tab per card, in the same order, whose text names the card; arrows, Home and End move between them (WAI-ARIA carousel with tabs).
- Only the current card can be reached: clones and peeking cards are inert, so nobody follows a link on a card they aren't looking at.
- The progress fill is the clock: a scale animation on the compositor that pauses in place; the dot grows into a pill over `--duration-panel`.
- Dots are 8px; the target around each is at least 32 × 48px, well over WCAG's 24px for a dense set.
- Photos fill the card with a 1px outline at 10%; a caption sits on a dark fade, and peeking cards dim theirs.
- **Content also renders in clones.** Check `isClone` (`useCarouselItem`) before playing media or tracking impressions.




