---
fonte: 01-canonicos/seed-componentes.md
versao_da_fonte: v1.43
secao: 33
titulo: "Central de Notificações — `estável` (v0.34) · CN5–CN12 · pattern F6 · suite `suite-cn.mjs` 45/45 ✓ · regressão A–F 291 verdes · gate visual aprovado 2026-08-06"
sequencia: 35 de 98
bytes_do_corpo: 10231
md5_do_corpo: 10ce03fb59da6e0db655af05e45f63b4
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
---
## 33. Central de Notificações — `estável` (v0.34) · CN5–CN12 · pattern F6 · suite `suite-cn.mjs` 45/45 ✓ · regressão A–F 291 verdes · gate visual aprovado 2026-08-06

> **Natureza:** pattern de COMPOSIÇÃO do F6, não componente novo — consome sino (icon-button §1) + badge dot (§21) + popover/tray (§24) + drawer (§31) + lista com os slots LS5 (§28) + empty esvaziado (§25) + toast (§17) + severidades T1–T5. As regras do marco v1.0 (CN1–CN4) permanecem intactas e NÃO foram re-pesquisadas: toasts de BACKGROUND gravam no centro, de primeiro plano não; régua editorial "só o que o usuário RESOLVE, nunca marketing"; persistência/tempo-real/preferências = produto (Lovable/Supabase, CN4).
>
> **Base (3 rodadas encadeadas, 2026-08-06, ~26 fontes):** R1 — **Carbon notifications pattern (íntegra: painel usado em conjunto com toasts; cronológica; nunca reenviar; WCAG 2.2.3/2.2.4 AAA; Carbon ainda não estabilizou o componente — sinal de pattern)**, **PatternFly notification badge + drawer v3–v6 (a spec mais completa do canon: unread por peso bold; mark all read; clear all com ressalva "varia por produto"; ≤3–4 categorias; badge attention só p/ erro crítico)**, NN/g indicators/notifications, Smashing 2025 (fadiga), UX Mag (modelo âncora), ui-patterns, evidência de campo Atlassian community (2 dores documentadas: badge que zera na abertura faz o usuário esquecer pendências; mark-all-read que não persiste destrói a confiança). R2 — EUI Header (`EuiHeaderSectionItemButton` com prop `notification` dot/contador; lista de alerts em **EuiPopover OU EuiFlyout** — exatamente os 2 degraus da CN) + issue #4257 (flyout como MVP do notification center), Knock (modelo unseen→seen→read; badge default unseen como anti-ruído de feed; filtro All/Unread; reverse chronological), Novu (seen one-way por IntersectionObserver; **#955: mark-all-read desabilitado sem itens**; #4846 flicker de estado). R3 — **SAP Fiori Notifications (cronológica por timestamp "como um inbox"; agrupamento por tipo é recurso de ALTO volume com bulk por grupo; maior prioridade do item define a do grupo; título 2 linhas + Show More; DISMISS ≠ PROCESSADO)**, Sara Soueidan live regions partes 1–2 (região nomeada dá contexto à contagem; live region não carrega rich text), ariaNotify/AOM (limitações estruturais — contexto), APG feed pattern (proposta SEM consenso do task force desde ARIA 1.1 — descartada), APG alertdialog (aria-modal só quando o conteúdo externo está de fato bloqueado), Harvard DAS (não mover foco em atualização não-crítica). Consolidado aprovado pelo Rafael em 2026-08-06.

### 33.1 Decisões CN5–CN12

| # | Decisão | Porquê | Descartado |
|---|---|---|---|
| CN5 | **Arquitetura em 2 superfícies:** sino no chrome (z 60) abre o **painel rápido** = popover §24 (tray <640px por herança Y4) com as **5 mais recentes** + header + footer "Ver todas (N)" → **drawer §31** com a lista completa. O toast (CN2) segue sendo o anúncio de chegada; o painel nunca re-anuncia o que o toast já falou | EUI: popover OU flyout do mesmo botão de header; Carbon: painel *em conjunto* com toasts; 5 itens mantêm o popover sem scroll (degrau leve do §23.1) | Superfície única (popover com scroll infinito = drawer disfarçado); página dedicada como destino primário (perde o estado que motivou o drawer) |
| CN6 | **Drawer da CN em regime STANDARD** (`show()`, não-modal, página interativa) — **resolve o ponto em aberto do DW1**. Esc fecha; foco entra no X ao abrir e **retorna ao SINO ao fechar** (âncora estável — o trigger "Ver todas" morreu junto com o popover); z 65 (emenda v1.1); <640px largura total (DW2), regime inalterado | O caso de uso É consulta lado-a-lado (ler → navegar à fonte → comparar) — o caso central que criou o standard no DW1; PatternFly: drawer de notificações = "ver a lista **sem sair da tela atual**"; APG: aria-modal só quando o fundo está de fato bloqueado — trap aqui seria mentira semântica | Modal-drawer (trap sem tarefa que o justifique); regime por prop do consumidor (regra do um: a CN tem UM comportamento) |
| CN7 | **Badge do sino reflete NÃO-LIDA, nunca "vista": abrir o painel NÃO limpa o badge.** Limpa por leitura item a item ou "Marcar todas como lidas". Dot default; contador e vermelho seguem CN1/V5. **O conceito "vista/seen" NÃO existe no DS** | Dor real (Atlassian community): badge que zera na abertura → usuário esquece pendências; PatternFly: unread no badge só quando existe marcar-como-lida E chegada é infrequente — a régua editorial CN garante ambas; Knock admite que unseen é otimização de feed social — o nosso contexto é ERP acionável | Modelo seen/unseen (Knock default) — certo p/ feed de marketing, errado p/ pendência de trabalho |
| CN8 | **Semântica de lida:** navegar à fonte (ação primária da linha) marca lida; ação secundária por item = toggle "Marcar como lida/não lida"; **"Marcar todas como lidas"** no header das 2 superfícies, **desabilitado sem não-lidas**. **Sem "Limpar tudo" e sem dispensar destrutivo** — item sai quando o produto o considera resolvido (CN4). **Lida ≠ resolvida: itens lidos permanecem** | PatternFly: clicar na linha = lida; Novu #955: mark-all desabilitado sem itens; Fiori: dismiss ≠ processado — e a régua CN é "só o que o usuário resolve", então sobrar até resolver é o correto; Atlassian: mark-all-read que não persiste é a quebra de confiança nº 1 (persistência é dura — CN4) | "Clear all" (risco de descartar pendência acionável); dispensar com undo (fila de undo sem demanda) |
| CN9 | **Ordenação cronológica inversa, SEM agrupamento por categoria na v1.** Severidade T1–T5 no leading já diferencia. Fronteira declarada: se o volume crescer, a 1ª evolução é agrupar por DATA (Hoje/Anteriores), nunca por tipo | Carbon: cronológica; Fiori: timestamp é o default ("como um inbox"), agrupamento é recurso de alto volume — a régua editorial mantém o volume baixo por construção; PatternFly limita a 3–4 categorias (o custo do agrupamento) | Agrupamento por tipo/prioridade na v1 (complexidade de launchpad corporativo sem demanda); ordenar por prioridade (esconde o recente) |
| CN10 | **Item = lista §28 com os slots LS5, sem slot novo:** ícone T1–T5 no leading · título ≤2 linhas com wrap · **timestamp relativo em JetBrains Mono no trailing com absoluto acessível (`<time datetime>` + `title`)** · não-lida por peso 700 + dot 8px vermelho-500 · live region única do grupo (1.13-b). **Chegada com painel ABERTO: prepende + live region polite nomeando ("Nova notificação: …"), SEM toast; painel FECHADO: o toast é o anúncio (CN2) — nunca os dois** | LS5 nasceu para isso (zero re-spec); Fiori/Carbon: 2 linhas; Soueidan: live region nomeada dá contexto; anúncio duplicado = dupla fala (regra do um aplicada ao canal sonoro) | `role="feed"` do APG (proposta sem consenso do TF desde 2017, suporte AT irregular, e jogaria fora a lista §28 já validada); timestamp só relativo (inacessível p/ auditoria e AT) |
| CN11 | **Composição dos estados (já decididos — amarração):** vazio = empty §25 tipo *esvaziado*, "Tudo em dia" (EEny permitido, Z5), sem live region própria; erro de carga = slot `role="alert"` pré-existente com ação de recuperação (herda S5/Z via LS5); loading = Régua de Espera (carga inicial → skeleton imediato) | Tudo herdado; a decisão é declarar a composição | — |
| CN12 | **Acessibilidade do sino:** icon-button §1 com **nome acessível dinâmico** — "Notificações" / "Notificações, N não lida(s)" — + `aria-expanded` + `aria-haspopup="dialog"`. Badge dot/contador **decorativo declarado** (o número vive no nome). Mudança de contagem NÃO anuncia — a chegada já foi anunciada pelo toast (T5). **Nomenclatura anti-colisão: as superfícies da CN chamam-se "Central de notificações"** — a landmark "Notificações" pertence à região de toasts (§17) e nomes acessíveis duplicados confundiriam a navegação por landmarks | Soueidan (o nome carrega o contexto); Harvard DAS (não interromper por atualização não-crítica); a colisão de nomes foi detectada na composição — registro para todo consumidor | Live region no badge (dupla fala com o toast); contagem só visual (AT sem o número); as duas superfícies chamadas "Notificações" (colisão com §17) |

### 33.2 Anatomia, tokens e fronteiras

Painel rápido: popover §24 (surface-overlay + shadow-overlay), largura ~380px desktop, header com título + ghost "Marcar todas como lidas", máx. 5 linhas, footer "Ver todas (N)" full-width ≥44px. Drawer: §31 integral em standard (sm 400; <640px total; z 65; X 44px). Linha: §28 densidade default (≥44px). Empty/erro/skeleton: §25/S5/§19. **Nenhum par de cor novo — todos os pares consumidos já foram medidos nos §17/§21/§24/§25/§26/§28/§30–§31** (primário 13.86/14.16 · secundário 6.55/8.92 · meta mono 4.74/7.95 · hover 12.75 · severidades T1/errata azul-800 · dot vermelho-500 decorativo-redundante ao peso). Fora do DS (reafirmado): preferências de notificação · push/e-mail · o que conta como "resolvido" · persistência/tempo-real (CN4) · agrupamento por data (fronteira de evolução, CN9) · tabela de notificações (B6).

### 33.3 Os 7 testes

1. Nenhum par novo; herdados medidos ✓. 2. Não-lida = peso+dot (nunca só cor); severidade = ícone+cor (T3). 3. Grayscale: peso e ícones carregam (provado no §28/§15). 4. Painel rápido × drawer a 1s (popover ancorado 5 itens × superfície lateral com lista completa). 5. Regra do um: uma live region nomeada por grupo; um canal de anúncio por chegada (toast OU live region). 6. Não-lidas visíveis sem interação (badge + peso + dot). 7. 360px: tray herdado do §24, drawer largura total, linhas ≥44px, X 44px, hitbox estendida no marcar-como-lida. *(Suite `suite-cn.mjs` 45/45 ✓; regressão A–F byte-perfeita = 291 verdes acumulados; gate visual do Rafael aprovado em 2026-08-06 — empilhamento renderizado, geometria do popover, `show()` nativo, tray 360px, dark e grayscale.)*

---

