# CarouselNavButton

> Componentes / Navegação e estrutura · Estado: **Em andamento** — Implementado e utilizável, mas ainda sem a validação completa de acessibilidade.

Botão redondo de anterior ou próximo para carrosséis, em quatro tratamentos — claro, escuro (sobre foto ou fundo escuro), contorno e verde tonal —, com nome acessível já em pt-BR. No fim da lista fica `aria-disabled`, sem perder o foco.

- Função: Navegação e estrutura
- Também chamado de: seta do carrossel, anterior e próximo, botão de navegação
- Mora em: `app/components/molecules/CarouselNavButton.tsx`
- Página: [https://phorte-design-system.vercel.app/styleguide/peca/CarouselNavButton](https://phorte-design-system.vercel.app/styleguide/peca/CarouselNavButton)
- Ficha no Storybook: [components-complex-carouselnavbutton](https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-carouselnavbutton--docs)
- Prévia ao vivo, sozinha: [https://phorte-design-system.vercel.app/previa/CarouselNavButton/0](https://phorte-design-system.vercel.app/previa/CarouselNavButton/0)
- Todas as peças: [https://phorte-design-system.vercel.app/llms.txt](https://phorte-design-system.vercel.app/llms.txt)

## Como usar no código

```tsx
import { CarouselNavButton } from '@/app/components/molecules/CarouselNavButton';

<CarouselNavButton direction={…}>…</CarouselNavButton>
```

O `…` marca as props obrigatórias — ver *Propriedades*.

## Uso

### Variantes na ficha

1. [Padrão](https://phorte-design-system.vercel.app/previa/CarouselNavButton/0)
2. [Variantes](https://phorte-design-system.vercel.app/previa/CarouselNavButton/1)
3. [Desabilitado](https://phorte-design-system.vercel.app/previa/CarouselNavButton/2)

Em par, nas laterais de um carrossel ou de uma fileira que rola na horizontal.

### Quando não usar

Para trocar de página numa lista, use a Pagination. Para uma ação comum com ícone, o Button com `aria-label`.

### Faça

- Use sempre em par (`direction="left"` e `"right"`).
- Troque o nome quando o item tiver nome melhor: `aria-label="Depoimento anterior"` vence o padrão.
- Use `variant="dark"` sobre foto ou fundo escuro: o anel de foco passa a ser o claro.
- Desabilite o botão da ponta quando o carrossel não der a volta: `disabled` vira `aria-disabled`, e o foco fica nele (E65).
- Aponte `aria-controls` para a trilha que as setas rolam, e diga o que é o item: "Próximo depoimento".
- Use `variant="tonal"` para o verde, em vez de sobrescrever a cor pela `className` (E65).

### Evite

- Setas que só aparecem no hover: quem usa teclado não passa o mouse.
- `variant="light"` sobre fundo claro: o botão branco some.
- Carrossel que avança sozinho sem pausa antes do conteúdo (`usePausaDeMovimento`), e mais de cinco pontos de página.

### Nota de uso

**O padrão de carrossel (E65)** — o botão sozinho não o garante: aponte `aria-controls` para a trilha; dê o nome do item no `aria-label` ("Próximo depoimento"); se houver avanço automático, a pausa vem **antes** do conteúdo (`usePausaDeMovimento`); no máximo cinco pontos. No fim da lista o botão fica `aria-disabled`, não `disabled`: o foco não cai no `<body>`. Use `dark` sobre foto e `tonal` para o verde — nunca a cor pela `className`.

### Anatomia

1. **Botão** — Círculo de 44px (48px a partir de 768px), com sombra.
2. **Seta** — Ícone de 24px, decorativo.

### Estados

| Estado | O que muda |
| --- | --- |
| Padrão | `light`: fundo `--card`; `dark`: `bg-sobre-escuro-medio` com borda `sobre-escuro-forte` (tokens desde a E65); `outline`: transparente com borda; `tonal`: `--secondary-subtle` com seta `--secondary-dark`. |
| Hover | `light` vira vermelho de interface com seta branca; `dark` vira claro com seta vermelha; `outline` ganha fundo; `tonal` enche de verde com seta branca. |
| Pressionado | Encolhe para 95% (`active:scale-95`). |
| Foco | Anel de 2px: `ring-ring` no `light`, no `outline` e no `tonal`, `ring-ring-inverse` no `dark`. |
| Desabilitado | `aria-disabled` (E65): 50% de opacidade e cursor proibido, **mas continua no Tab** e com o foco — o clique é ignorado. |

### Comportamento

| Situação | O que acontece |
| --- | --- |
| Sem `aria-label` | Nome "Item anterior" ou "Próximo item", pela direção. |
| Com `aria-label` | O passado vence o padrão. |
| Chega ao fim da lista | O "Próximo" passa a `aria-disabled` e **o foco fica nele** — conferido no teste da ficha. Com o `disabled` nativo de antes, o foco caía no `<body>` no último clique. |

### Relacionados

- [Testimonials](https://phorte-design-system.vercel.app/styleguide/md/Testimonials.md) — Usa as setas para passar os depoimentos.
- [TopCourses](https://phorte-design-system.vercel.app/styleguide/md/TopCourses.md) — Usa as setas na fileira de cursos.
- [HeroCarousel](https://phorte-design-system.vercel.app/styleguide/md/HeroCarousel.md) — Usa a variante `dark` sobre a foto (E65).
- [Pagination](https://phorte-design-system.vercel.app/styleguide/md/Pagination.md) — Para trocar de página numa lista.

## Especificação

### Propriedades

| Prop | Tipo | Padrão | Obrigatória | Descrição |
| --- | --- | --- | --- | --- |
| `variant` | `'light' \| 'dark' \| 'outline' \| 'tonal'` | `'light'` | não | Variante do `cva`. |
| `direction` | `'left' \| 'right'` | — | sim |  |

Aceita também: `React.ButtonHTMLAttributes<HTMLButtonElement>`.

### Medidas

| Parte | Valor | Classe |
| --- | --- | --- |
| Botão | 44px; 48px a partir de 768px (medido: 48px em 1280) | `h-alvo-toque w-alvo-toque md:h-12 md:w-12` |
| Seta | 24px | `size={24}` |

### Tokens de cor

| Token | Valor | Usado como |
| --- | --- | --- |
| `--ink-inverse` | #FAFAFA | `bg-ink-inverse`, `text-ink-inverse` |
| `--primary` | #D42B2B | `bg-primary`, `text-primary` |
| `--background` | #FAFAFA | `bg-background` |
| `--border-interactive` | #8C8C8C | `border-border-interactive` |
| `--card` | #FFFFFF | `bg-card` |
| `--foreground` | #1A1A1A | `text-ink` |
| `--muted-foreground` | #595959 | `text-muted-foreground` |
| `--primary-foreground` | #FFFFFF | `text-primary-foreground` |
| `--ring` | var(--footer-red)), decisão da revisão 2. Se outra peça precisar
   * dele como superfície, o nome vira de papel (ex.: --surface-brand-strong). */
  --footer-red: #7D1B1B | `ring-ring` |
| `--ring-inverse` | #FAFAFA | `ring-ring-inverse` |
| `--secondary` | #0B8434 | `bg-secondary` |
| `--secondary-dark` | #0D6B2E | `text-secondary-dark` |
| `--secondary-foreground` | #FFFFFF | `text-secondary-foreground` |
| `--secondary-subtle` | #EAF4EE | `bg-secondary-subtle` |

## Acessibilidade

### Teclado

| Tecla | Faz |
| --- | --- |
| Tab | Leva o foco ao botão; o desabilitado continua na ordem, anunciado como indisponível (E65). |
| Enter / Espaço | Aciona o botão (é um `<button>`). |

### Leitor de tela

- O nome vem do `aria-label`, e a seta é `aria-hidden`.
- Desabilitado por `aria-disabled`: o leitor diz "indisponível", e o foco não se perde no fim da lista.

### O que sustenta o estado

Usa os padrões: estatico. Falta ouvir com leitor de tela: estatico.

## Status e recursos

| Tipo | Recurso | Status |
| --- | --- | --- |
| Código | `app/components/molecules/CarouselNavButton.tsx` | Disponível |
| Ficha | https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-carouselnavbutton--docs | Disponível |
| Teste de acessibilidade | axe em `npm run test` | No gate de todo commit |
| Leitor de tela | Passada da E33 | Falta ouvir |
| Design | Figma | Desativado até a Fase 2 |

### Histórico

- `0298af8` 2026-09-30 — E147: fechamento da Entrega 11 — REPORT.md, verificação cross-agent e o gate estático estrito
- Histórico completo no GitHub: https://github.com/srbunnie/Pos-Phorte-Design-System/commits/main/app/components/molecules/CarouselNavButton.tsx
