KDS
Display

Carousel

Slides horizontais ou verticais com Embla — galerias, depoimentos, parceiros.

Overview

Carousel é construído sobre Embla, oferecendo arrasto, swipe touch e navegação por teclado. Use apenas quando ordem importa menos que presença — galerias visuais, depoimentos rotativos, logos de parceiros.

Carrosséis escondem conteúdo: o que está depois do primeiro slide provavelmente não será visto. Para conteúdo priorizado, prefira uma lista vertical.

Preview
Carrossel com 5 slides + navegação.
1
2
3
4
5

Anatomy

<Carousel orientation="horizontal" | "vertical">
  ├─ <CarouselContent>
  │    └─ <CarouselItem basis="..." />  ← um por slide
  ├─ <CarouselPrevious />              ← desabilita ao chegar no início
  └─ <CarouselNext />                  ← desabilita ao chegar no fim
</Carousel>

Usage

import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious
} from "@kalvner/kds/display/carousel";

export function Gallery({ images }: { images: string[] }) {
  return (
    <Carousel>
      <CarouselContent>
        {images.map((src) => (
          <CarouselItem key={src} className="basis-1/3">
            <img src={src} alt="" />
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  );
}

Props

PropTipoDefaultDescrição
orientation'horizontal' | 'vertical''horizontal'Eixo de rolagem.
optsEmblaOptionsTypeOpções nativas Embla (loop, align, dragFree...).
pluginsEmblaPluginType[]Plugins (autoplay, fade, classNames...).
setApi(api) => voidRecupera a API Embla para controle externo.

CarouselItem

PropTipoDefaultDescrição
classNamestring'basis-full'Use basis-1/2, basis-1/3 para múltiplos por view.

CarouselPrevious · CarouselNext

PropTipoDefaultDescrição
variantButtonVariant'outline'Aparência do botão.
sizeButtonSize'icon'Tamanho.

Subcomponents

  • CarouselContent — wrapper que recebe a ref do Embla.
  • CarouselItem — slide individual; basis-* define quantos por view.
  • CarouselPrevious / CarouselNext — botões que se desabilitam automaticamente nas extremidades quando loop está off.

Variants

Multiple per view
basis-1/3 mostra três slides.
1
2
3
4
5
6
Vertical
Slides empilhados, controles em cima/baixo.
1
2
3
4
5

States

EstadoComportamento
canScrollPrev=falseBotão Previous desabilitado.
canScrollNext=falseBotão Next desabilitado.
loop=trueAmbos sempre habilitados (volta ao início).

Composition

Para autoplay, importe embla-carousel-autoplay e passe via plugins. Sempre ofereça pausa em hover/foco — auto-rotação sem pausa viola WCAG 2.2.2 (Pause, Stop, Hide).

import Autoplay from "embla-carousel-autoplay";

<Carousel
  plugins={[Autoplay({ delay: 4000, stopOnInteraction: true })]}
  opts={{ loop: true }}
>
  ...
</Carousel>

When to use

  • Galeria de imagens / depoimentos / cases.
  • Logos de parceiros (lista longa, ordem indiferente).
  • Tour de produto com 3-5 etapas (visualmente ricas).

When not to use

  • Conteúdo priorizado (CTA principal, número-chave) — vai para área visível, não para slide N.
  • Listas extensas que precisam ser comparadas — use Grid.
  • Mobile com muito texto — leitura corrida vence carrossel.

Best practices

  • Mostre pelo menos meio do próximo slide (basis-[80%] em mobile) para sinalizar que há mais.
  • Bullets de paginação são opcionais — setApi te dá selectedScrollSnap() para implementar se quiser.
  • Carregue imagens com loading="lazy" exceto a primeira.
  • Em mobile, deixe o swipe touch fazer o trabalho — o usuário espera isso.

Accessibility

ConcernComportamento
RegionWrapper tem role="region" + aria-roledescription="carousel".
SlidesCada item tem role="group" + aria-roledescription="slide".
Keyboard / rolam ( / em vertical), Home/End opcional.
PausávelAutoplay precisa de pausa em hover/foco.
Screen readerAnuncie quantidade ("Slide 2 de 5") ao trocar — implemente via live region se necessário.
  • Tabs — quando ordem importa e cada slide é distinto.
  • Sheet — para fluxo passo-a-passo (wizard).
  • Pagination — listas paginadas em grade.

On this page