# P0.S4 — primitivas de administração: fieldset, form-errors, confirm e data-table

| Campo | Valor |
|---|---|
| **Fase** | P0 — Fundação do painel: configurações tipadas e primitivas |
| **Issue** | P0.S4 — primitivas compartilhadas + axe |
| **`kd` task** | `task_00zewwil` (épico `epic_00j5mhqf`) |
| **Âncora** | `wiki/implementation-phases/P0-fundacao-painel.md` · `src/layout/Cms/components` |
| **Status da revisão** | ✅ revisado |

## O que foi implementado

- `<x-cms::fieldset>` — agrupamento semântico com `legend`, descrição opcional e
  `aria-describedby`; sem regra de negócio.
- `<x-cms::form-errors>` — resumo `role="alert"` com a lista de erros e `data-form-errors`;
  o JS do shell foca o primeiro `[aria-invalid="true"]` (o `autofocus` server-side é o fallback
  sem JS).
- `<x-cms::confirm>` — gatilho `<button popovertarget>` + popover nativo `role="dialog"` com
  `<form method="post">`, CSRF, `_method` e botão de cancelar com `popovertargetaction="hide"`.
  O chamador usa fora de outro `<form>` e fornece `fields` para dados ocultos.
- `<x-cms::data-table>` — tabela fina sobre `x-cms::table`: `caption`, `columns` (com `sortable`,
  `url`, `direction` e `class`), `aria-sort`, linhas no slot e `empty` com `colspan` + empty state.
- Integração nas telas de Configurações: `data-table` no índice, `fieldset` e `form-errors` no
  formulário; o texto do resumo passou a ser do shell (`layout::shell.form_errors_title`).
- Labels novos nos quatro locales (`cancel`, `confirm`, `form_errors_title`) e no módulo
  (`institution_data`, colunas, vazio, abrir seção).

## Arquivos para revisar

- `src/layout/Cms/components/fieldset.blade.php`
- `src/layout/Cms/components/form-errors.blade.php`
- `src/layout/Cms/components/confirm.blade.php`
- `src/layout/Cms/components/data-table.blade.php`
- `src/layout/Cms/Assets/js/app.js`
- `src/layout/Lang/{pt_BR,en,es,fr}/shell.php`
- `src/modules/Infraestrutura/Configuracoes/Layout/Views/cms/index.blade.php`
- `src/modules/Infraestrutura/Configuracoes/Layout/Views/cms/form.blade.php`
- `src/modules/Infraestrutura/Configuracoes/Lang/{pt_BR,en,es,fr}/cms.php`
- `tests/Feature/CmsPartialsTest.php`

## Pontos de revisão

### Semântica / a11y
- [ ] `fieldset`/`legend` agrupam sem substituir o `<h1>` do shell; descrição associada por id.
- [ ] Resumo de erro é `role="alert"`; o foco vai ao primeiro inválido; sem JS o `autofocus` cobre.
- [ ] `confirm` usa Popover nativo (sem JS), `role="dialog"`, nome pelo título, `Esc`/light-dismiss,
      formulário real com CSRF e `_method`; sem `<form>` aninhado.
- [ ] `data-table` tem `caption`, `scope="col"`, `aria-sort` só em coluna ordenável e vazio com
      `colspan` correto.

### Segurança / arquitetura
- [ ] Nenhum componente consulta banco, executa regra de negócio ou escreve HTML/CSS/`style=`.
- [ ] Nenhum segredo/PII nos exemplos; o `confirm` só recebe `action`/`title`/mensagem do chamador.
- [ ] JS é enhancement: o formulário e o popover funcionam sem JS.

### i18n / testes
- [ ] Quatro locales para as strings novas do shell; módulo com paridade.
- [ ] `CmsPartialsTest` cobre render, `aria-sort`, empty state, `_method` e resumo.
- [ ] Axe sem violações nas telas de Configurações (`17-cms-configuracoes`).
- [ ] `make check` 2× e `make check E2E=1`.

## Comandos úteis

```bash
make check
make check E2E=1
make exec cmd='vendor/bin/phpunit tests/Feature/CmsPartialsTest.php'
tools/e2e.sh test 17-cms-configuracoes --project=cms-desktop
```

## Notas da revisão

| Data | Revisor | Resultado | Observações |
|---|---|---|---|
| 2026-10-24 | agente revisor P0-S4 | ✅ | **A corrigido:** `bool`/`enum` agora têm `id` de erro, `aria-describedby` e `aria-invalid`; **B corrigido:** `color` é `input type=text` (aceita `oklch`, sem normalização silenciosa); **C corrigido:** teste prova um único `aria-sort` e resumo ausente sem erros. E2E/axe 2/2, `CmsPartialsTest` 13/78. |
