Componentes
17. Toast
seed-componentes.md v1.43 · §17seção 19 de 9817-toast-estavel-validado-pelo-rafael-em-2026-08.md · MD5 a5480c74Título completo no canon: Toast — estável · validado pelo Rafael em 2026-08-04 (preview v0.15 + suite; teste de fogo do §1.13/1.13-b — aprovado)
Base: R1 — Carbon (5s, empilhamento, top-right), M1/M2/M3 oficiais (janela 4–10s, uma ação, acima da bottom-nav, "pode permanecer até o usuário agir"), NN/g (caso dos 5 minutos), EUI (10s, ação atual vs histórica), GitLab Pajamas. R2 — React Aria/Spectrum toast (landmark "Notificações", F6, foco restaurado, fila com prioridade), Radix (região + hotkey), Sonner/shadcn (+ auditoria WCAG 2026: 4s default viola 2.2.1), react-toastify (alt+t), Base Web (sem duração se houver ação), Angular Material, regra de leitura Byrne-Haber (5s+1s/120 palavras → mínimo aceitável 6s). R3 — WCAG 2.2.1 Timing Adjustable + 4.1.3, GitLab a11y issue (ação crítica dentro de role=status viola 2.2.1), SAP Fiori message toast (inferior-central), Ionic (swipe orientado pela posição, positionAnchor), bug documentado iOS (toast na base coberto pelo teclado), Mobbin (base = alcance do polegar), Baymard (confirmação só em label pequeno é perdida por subgrupo, especialmente mobile). Decisões Q1–Q7 conferidas pelo Rafael em 2026-08-04.
17.1 Papel e a régua de uso (Q1, emendado com Baymard)#
Confirmação efêmera e sobreposta do desfecho da ação ATUAL (salvou, enviou, copiou). O toast é o SEGUNDO sinal do desfecho; o primeiro é a própria UI refletindo o novo estado (linha aparece na tabela, botão vira "salvo") — Baymard mediu usuários perdendo confirmações que existiam só como aviso pequeno. NUNCA: portador único de erro que exige ação (NN/g: usuária esperou 5 minutos por um erro que sumiu em 5s), erro de validação (é B4), informação histórica, saudação de sessão (EUI), marketing.
17.2 Decisões Q2–Q7#
| # | Decisão | Porquê | Descartado |
|---|---|---|---|
| Q2 | Sucesso/informação = auto-dismiss; atenção = duração estendida; erro = SEM auto-dismiss (persiste até fechar). Erro em toast só para falha de operação assíncrona sem página-contexto (herda K2 e N4) | Auditoria shadcn: crítico = duration Infinity + dismissal manual; WCAG 2.2.1; M3: "pode permanecer até o usuário agir" | Erro auto-dismiss (perda de informação crítica) |
| Q3 | Duração: 8s default (sucesso/informação) · 10s atenção · erro persiste. Pausa em hover E em foco E com página oculta (visibilitychange); timer reinicia ao retomar |
Janela oficial Material 4–10s; regra de leitura: mínimo aceitável 6s; 4s do Sonner reprova 2.2.1; EUI registrou como bug pausar só em mouseover sem foco | 4–5s (rápido demais); 10s fixo (atrasa a fila no uso denso do ERP) |
| Q4 | Máx. UMA ação; nunca "Fechar" como ação; nunca o único caminho para a função; toast com ação não auto-dismissa. Undo é o caso canônico | M3: uma ação, duas = dialog, snackbar nunca é o único acesso; Angular Material: sem duração quando há ação (AT precisa navegar até ela); GitLab: ação crítica em role=status viola 2.2.1 — a função existe na página sem limite | Ação com timer correndo |
| Q5 | Container = landmark role="region" + aria-label="Notificações", alcançável por F6 (atalho de foco); foco NUNCA roubado ao aparecer; ao fechar o último toast focado, foco RESTAURADO ao ponto anterior |
React Aria (F6/Shift+F6 + restauração) e Radix (região rotulada + hotkey) convergem; sem landmark, usuário de teclado não alcança a ação antes do timeout | Toast fora de landmark; autofocus no toast |
| Q6 | Empilhamento: máx. 3 visíveis, mais novo no topo, excedente em FILA | Carbon (empilha, novo no topo) + React Aria (fila com limite); operações em lote do ERP perderiam confirmações no modelo um-por-vez | Material "um por vez" (descartado com porquê: lote ERP); ilimitado (avalanche) |
| Q7 | Posição: desktop inferior-direita · mobile inferior-central, acima de bottom-nav/teclado (offset via visualViewport + --seed-safe-bottom), swipe-para-baixo dismissa |
EUI/GitLab: inferior-direita em produto denso (não cobre header/nav/cabeçalho de tabela — perfil dataviz SEED); Fiori: inferior-central; M2: acima da bottom-nav; Mobbin: base = polegar; bug iOS documentado do teclado motiva a regra do visualViewport (vira teste da suite); Ionic: swipe orientado pela posição | Top-right (Carbon — colide com a área de ações de página do ERP); top mobile (longe do polegar) |
17.3 ARIA e live region (o teste de fogo)#
Segue T5 + nota 1.13-b: a REGIÃO (role="region") existe no DOM desde o load; cada toast é inserido dentro dela já populado, com role="status" (sucesso/informação/atenção) ou role="alert" (erro) — valor sempre explícito (§2.6). aria-atomic="true" no toast. O botão fechar fica FORA do texto anunciado (aria-label próprio). Frase completa e específica nomeando o objeto ("Proposta #482 enviada", nunca "Sucesso").
17.4 Anatomia e tokens#
Card 320–400px (mobile: min(100vw - 32px, 400px)) sobre --seed-surface-overlay + --seed-shadow-overlay (elevação de sobreposição, tokens v1.2 — no dark a borda sutil assume a separação); barra lateral 4px + ícone na severidade (T1/T3); texto --seed-text-primary; ação = botão ghost; fechar 44×44. Entrada/saída 160ms --seed-ease-out; prefers-reduced-motion: aparece/some seco. Gap de pilha 8px.
17.5 Microcopy#
Passado para desfecho ("Proposta #482 enviada"), gerúndio para processo em andamento — regra herdada do Fluent, mas o toast de progresso ("Enviando…") fica DECIDIDO NO SUB-BLOCO B junto do progress (ponta solta declarada no consolidado). Sem "com sucesso" (implícito — EUI writing).
17.6 Os 7 testes#
- Card sobre página ≥3:1 pela borda/sombra (medir). 2. Severidade por cor + ícone + texto. 3. Grayscale: ícone + barra carregam. 4. Sucesso × erro a 1s (persistência + ícone). 5. Uma região para todos os toasts; um anúncio por toast. 6. Fila visível (contador "+2" quando há excedente). 7. 360px: inferior-central acima do teclado simulado; swipe; fechar 44px. (Verificado: suite v0.15, aprovado.)
Também cita o §17: banco-cn, banco-superficies.