---
fonte: 01-canonicos/seed-componentes.md
versao_da_fonte: v1.43
secao: 30
titulo: "Modal — `estável` (v0.30) · MD1–MD5 · validação executada 230/230 + visual aprovada em 2026-08-05 (1 ciclo de crítica)"
sequencia: 32 de 98
bytes_do_corpo: 3849
md5_do_corpo: ae3c1d115a9520ae1f21fb7e24a2c46d
gerado_por: 06-validacao/geradores/gen-camada-ia.py
nota: fatia GERADA — o corpo abaixo é byte a byte o trecho do canônico; edite o canônico, nunca esta fatia. Canônico inteiro em https://ds.seed.eng.br/01-canonicos/seed-componentes.md
---
## 30. Modal — `estável` (v0.30) · MD1–MD5 · validação executada 230/230 + visual aprovada em 2026-08-05 (1 ciclo de crítica)

> **Base (3 rodadas, 2026-08-05):** R1 — APG dialog (trap, foco inicial: título tabindex=-1 quando conteúdo longo; alertdialog; exemplo oficial usa 100% da tela no mobile), NN/g ("diálogos curtos e diretos; nunca quando a decisão depende de informação bloqueada"), Smashing decision tree 2026 (evite bloquear; drawer antes de modal), MoJ/GOV.UK (GOV.UK não tem modal no DS; MoJ adotou p/ usuários profissionais com foco no 1º campo, validado em pesquisa). R2 — **MDN showModal/::backdrop (primárias: Baseline "widely available" mar/2022; top layer; inert automático; retorno de foco nativo)**, Radix Dialog (stack), artigo top-layer (LIFO). R3 — **Scott O'Hara "Use the dialog element (reasonably)" (primária: o autor do veto de 2019 liberou o nativo)**, accessuse.eu, CSUN 2019 (foco inicial).

### 30.1 Decisões MD1–MD5

| # | Decisão | Porquê | Descartado |
|---|---|---|---|
| MD1 | Base: **`<dialog>` nativo + `showModal()`**; React = Radix Dialog (Lovable). Top layer (fim do z-index), `::backdrop`, fundo `inert` (teclado E leitor), Esc e retorno de foco de graça. `role="alertdialog"` p/ confirmação destrutiva/erro bloqueante | O'Hara liberou o nativo (2023); MDN Baseline desde mar/2022 | div+ARIA custom (custo sem ganho hoje); `show()` p/ modal ("modal quebrado": sem trap/backdrop/inert) |
| MD2 | **Régua fecha os 3 degraus (§23.1): modal SÓ p/ decisão obrigatória, confirmação destrutiva ou tarefa curta e focada.** Regra inversa: tarefa longa ou que exige consultar a página → drawer ou página | NN/g; Smashing 2026; GOV.UK nem tem modal (sinal de parcimônia) | Modal como contêiner conveniente (treina fechar por reflexo) |
| MD3 | Esc + X visível sempre; **backdrop fecha SÓ modal sem formulário** (com form: não — perda de dados); foco inicial: 1º campo em form (MoJ) · título `tabindex="-1"` se conteúdo longo (APG) · **botão NÃO-destrutivo em confirmação destrutiva** (APG); retorno ao trigger nativo; nome via `aria-labelledby` obrigatório | APG + MoJ + accessuse.eu | Fechar só no X; foco inicial no botão destrutivo |
| MD4 | Tamanhos sm (confirmação) / md (form curto) com max-height + scroll no body; **<640px modal de tarefa ocupa a tela** (APG: esconde movimento de fundo do mobile); confirmações seguem centradas. **Empilhamento proibido** — 1 por vez; exceção única: confirmação de descarte sobre form sujo (replace, não pilha) | APG example; top layer é LIFO mas pilha quebra contexto/AT | Pilha de modais |
| MD5 | 3 zonas: header fixo (título+X) · body scrollável · footer fixo (ações). Tudo dentro herda: form→B2, espera→§18/§19, erro→§15, ações→B1. Nenhum componente nasce dentro do modal | EUI (pinned header/footer) | Modal com anatomia própria |

### 30.2 Tokens

Superfície `--seed-surface-overlay` + `--seed-shadow-overlay` (pares §2.8/§17 já medidos) · radius 12 (herda card) · **backdrop rgba(36,46,52,.5) light / rgba(0,0,0,.6) dark — DECORATIVO declarado** (a separação modal↔página é dada por inert+trap+sombra+deslocamento; o escurecimento é reforço, nunca canal único) · animação 160ms ease-out com `prefers-reduced-motion` desligando. **Nenhum par de texto novo.**

### 30.3 Os 7 testes

1. Pares reusados ✓; backdrop decorativo declarado. 2. Modalidade sinalizada por trap+inert+sombra, não só escurecimento. 3. Grayscale ✓ (sombra+borda de zona carregam). 4. Confirmação × tarefa a 1s (sm centrado × zonas com form). 5. Um modal por vez (MD4). 6. Aberto é auto-evidente. 7. 360px: tarefa em tela cheia, X de 44px, footer acessível ao polegar. *(Validação executada 230/230 + visual aprovada em 2026-08-05.)*

---

