# Gaveta

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

Um painel que entra pela lateral ou por baixo, sobre a página: o detalhe de um item sem sair da lista, os filtros no celular, o carrinho. É um diálogo modal — prende o foco, deixa o resto da página inerte e devolve o foco a quem abriu.

- Função: Estado e aviso
- Também chamado de: drawer, gaveta, painel lateral, sheet, bottom sheet, folha
- Mora em: `app/components/molecules/Gaveta.tsx`
- Página: [https://phorte-design-system.vercel.app/styleguide/peca/Gaveta](https://phorte-design-system.vercel.app/styleguide/peca/Gaveta)
- Ficha no Storybook: [components-complex-gaveta](https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-gaveta--docs)
- Prévia ao vivo, sozinha: [https://phorte-design-system.vercel.app/previa/Gaveta/0](https://phorte-design-system.vercel.app/previa/Gaveta/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 { Gaveta } from '@/app/components/molecules/Gaveta';

<Gaveta aberta={…} onFechar={…} titulo={…}>…</Gaveta>
```

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

## Uso

### Variantes na ficha

1. [Aberta](https://phorte-design-system.vercel.app/previa/Gaveta/0)
2. [Por baixo](https://phorte-design-system.vercel.app/previa/Gaveta/1)
3. [Interativa](https://phorte-design-system.vercel.app/previa/Gaveta/2)

Quando a tarefa pede mais espaço que uma pergunta, mas a pessoa volta para a mesma página depois: filtros no celular, o detalhe de um item da lista, o carrinho.

### Quando não usar

Para uma pergunta curta ou confirmação: o Modal. Para conteúdo que acompanha a página sem bloqueá-la: uma coluna da página, não um diálogo. Para navegar entre seções do site: o menu da Navbar.

### Faça

- Dê um `titulo` que diga a tarefa ("Filtrar cursos"): ele nomeia o diálogo.
- Ponha a ação principal no `rodape` ("Ver 12 cursos"), que fica fixo embaixo quando o conteúdo rola.
- Use `posicao="baixo"` no celular e `"direita"` no computador, com o `tamanho` do conteúdo (320, 480 ou 640px).
- Desligue `fecharNoFundo` em formulário longo: um clique errado perderia o que se escreveu.

### Evite

- Gaveta dentro de gaveta, ou uma gaveta que abre um Modal.
- Navegação de várias etapas dentro dela: é uma página.
- Tirar o botão "Fechar": a saída explícita é obrigatória.

### Anatomia

1. **Véu** — Preto a 40% (`--veu-medio`) sobre a página. É só desenho: o clique fora do painel fecha pelo documento (E137), por padrão; um clique dentro do painel não fecha — testado na ficha.
2. **Painel** — Em `--card`, com sombra; à direita, da altura da tela (320, 480 ou 640px); por baixo, com os cantos de cima arredondados (240, 400 ou 560px, até 5/6 da tela).
3. **Cabeçalho** — Título (h2, 18px, negrito), descrição opcional e o "Fechar" de 44px.
4. **Corpo** — Rola sozinho quando o conteúdo passa da altura.
5. **Rodapé** — As ações, à direita, sobre `--muted`, fixas embaixo.

### Estados

| Estado | O que muda |
| --- | --- |
| Fechada | Não existe na página. |
| Abrindo | Entra deslizando 32px e aparecendo, em 200ms — só com movimento liberado. |
| Aberta | A página atrás fica inerte e não rola. |
| Pela esquerda | `posicao="esquerda"` (E142): o menu de navegação no celular — o do styleguide usa esta. Com `focoInicial`, o foco entra no campo indicado (o filtro), e não no primeiro focável — testado na ficha. |

### Comportamento

| Situação | O que acontece |
| --- | --- |
| Abre | O foco vai ao primeiro campo, pulando o "Fechar"; sem campo, ao "Fechar"; sem nada, ao painel — testado na ficha. |
| Tab no último elemento | Volta ao primeiro: o foco não sai da gaveta — testado na ficha. |
| Fecha (Esc, X, fundo) | O foco volta a quem abriu; `onFechar` recebe `escape`, `botao` ou `fundo` — testado na ficha. |
| Fundo desligado | Com `fecharNoFundo={false}`, o clique fora não fecha nem tira o foco — testado na ficha. |

### Relacionados

- [Modal](https://phorte-design-system.vercel.app/styleguide/md/Modal.md) — Pergunta curta ou confirmação, no centro.
- [FilterGroup](https://phorte-design-system.vercel.app/styleguide/md/FilterGroup.md) — Os filtros que costumam ir dentro dela.
- [Button](https://phorte-design-system.vercel.app/styleguide/md/Button.md) — O acionador e as ações do rodapé.

## Especificação

### Propriedades

| Prop | Tipo | Padrão | Obrigatória | Descrição |
| --- | --- | --- | --- | --- |
| `posicao` | `'direita' \| 'esquerda' \| 'baixo'` | `'direita'` | não | Variante do `cva`. |
| `tamanho` | `'sm' \| 'md' \| 'lg'` | `'md'` | não | Variante do `cva`. |
| `aberta` | `boolean` | — | sim |  |
| `onFechar` | `(origem: OrigemDoFechamentoDaGaveta) => void` | — | sim | Recebe a origem: `'botao'` (o X), `'fundo'` ou `'escape'`. |
| `titulo` | `string` | — | sim | Obrigatório: é o nome do diálogo. Sem ele, o leitor diz só "diálogo". |
| `descricao` | `string` | — | não |  |
| `children` | `React.ReactNode` | — | sim |  |
| `rodape` | `React.ReactNode` | — | não | Ações do pé ("Aplicar filtros", "Finalizar compra"), fixas embaixo. |
| `fecharNoFundo` | `boolean` | `true` | não | Clique no fundo fecha (padrão). O Esc e o X continuam fechando. |
| `focoInicial` | `React.RefObject<HTMLElement \| null>` | — | não | Onde o foco entra, quando não é o primeiro campo (E142): o filtro de um menu, por exemplo. |

### Tokens de cor

| Token | Valor | Usado como |
| --- | --- | --- |
| `--border` | #E5E5E5 | `border-border` |
| `--card` | #FFFFFF | `bg-card` |
| `--foreground` | #1A1A1A | `text-ink` |
| `--muted` | #F4F6F9 | `bg-muted` |
| `--muted-foreground` | #595959 | `text-muted-foreground` |

## Acessibilidade

### Teclado

| Tecla | Faz |
| --- | --- |
| Tab | Percorre os elementos da gaveta; do último, volta ao primeiro. |
| Shift / Tab | Volta; do primeiro, vai ao último. |
| Esc | Fecha e devolve o foco a quem abriu. |

### Leitor de tela

- É `role="dialog"` com `aria-modal`, nomeado pelo título e descrito pela descrição.
- O resto da página fica `inert` enquanto ela está aberta: o leitor não sai sem perceber.
- A mesma mecânica do Modal, num hook só (`app/lib/dialogo-modal.ts`).

### O que sustenta o estado

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

## Status e recursos

| Tipo | Recurso | Status |
| --- | --- | --- |
| Código | `app/components/molecules/Gaveta.tsx` | Disponível |
| Ficha | https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-gaveta--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/Gaveta.tsx
