MenuChevron Down
Carousel Carrossel - Docs - Artefact

Carousel Carrossel

Data Display
Auto-interativo

Introdução

Uma apresentação de slides que pagina por um conjunto de slides usando CSS scroll-snap real e nativo — não cálculos de transform. Suporta paginação por grupo (slidesPerPage), loop, reprodução automática, rolagem com arraste do mouse, navegação por teclado e orientação vertical.

Uso

Carrossel básico

import { Carousel } from "../components/ui";

export default function Page() {
  return (
    <Carousel
      slides={[
        <div>Slide 1</div>,
        <div>Slide 2</div>,
        <div>Slide 3</div>,
      ]}
    />
  );
}

Múltiplos slides por página, com loop

<Carousel
  slides={slides}
  slidesPerPage={3}
  spacing="16px"
  loop
  colorPalette="purple"
/>

Reprodução automática com pausa ao passar o cursor

<Carousel
  slides={slides}
  autoplay={{ delay: 2500 }}
  pauseOnHover
  loop
  showAutoplayTrigger
/>

Orientação vertical

<div class={css({ height: "72" })}>
  <Carousel slides={slides} orientation="vertical" class={css({ height: "full" })} />
</div>

Controles sobrepostos (inline)

<Carousel slides={slides} inline loop />

Construtor de Páginas CMS

Este componente está disponível como um bloco carousel no Construtor de Páginas (content/pages/*.json). Os slides são registros simples { image, caption, href }, não blocos de componentes aninhados:

{
  "type": "carousel",
  "slides": [
    { "image": "/hero-1.jpg", "caption": "Slide 1" },
    { "image": "/hero-2.jpg", "caption": "Slide 2" }
  ],
  "loop": true,
  "autoplayDelay": 3000
}

Propriedades

Carousel

O componente de conveniência orientado a dados: passe slides e ele compõe ItemGroup/Item mais um Control padrão (gatilhos de anterior/próximo e pontos indicadores) para você. Para composição manual completa, use Carousel.Root e as partes exportadas diretamente (ver Composição manual).

PropTypeDescriptionDefault
slidesJSX.Element[]O conteúdo dos slides. slideCount é derivado de seu comprimento.-
interactivebooleanForça a hidratação como uma ilha.true
pagenumberSe o carrossel está em uma determinada página (controlado).-
defaultPagenumberPágina inicial (não controlado).0
slidesPerPagenumberNúmero de slides visíveis de uma vez.1

| slidesPerMove | `number \ | "auto"` | Slides avançados por passo de página. "auto" usa slidesPerPage. | "auto" | | orientation | `"horizontal" \ | "vertical"` | Eixo de rolagem. | "horizontal" |

| loop | boolean | Volta ao início na primeira/última página. | false | | spacing | string | Espaço entre slides (qualquer comprimento CSS). | "0px" | | padding | string | Padding de rolagem extra em cada extremidade (qualquer comprimento CSS). | - | | autoSize | boolean | Permite que os slides se dimensionem sozinhos em vez de se dividirem igualmente por slidesPerPage. | false | | allowMouseDrag | boolean | Habilita rolagem por clicar-e-arrastar com o mouse (a rolagem por toque/trackpad sempre funciona nativamente). | false |

| autoplay | `boolean \ | { delay: number }` | Avança as páginas automaticamente. Sempre volta ao início ao final, independentemente de loop. | false |

| pauseOnHover | boolean | Pausa a reprodução automática enquanto o ponteiro está sobre o carrossel. | false |

| snapType | `"proximity" \ | "mandatory"` | Rigor do scroll-snap CSS. | "mandatory" |

| disabled | boolean | Desabilita todos os gatilhos/indicadores e o arraste. | false | | showControls | boolean | Renderiza PrevTrigger/NextTrigger no Control padrão. | true | | showIndicators | boolean | Renderiza um IndicatorGroup no Control padrão. | true | | showAutoplayTrigger | boolean | Renderiza um AutoplayTrigger no Control padrão. | false | | itemClass | string | Classe personalizada aplicada a cada Item gerado. | - |

| size | `"sm" \ | "md" \ | "lg"` | Tamanho dos gatilhos/indicadores. | "md" |

| colorPalette | `"gray" \ | "blue" \ | "cyan" \ | "green" \ | "orange" \ | "purple" \ | "red" \ | "teal" \ | "indigo" \ | "pink" \ | "yellow" \ | "success" \ | "error" \ | "warning"` | Cor de destaque para o indicador ativo/gatilho de autoplay pressionado. | "green" |

| inline | boolean | Sobrepõe o Control sobre o grupo de itens em vez de empilhá-lo abaixo. | false | | translations | CarouselTranslations | Strings localizadas (aria-labels, texto de progresso). | - | | onPageChange | (details: { page: number; pageSnapPoint: number }) => void | Chamado quando a página ativa se estabiliza. | - | | onAutoplayStatusChange | (details: { type: string; isPlaying: boolean; page: number }) => void | Chamado quando a reprodução automática inicia/avança/para. | - | | onDragStatusChange | (details: { type: string; isDragging: boolean; page: number }) => void | Chamado ao iniciar/mover/finalizar o arraste. | - | | class | string | Classes CSS personalizadas para o elemento raiz. | - | | classNames | Record<string, string> | Classes CSS personalizadas por parte (root, itemGroup, item, control, prevTrigger, nextTrigger, indicatorGroup, indicator, autoplayTrigger). | - |

Carousel.Item

PropTypeDescriptionDefault
indexnumberA posição do slide. Obrigatório.-

| snapAlign | `"start" \ | "center" \ | "end"` | Qual borda do slide se ajusta à visão. | "start" |

Carousel.Indicator

PropTypeDescriptionDefault
indexnumberA página para a qual salta. Obrigatório.-
readOnlybooleanRenderiza o ponto sem um manipulador de clique.false

Notas de arquitetura

  • Rolagem nativa, não transforms. ItemGroup é um contêiner real overflow: auto de grid/flex com scroll-snap-type; a paginação chama scrollTo(...) sobre ele. Isso significa que o deslize por toque, a rolagem por trackpad e a rolagem por teclas de seta no elemento focado funcionam mesmo antes de a hidratação terminar — apenas os cliques de gatilho/indicador e a reprodução automática requerem JavaScript.
  • pageSnapPoints é o índice do item em que cada página começa, calculado com a mesma fórmula estrutural que a máquina @zag-js/carousel do Ark UI usa (getPageSnapPoints) — determinístico apenas a partir de slideCount/slidesPerPage/slidesPerMove, portanto é idêntico no servidor e antes da hidratação (nenhuma medição de layout é necessária para SSR).
  • Os filhos não são re-renderizados na hidratação. Assim como nas demais ilhas deste projeto, a raiz interativa do Carousel corrige data-current, disabled, data-inview e aria-hidden diretamente no DOM já renderizado (ver applyPageState em carousel-primitive.tsx) em vez de regenerar os filhos Item/Indicator — o HonoX rehidrata os filhos de uma ilha a partir de um snapshot HTML serializado, sem invocar novamente o componente que os produziu.
  • Nunca dependa de um onClick de JSX para um botão gatilho/ indicador. Pelo mesmo motivo: PrevTrigger/NextTrigger/Indicator/ AutoplayTrigger são compostos como filhos, então o hono/jsx/dom nunca reconcilia suas próprias props de evento sintéticas sobre esses nós já montados — um onClick neles silenciosamente nunca dispara. Todo o tratamento de clique é delegado a partir da raiz em um único useEffect (target.closest('[data-part="..."]')), espelhando dropdown-primitive.tsx/combobox-primitive.tsx. Esse efeito (e o de pauseOnHover) monta exatamente uma vez e lê scrollNext/scrollPrev/ isPlaying/etc. por meio de refs em vez de capturá-los diretamente por closure — colocar estado reativo em seu array de dependências reanexaria o listener a cada mudança, e o próprio setIsPlaying de pauseOnHover (disparado por pointerenter, que chega logo antes do clique emparelhado em um gesto de clique real) de outra forma desmontaria o listener de clique no intervalo entre a chegada do mouse e o pressionar do botão.
  • Simplificações em relação ao Ark UI upstream: o rastreamento de "em vista" usa a mesma matemática de intervalo de índices que a renderização SSR (não um IntersectionObserver real), e o tabindex de ItemGroup é sempre 0 (não alternado com base em se um slide contém um elemento focável). Ambos são compromissos pragmáticos que cobrem o caso comum de slidesPerPage fixo; RTL (dir) não é suportado, em consonância com o restante desta biblioteca de componentes.