Negocios

Carousel

Componente para exibir conteúdo em sequência com navegação por setas. Baseado em Embla Carousel.

Visão geral

O Carousel usa Embla Carousel para navegação fluida. Padrão Netflix: slides 1:1 com tamanho fixo, overflow lateral mostra o próximo parcialmente.

Demo — estilo Netflix (1:1)

Slide 1

Slide 2

Slide 3

Slide 4

Slide 5

Import

import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } from "@/components/ui/carousel"

Padrão 1:1 Netflix

Cada slide tem largura fixa (basis-[520px]) e proporção quadrada via aspect-square. O slide seguinte aparece parcialmente na borda direita. O conteúdo é o slide em si — sem card externo envolvendo o carrossel.

Múltiplos slides visíveis

Slides menores exibidos em grupo — usa basis fracionado para definir quantos aparecem por vez.

Mentorias

Financeiro

Agenda

Relatórios

Metas

Equipe

2 ou 3 slides visíveis

<Carousel opts={{ align: "start" }}>
  <CarouselContent viewportClassName="overflow-visible" className="-ml-4">
    {items.map((item) => (
      <CarouselItem key={item} className="pl-4 basis-1/2 md:basis-1/3 shrink-0">
        <div className="aspect-square rounded-[10px] bg-white shadow-[var(--shadow-card)]">
          {/* conteúdo */}
        </div>
      </CarouselItem>
    ))}
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Loop infinito

Com opts={{ loop: true }} o carrossel reinicia automaticamente ao chegar no último slide.

Jan

Fev

Mar

Abr

Mai

Jun

Loop habilitado

<Carousel opts={{ align: "start", loop: true }}>
  <CarouselContent viewportClassName="overflow-visible" className="-ml-4">
    {items.map((item) => (
      <CarouselItem key={item} className="pl-4 basis-[520px] shrink-0">
        <div className="aspect-square rounded-[10px] bg-white shadow-[var(--shadow-card)]" />
      </CarouselItem>
    ))}
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Cards de conteúdo

Slides com estrutura de card real — badge, título, descrição e ação.

Gestão

Mentorados ativos

Acompanhe o progresso com métricas em tempo real.

Ver mais →

Financeiro

Receita do mês

Visão consolidada de entradas e metas atingidas.

Ver mais →

Agenda

Próximas sessões

Sessões agendadas para os próximos 7 dias.

Ver mais →

Relatório

NPS da semana

Satisfação dos mentorados nas últimas avaliações.

Ver mais →

Card com badge, título e descrição

<CarouselItem className="pl-4 basis-[340px] shrink-0">
  <div className="flex h-full flex-col justify-between rounded-[10px] bg-white p-[30px] shadow-[var(--shadow-card)]">
    <div>
      <span className="mb-3 inline-block rounded-full bg-muted px-3 py-1 text-xs font-semibold">
        Badge
      </span>
      <h3 className="mb-2 text-base font-semibold">Título do card</h3>
      <p className="text-sm text-muted-foreground">Descrição do conteúdo.</p>
    </div>
    <p className="mt-6 text-sm font-medium text-primary">Ver mais →</p>
  </div>
</CarouselItem>

Orientação vertical

Carousel com scroll vertical — útil para listas de itens em painéis laterais.

Slide 1

Slide 2

Slide 3

Slide 4

Slide 5

Carousel vertical

<Carousel orientation="vertical" opts={{ align: "start" }}>
  <CarouselContent className="-mt-4 h-[560px]">
    {items.map((item) => (
      <CarouselItem key={item} className="pt-4 basis-full">
        <div className="flex h-full items-center justify-center rounded-[10px] bg-white" />
      </CarouselItem>
    ))}
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Padrão de implementação

Snippets para os usos mais comuns do Carousel no projeto.

Carousel básico

<Carousel className="w-full max-w-xl">
  <CarouselContent>
    <CarouselItem>
      <img src="/slide-1.jpg" alt="Slide 1" />
    </CarouselItem>
    <CarouselItem>
      <img src="/slide-2.jpg" alt="Slide 2" />
    </CarouselItem>
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Com autoplay (plugin)

"use client"
import Autoplay from "embla-carousel-autoplay"
import { useRef } from "react"

export function CarouselAutoplay() {
  const plugin = useRef(Autoplay({ delay: 3000 }))

  return (
    <Carousel plugins={[plugin.current]}>
      <CarouselContent>...</CarouselContent>
    </Carousel>
  )
}

Acesso à API do carousel

"use client"
import { useState } from "react"
import { type CarouselApi } from "@/components/ui/carousel"

export function CarouselControlled() {
  const [api, setApi] = useState<CarouselApi>()

  return (
    <Carousel setApi={setApi}>
      <CarouselContent>...</CarouselContent>
    </Carousel>
  )
}

Props e uso

API dos sub-componentes do Carousel.

Props principais

orientation

"horizontal" | "vertical"

Direção do scroll. Padrão: horizontal.

opts

EmblaOptionsType

Opções do Embla Carousel (loop, align, etc).

plugins

EmblaPluginType[]

Plugins do Embla (autoplay, autoScroll, etc).

setApi

(api: CarouselApi) => void

Callback para acessar a API do carousel para controle externo.

CarouselItem basis

className: basis-*

Largura do slide via Tailwind. Ex: basis-1/2 para 2 slides visíveis.

Acessibilidade

O Embla Carousel não inclui atributos ARIA automaticamente. Para carousels de conteúdo importante, adicione role="region" e aria-label no container.

Os botões CarouselPrevious e CarouselNext têm textos sr-only embutidos ("Previous slide" / "Next slide").

Para carousels com autoplay, sempre forneça um controle de pause acessível.

MN Design System · Primary #5FC318 · Brand Green #AFF000 · Font: Inter