Capítulo 68 de 108
Carrossel com suporte a swipe e motion, construído sobre a lib Embla Carousel. Controla tamanho/espaçamento dos slides via classes Tailwind (basis-*, pl-*/-ml-*), não via props dedicadas.
opts: objeto repassado direto para o Embla (align, loop, direction, etc) — ver docs do Embla para todas as opções.orientation: "horizontal" | "vertical".plugins: array de plugins Embla (ex. embla-carousel-autoplay) passados ao Carousel.setApi: prop que expõe a instância da API Embla via callback de estado, permitindo controle programático (slide atual, total, navegação, eventos .on("select", ...)).basis-* (ou basis-1/2 lg:basis-1/3 responsivo) no CarouselItem, não uma prop size.pl-[VALUE] no CarouselItem combinado com -ml-[VALUE] no CarouselContent (offset negativo compensando o padding).<Carousel className="w-full max-w-xs">
<CarouselContent>
{Array.from({ length: 5 }).map((_, index) => (
<CarouselItem key={index}>
<Card><CardContent className="flex aspect-square items-center justify-center p-6">{index + 1}</CardContent></Card>
</CarouselItem>
))}
</CarouselContent>
<CarouselPrevious />
<CarouselNext />
</Carousel>
"use client"
export function CarouselDApiDemo() {
const [api, setApi] = React.useState<CarouselApi>()
const [current, setCurrent] = React.useState(0)
const [count, setCount] = React.useState(0)
React.useEffect(() => {
if (!api) return
setCount(api.scrollSnapList().length)
setCurrent(api.selectedScrollSnap() + 1)
api.on("select", () => setCurrent(api.selectedScrollSnap() + 1))
}, [api])
return (
<Carousel setApi={setApi}>
{/* ... */}
</Carousel>
)
}
setApi para exibir "Slide X of Y" e reagir ao evento select.const plugin = React.useRef(Autoplay({ delay: 2000, stopOnInteraction: true }))
<Carousel
plugins={[plugin.current]}
onMouseEnter={plugin.current.stop}
onMouseLeave={plugin.current.reset}
>
Carousel
├── CarouselContent
│ ├── CarouselItem
│ └── CarouselItem
├── CarouselPrevious
└── CarouselNext
basis-* sem responsividade em carrosséis multi-item: gera overflow ou itens minúsculos em telas pequenas; use breakpoints (md:basis-1/2 lg:basis-1/3).opts={{ direction: dir }}: definir só dir="rtl" no elemento não inverte a direção de scroll do Embla — é preciso passar direction explicitamente em opts.basis-*, pl-*/-ml-*), não props do componente.setApi + useEffect é o padrão para expor estado (slide atual, contagem) ou reagir a eventos do carrossel.plugins, referência estável recomendada com useRef.dir no componente quanto direction em opts precisam ser setados, e os botões de navegação geralmente precisam de rtl:rotate-180.Card.CarouselItem para manter proporção consistente de mídia.