Carousel
Slides nativos com scroll-snap, com inércia no toque, arrastar com o mouse, setas do teclado, pontos, miniaturas e um autoplay que pausa quando deve.
pnpm dlx shadcn@latest add https://hextaui.com/r/carousel.jsonAdiciona o componente, os tokens de tema do HextaUI e quaisquer componentes do HextaUI dos quais ele depende.
Adicione os tokens de tema ao seu CSS global, se ainda não o fez.
Instale as dependências.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnCopie e cole o código a seguir no seu projeto.
components/ui/carousel.tsx components/ui/button.tsx components/ui/number-flow.tsx lib/motion.ts Atualize os caminhos de importação para corresponder à configuração do seu projeto.
Os slides rolam nativamente com o CSS scroll snap, então a inércia do toque e a rolagem do trackpad têm a sensação da plataforma. Um mouse pode arrastar, e as teclas de seta movem um slide por vez.
API
Passe setApi para obter a API do carousel e escute select para exibir a sua própria posição. Next fica desativado no último slide, mas mantém o foco.
Vários por vez
Os itens definem o próprio basis. Os espaçamentos vêm da prop spacing, então permanecem exatos em qualquer basis.
Pontos e contador
O ponto ativo se estica conforme os slides rolam e seus vizinhos abrem espaço. O contador gira apenas o dígito que mudou.
Autoplay
autoplay vem desativado por padrão e continua desativado com movimento reduzido. Ele pausa ao passar o mouse, com foco do teclado, toque, arraste, aba oculta ou quando sai da vista, e o ponto ativo se preenche conforme o temporizador corre.
Miniaturas
<CarouselThumbnails /> acompanha o carousel principal e rola para manter a miniatura ativa à vista.
Vertical
orientation="vertical" precisa de uma altura em <CarouselContent />. Os botões vão para cima e para baixo.
Controlado
Passe index e onIndexChange. Deslizar atualiza seu estado e seu estado rola o carousel.
Voltar ao início e índice inicial
rewind leva Next, no último slide, de volta ao primeiro. defaultIndex abre em um slide sem animação de rolagem.
Links e conteúdo focável
Arrastar um link com o mouse rola sem abri-lo. Navegar com Tab até um slide fora da tela o rola para a vista.
Adicionar e remover slides
Os pontos, o contador e os botões se atualizam conforme os slides entram e saem.
Aninhado
As teclas de seta, o arrastar e os pontos só movem o carousel em que você está.
Conteúdo longo e um único slide
Texto sem quebra é quebrado dentro do seu slide. Com um único slide, os pontos ficam ocultos e os botões permanecem desativados.
Da direita para a esquerda
Os slides começam pela direita, as setas se invertem, a tecla de seta para a esquerda avança e os pontos se preenchem a partir da direita.
As teclas funcionam com o foco em qualquer lugar dentro do carousel, exceto em campos de texto e carousels aninhados.
| Tecla | Ação |
|---|---|
| → | Próximo slide. Anterior em layouts da direita para a esquerda. ↓ em carousels verticais. |
| ← | Slide anterior. Próximo em layouts da direita para a esquerda. ↑ em carousels verticais. |
| Tab | Percorre os botões, o ponto ativo e o conteúdo dos slides, rolando para a vista os slides fora da tela. |
| EnterSpace | Ativa o botão, ponto ou miniatura em foco. |
- A raiz é uma
regiondescrita como carousel. Dê a ela umaria-label. - Cada item é um
groupdescrito como slide e rotulado com sua posição, como “3 of 5”. - Uma região live educada (polite) anuncia o novo slide após a navegação por teclado ou botão, e fica em silêncio enquanto o autoplay roda.
- Pontos e miniaturas usam uma única parada de tabulação, e o foco acompanha o ativo.
- Previous e Next continuam focáveis quando desativados, então o foco nunca se perde em nenhuma das pontas.
| Prop | Tipo | Padrão |
|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" |
spacingEspaço entre os slides. | "none" | "sm" | "default" | "lg" | "default" |
index | number | – |
defaultIndex | number | 0 |
onIndexChange | (index: number) => void | – |
rewindVolta do último slide para o primeiro. | boolean | false |
mouseDragPermite arrastar os slides com o mouse. | boolean | true |
autoplayAvança por um temporizador. delay tem padrão de 5000ms, mínimo de 1000ms. | boolean | { delay?: number } | false |
setApi | (api: CarouselApi) => void | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Atributo | Descrição |
|---|---|
data-slot="carousel" | Selecione a raiz no CSS. |
data-orientation | A orientação. |
--carousel-spacing | O espaço entre os slides, definido por spacing. |
| Prop | Tipo | Padrão |
|---|---|---|
classNameAplicado à trilha que contém os slides. | string | – |
viewportClassNameAplicado ao viewport de rolagem. | string | – |
| Atributo | Descrição |
|---|---|
data-slot="carousel-content" | O viewport de rolagem. |
data-slot="carousel-container" | A trilha dentro dele. |
data-scrollable | Presente quando há mais de uma posição. |
data-dragging | Presente enquanto um arraste com o mouse está em andamento. |
| Prop | Tipo | Padrão |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <div> |
| Atributo | Descrição |
|---|---|
data-slot="carousel-item" | Defina basis-* para mostrar vários por vez. |
Ambos renderizam um <Button /> e aceitam suas props. Ficam fora do conteúdo, então deixe espaço ao redor do carousel.
| Prop | Tipo | Padrão |
|---|---|---|
variant | ButtonProps["variant"] | "outline" |
size | ButtonProps["size"] | "icon-sm" |
childrenSegue a orientação e a direção. | ReactNode | Arrow icon |
| Atributo | Descrição |
|---|---|
data-slot="carousel-previous" | Rotulado como “Previous slide”. |
data-slot="carousel-next" | Rotulado como “Next slide”. |
data-disabled | Presente em qualquer das pontas. O botão continua focável. |
| Prop | Tipo | Padrão |
|---|---|---|
aria-label | string | "Choose slide" |
| Atributo | Descrição |
|---|---|
data-slot="carousel-dots" | O grupo de pontos. Oculto com uma única posição. |
data-slot="carousel-dot" | Cada ponto. O ativo tem aria-current. |
--dot-active | De 0 a 1, quão ativo um ponto está durante a rolagem. |
| Atributo | Descrição |
|---|---|
data-slot="carousel-counter" | Mostra a posição atual sobre o total, com um dígito que gira. |
| Prop | Tipo | Padrão |
|---|---|---|
variant | ButtonProps["variant"] | "ghost" |
size | ButtonProps["size"] | "icon-sm" |
| Atributo | Descrição |
|---|---|
data-slot="carousel-autoplay-toggle" | Rotulado como “Pause slideshow” ou “Play slideshow”. |
| Prop | Tipo | Padrão |
|---|---|---|
aria-label | string | "Slides" |
| Atributo | Descrição |
|---|---|
data-slot="carousel-thumbnails" | A faixa de rolagem. |
| Prop | Tipo | Padrão |
|---|---|---|
indexO slide que ele abre. O padrão é sua posição na faixa. | number | – |
render | ReactElement | (props, state) => ReactElement | <button> |
| Atributo | Descrição |
|---|---|
data-slot="carousel-thumbnail" | Seleciona as miniaturas no CSS. |
data-active | Presente enquanto o seu slide está à vista. |
Retornado por setApi e useCarousel(). Passe jump: true para mover sem animar.
| Prop | Tipo | Padrão |
|---|---|---|
scrollPrev | (jump?: boolean) => void | – |
scrollNext | (jump?: boolean) => void | – |
scrollToRola até uma posição de encaixe. | (index: number, jump?: boolean) => void | – |
scrollToSlideRola até a posição que mostra um slide. | (slideIndex: number, jump?: boolean) => void | – |
canScrollPrev | () => boolean | – |
canScrollNext | () => boolean | – |
selectedScrollSnap | () => number | – |
scrollSnapList | () => number[] | – |
slidesInView | () => number[] | – |
slideNodes | () => HTMLElement[] | – |
viewportNode | () => HTMLElement | null | – |
play | () => void | – |
stop | () => void | – |
isPlaying | () => boolean | – |
on / off | (event: "select" | "scroll" | "settle" | "reInit", listener) => CarouselApi | – |
Use dentro de <Carousel /> para criar seus próprios controles. Retorna api, orientation, selectedIndex, snapCount, slideCount, slidesInView, canScrollPrev, canScrollNext, isPlaying e os métodos de rolagem e reprodução.
- ButtonBotões em todas as variantes e tamanhos, com um fluxo integrado de carregamento, sucesso e erro que dispensa o spinner em requisições rápidas.
- Number flowNúmeros animados em que só os dígitos alterados giram, com qualquer formato Intl e locale.
- AccordionTítulos empilhados que revelam cada um um painel, com movimento de altura que você pode reverter no meio e painéis que continuam pesquisáveis enquanto fechados.
- Aspect ratioUma caixa que mantém sua forma antes de a mídia carregar, exibe um shimmer durante o carregamento, faz a mídia aparecer com fade e usa um fallback quando ela falha.
- CollapsibleUm painel que aparece e desaparece com um movimento de altura que você pode reverter no meio, sem fazer o layout pular.
- ResizablePainéis que você pode separar arrastando, com um divisor discreto que desperta no hover, tamanhos que deslizam ao redefinir ou recolher e layouts que persistem.