# Carousel

> Touch-friendly content rotator with autoplay, indicators, keyboard navigation, and reduced-motion support.

- Available in: `@sisyphos-ui/react`, `@sisyphos-ui/vue`, `@sisyphos-ui/angular`
- Docs: https://sisyphosui.com/docs/components/carousel

## Installation

Pick the framework binding that matches your stack:

```bash
pnpm add @sisyphos-ui/react   # React 18+
pnpm add @sisyphos-ui/vue     # Vue 3+
pnpm add @sisyphos-ui/angular # Angular 17+
```

## Import

```tsx
import "@sisyphos-ui/react/styles.css";
import { Carousel } from "@sisyphos-ui/react";
```

## Framework usage

### React 18+

```tsx
import { Carousel } from "@sisyphos-ui/react";

export const Slides = () => (
  <Carousel autoplay>
    <Carousel.Slide><img src="/a.jpg" alt="" /></Carousel.Slide>
    <Carousel.Slide><img src="/b.jpg" alt="" /></Carousel.Slide>
    <Carousel.Slide><img src="/c.jpg" alt="" /></Carousel.Slide>
  </Carousel>
);
```

### Vue 3+

```vue
<script setup lang="ts">
import { Carousel, CarouselSlide } from "@sisyphos-ui/vue";
</script>

<template>
  <Carousel :autoplay="true">
    <CarouselSlide><img src="/a.jpg" alt="" /></CarouselSlide>
    <CarouselSlide><img src="/b.jpg" alt="" /></CarouselSlide>
    <CarouselSlide><img src="/c.jpg" alt="" /></CarouselSlide>
  </Carousel>
</template>
```

### Angular 17+

```ts
import { Component } from "@angular/core";
import { Carousel } from "@sisyphos-ui/angular";

@Component({
  selector: "app-slides",
  standalone: true,
  imports: [Carousel],
  template: `
    <sui-carousel [autoplay]="true">
      <ng-template carousel-slide><img src="/a.jpg" alt="" /></ng-template>
      <ng-template carousel-slide><img src="/b.jpg" alt="" /></ng-template>
    </sui-carousel>
  `,
})
export class SlidesComponent {}
```

## Examples

### Default

```tsx
import { Carousel } from "@sisyphos-ui/react";

const SLIDES = [
  { bg: "#ff7022",  title: "Ship faster" },
  { bg: "#10b981",  title: "Stay accessible" },
  { bg: "#3b82f6",  title: "Theme at runtime" },
];

export function Example() {
  return (
    <Carousel className="w-full max-w-xl">
      {SLIDES.map((s) => (
        <div
          key={s.title}
          style={{ background: s.bg }}
          className="flex aspect-[16/9] items-center justify-center rounded-lg text-white text-2xl font-bold"
        >
          {s.title}
        </div>
      ))}
    </Carousel>
  );
}
```

### Auto-play

Enable `autoPlay` and tune the pace with `autoPlayInterval`. Pauses on hover/focus.

```tsx
import { Carousel } from "@sisyphos-ui/react";

const SLIDES = [
  { bg: "#ff7022", title: "Ship faster" },
  { bg: "#10b981", title: "Stay accessible" },
  { bg: "#3b82f6", title: "Theme at runtime" },
];

function Slide({ bg, title }: { bg: string; title: string }) {
  return (
    <div
      style={{
        background: bg,
        aspectRatio: "16 / 9",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#fff",
        fontWeight: 700,
        fontSize: 28,
        borderRadius: 12,
      }}
    >
      {title}
    </div>
  );
}

export function Example() {
  return (
    <Carousel autoPlay autoPlayInterval={2500}>
      {SLIDES.map((s) => <Slide key={s.title} {...s} />)}
    </Carousel>
  );
}
```

### No loop

`loop={false}` stops wrapping — arrows disable at the edges.

```tsx
import { Carousel } from "@sisyphos-ui/react";

const SLIDES = [
  { bg: "#ff7022", title: "Ship faster" },
  { bg: "#10b981", title: "Stay accessible" },
  { bg: "#3b82f6", title: "Theme at runtime" },
];

function Slide({ bg, title }: { bg: string; title: string }) {
  return (
    <div
      style={{
        background: bg,
        aspectRatio: "16 / 9",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#fff",
        fontWeight: 700,
        fontSize: 28,
        borderRadius: 12,
      }}
    >
      {title}
    </div>
  );
}

export function Example() {
  return (
    <Carousel loop={false} defaultIndex={1}>
      {SLIDES.map((s) => <Slide key={s.title} {...s} />)}
    </Carousel>
  );
}
```

### Dots only

Hide arrow controls with `showArrows={false}` for pure dot-driven navigation.

```tsx
import { Carousel } from "@sisyphos-ui/react";

const SLIDES = [
  { bg: "#ff7022", title: "Ship faster" },
  { bg: "#10b981", title: "Stay accessible" },
  { bg: "#3b82f6", title: "Theme at runtime" },
];

function Slide({ bg, title }: { bg: string; title: string }) {
  return (
    <div
      style={{
        background: bg,
        aspectRatio: "16 / 9",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#fff",
        fontWeight: 700,
        fontSize: 28,
        borderRadius: 12,
      }}
    >
      {title}
    </div>
  );
}

export function Example() {
  return (
    <Carousel showArrows={false}>
      {SLIDES.map((s) => <Slide key={s.title} {...s} />)}
    </Carousel>
  );
}
```

### Controlled index

Drive the carousel from outside UI with `index` + `onIndexChange`.

```tsx
import { useState } from "react";
import { Button, Carousel } from "@sisyphos-ui/react";

const SLIDES = [
  { bg: "#ff7022", title: "Ship faster" },
  { bg: "#10b981", title: "Stay accessible" },
  { bg: "#3b82f6", title: "Theme at runtime" },
];

function Slide({ bg, title }: { bg: string; title: string }) {
  return (
    <div
      style={{
        background: bg,
        aspectRatio: "16 / 9",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#fff",
        fontWeight: 700,
        fontSize: 28,
        borderRadius: 12,
      }}
    >
      {title}
    </div>
  );
}

export function Example() {
  const [index, setIndex] = useState(0);

  return (
    <>
      <Button disabled={index === 0} onClick={() => setIndex(i => i - 1)}>Prev</Button>
      <Button disabled={index === SLIDES.length - 1} onClick={() => setIndex(i => i + 1)}>Next</Button>
      <Carousel index={index} onIndexChange={setIndex} loop={false}>
        {SLIDES.map((s) => <Slide key={s.title} {...s} />)}
      </Carousel>
    </>
  );
}
```

<!-- exports: { "Carousel": "@sisyphos-ui/react" } -->