---
fonte: 01-canonicos/seed-componentes.md
versao_da_fonte: v1.43
secao: 20
titulo: "Progress — `estável` · validado pelo Rafael em 2026-08-04 (suite v0.17) · resolve a ponta do §17.5"
sequencia: 22 de 98
bytes_do_corpo: 4155
md5_do_corpo: c823a99ad3aa6460ee7f1c295e7ec7ba
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
---
## 20. Progress — `estável` · validado pelo Rafael em 2026-08-04 (suite v0.17) · resolve a ponta do §17.5

> **Base:** R1 — NN/g (>10s exige estimativa explícita), Carbon progress bar (handoff indeterminado→determinado; direção E→D), Material m1 PRIMÁRIO (nunca regride; uma barra para o todo) e m2 (handoff). R2 — React Aria useProgressBar (valuetext localizado; label obrigatório), Radix/shadcn (omitir value = indeterminado), Angular Material (não alterar valuemin/max padrão), MUI (aria-valuetext quando não é %). R3 — **W3C ARIA25 íntegra** (técnica oficial do 4.1.3: progressbar NÃO é live region; canal polite separado visually-hidden), MDN progressbar, marcos 25/50/75 (nunca cada 1%), Fiori (bloquear o mínimo). Fronteira: stepper "passo 2 de 5" é NAVEGAÇÃO → Bloco 5 (registrado no roadmap).

### 20.1 Decisões U1–U6

| # | Decisão | Porquê | Descartado |
|---|---|---|---|
| U1 | Uso: fração conhecida OU >10s. Pode nascer indeterminada e CONVERTER quando o dado chega; o valor NUNCA regride (clamp); operações sequenciais = UMA barra do todo | m1 primário: "always fill from 0% to 100% and never decrease"; "the progress as a whole, not each individual operation"; Carbon/m2: handoff | Barra por sub-operação; regressão visual |
| U2 | ARIA: `role="progressbar"` + `aria-valuenow/min/max` (0/100 padrão, NÃO alterar); **indeterminada = OMITIR valuenow**; rótulo obrigatório (`aria-labelledby` no label visível); `aria-valuetext` quando o formato humano não é % ("7 de 12 faturas") | MDN; Angular Material (mudar min/max quebra AT); React Aria/MUI (valuetext) | Div animada sem role |
| U3 | **Anúncio = regime CONTÍNUO do §1.13** (par simétrico da 1.13-b): o progressbar NÃO anuncia sozinho — canal SEPARADO visually-hidden `role="status"` pré-existente anuncia MARCOS (25/50/75/100), nunca cada 1%, e a conclusão NOMEIA o objeto. O §14 (N3/N4) passa a referenciar este componente como canônico | W3C ARIA25: os values comunicam programaticamente mas não são anunciados ao mudar — a live region polite separada é quem fala; cada 1% soterra | Anunciar todo %; confiar só no role |
| U4 | `aria-busy="true"` na região que a operação reconstrói (tabela em lote); controles internos desabilitados durante | Escopo correto do aria-busy | aria-busy no body |
| U5 | >10s: barra + texto de status (percentual/etapa em **JetBrains Mono** — dado de medição, tokens v1.2 §tipografia); o resto da UI permanece interativo sempre que possível | Fiori: bloquear o mínimo; NN/g >10s = estimativa explícita | Overlay global em operação longa |
| U6 | **Toast de processo (fecha a ponta do §17.5):** operação longa em BACKGROUND vive num toast PERSISTENTE (herda Q2/Q4) contendo esta progressbar; título em gerúndio ("Enviando 12 faturas…"); aos 100% CONVERTE em toast de desfecho (sucesso, aí sim com auto-dismiss 8s). O nó-raiz do toast de processo NÃO leva role vivo — quem anuncia é o canal U3 interno (senão o atomic re-falaria o toast inteiro a cada %) | Fluent (gerúndio→substantivo; processos similares combinam num toast) + U1 (uma barra do todo) + §1.13 (uma live region por componente, do tipo certo) | Toast de processo com auto-dismiss; role="status" no raiz (re-anúncio a cada update) |

### 20.2 Anatomia e tokens

Trilho 8px radius 999 em `--seed-border-subtle`; preenchimento `--seed-action-primary-bg`, transição de largura 200ms `--seed-ease-out` (reduced-motion: seca); label acima à esquerda, valor à direita em mono; indeterminada: segmento ~30% varrendo E→D em loop (direção reservada da barra — Carbon).

### 20.3 Os 7 testes

1. Preenchimento×trilho e trilho×página ≥3:1 (medir light/dark). 2. Progresso por comprimento + número + anúncio. 3. Grayscale: comprimento carrega. 4. Determinada×indeterminada a 1s (número presente × varredura). 5. Uma barra por processo (U1); um canal de anúncio (U3). 6. Estado visível: label + valor sem interação. 7. 360px: barra full-width, label/valor empilham sem truncar; toast de processo legível. *(Verificado: suite v0.17, aprovado.)*

---

