# Componentes

Versão 1.0.0 · 15/09/2026 · estado técnico: implementado, em revisão · aprovação institucional: não atribuída.

## Origem e alcance

O manual visual, pp. 22–24, orienta a construção de ícones; pp. 26–34, as cores. O guia HTML, seções 12–13, documenta famílias de interface institucional. Componentes operacionais, densidades, contratos Alpine, teclado e estados são extensões técnicas exigidas pelo prompt, não novas regras oficiais de marca.

Os exemplos estão em `src/design-system.html`, `src/padroes-erp.html` e `src/institucional.html`. A biblioteca compartilhada fica em `src/partials/design-system/`; o comportamento em `src/js/components/design-system.js`; a fonte visual é `src/css/style.css`. O portal compõe os mesmos partials das jornadas. Não há cópias exclusivas da documentação para simular cobertura.

## Contrato de composição

O processador real do Webpack resolve includes recursivamente e não oferece parâmetros. Caminhos de includes são relativos ao arquivo que os contém. Atributos HTML dentro de snippets são interpretados no documento final.

```html
<!-- Em src/minha-pagina.html -->
<include src="./partials/design-system/table.html"></include>
<include src="./partials/design-system/form.html"></include>
```

```js
import { registerDesignSystem } from './components/design-system';
registerDesignSystem(Alpine); // antes do único Alpine.start()
```

Cada instância possui seu `x-data`. Campos e painéis usam `x-id` e `$id(...)` para manter `label`, `aria-describedby`, `aria-controls` e nomes de grupos únicos, inclusive com dois includes iguais na mesma página. As abas usam a chave do item na geração de IDs. Não fixe IDs copiados de capturas.

Classes públicas: `tp-button`, variantes `tp-button-primary/secondary/ghost/danger/inverse/accent/icon`; `tp-input`; `tp-field`; `tp-card`; `tp-badge` e variantes `success/warning/danger`; `tp-table`; `tp-table-scroll`; `tp-alert` e variantes; `tp-dialog`; `tp-drawer`; `tp-tab`; `tp-tablist`; `tp-faq`; `tp-progress`; `tp-switch`.

`tp-core` ativa o reset compartilhado. `data-density="compact"` adapta altura de controle e células; a ausência do atributo usa a densidade confortável. A classe `dark` determina o tema por tokens. O CSS distribuído contém o núcleo e estilos dos componentes, sem depender de layout do portal. A geração e o exemplo mínimo são documentados em `instalacao-e-adocao.md`.

Não há eventos de negócio globais emitidos pelos componentes. O estado demonstrativo é local à instância. Não use o texto de status como confirmação de backend. Não existe API de publicação, pagamento, autenticação ou envio.

## Anatomia e estados por família

### Ações

**Arquivo:** `actions.html`. **Anatomia:** elemento nativo, rótulo de ação, ícone opcional, estado ocupado. **Uso:** ação primária para a próxima ação principal; secundária para apoio; ghost para ação contextual; link para navegação. Ação destrutiva abre a confirmação compartilhada em `modal.html`. Não use links vazios ou cor de erro para aumentar importância.

**Variantes:** primária, secundária, ghost, inversa, CTA amarelo, somente ícone, desabilitada, em carregamento e pressionada. **Estados:** default, hover, focus-visible, active, `disabled`, em carga (`aria-busy` + `aria-disabled="true"` + `.tp-button-loading`, com guarda no handler — nunca `disabled`, que tira o foco do teclado), `aria-pressed` (só com rótulo fixo; rótulo que muda com o estado nomeia a próxima ação e dispensa `aria-pressed`); confirmação local em `role="status"`. O loading de 900 ms é exclusivamente didático. **Tokens:** `--tp-action`, `--tp-on-action`, `--tp-radius`, `--tp-control-height`, `--tp-focus`.

**Teclado:** botão nativo com Enter/Espaço; link com Enter. Botão indisponível é `disabled` real; botão em carga é `aria-disabled`, para que o foco não caia no `<body>`. O ícone favorito tem nome acessível e estado pressionado. **Responsividade:** linha flexível com quebra; não exigir texto de tamanho fixo. **Escuro:** função semântica por tokens. **Conteúdo:** “Salvar rascunho”, “Continuar”, “Manter registro”. O CTA amarelo é **extensão digital aprovada pela marca em 22/09/2026 (Guilherme Sydow, resposta M5)**; continua sendo extensão digital registrada, e não aplicação da norma do manual, mas não está mais pendente de homologação.

```html
<button type="button" class="tp-button tp-button-primary">Salvar rascunho</button>
<a class="tp-link" href="padroes-erp.html">Ver registros</a>
```

### Entrada e formulários

**Arquivos:** `inputs.html`, `form.html`. **Anatomia:** label, campo, indicação de obrigatoriedade, ajuda/erro. **Uso:** pedir somente informação necessária à etapa. Não utilizar placeholder como label, coletar dados reais nesta demonstração ou avançar silenciosamente quando houver erro.

**Cobertura:** texto, busca, e-mail, textarea, select, checkbox, radio, switch, data, período, seleção local de arquivo; read-only; dois passos; conclusão e reinício. O datepicker é o controle nativo `type="date"`; a apresentação depende do navegador. As páginas legadas mantêm flatpickr. Upload aceita `.csv/.txt` para seleção e mostra somente o nome; não lê conteúdo, não envia arquivo e não afirma validação de conteúdo.

**Estado:** vazio, preenchido, foco, erro, read-only, desabilitado quando aplicável; switch com `role="switch"` e `aria-checked`. **Tokens:** texto, superfície, borda, erro, foco, controle e raio. **Validação:** nome e empresa com mínimo de 2 caracteres, estrutura simples de e-mail, área obrigatória; observação opcional até 600 caracteres. Isso valida o formulário demonstrativo, não identifica empresa, pessoa nem capacidade de entrega do e-mail.

**Teclado/foco:** primeiro erro recebe foco após validação; avançar leva ao primeiro campo da etapa 2; voltar devolve ao nome; conclusão recebe foco; reinício limpa os dados e retorna ao primeiro campo. Etapas ocultas usam `x-show`; erros são associados pelo ID e `aria-invalid`. Submit nativo é interceptado por `@submit.prevent`; nenhuma requisição é realizada.

**Responsividade:** duas colunas até faltar espaço, uma em telas estreitas; etiquetas e erros quebram linha. **Conteúdo:** usar `pessoa@example.invalid` e empresa fictícia. **Configuração:** os campos e textos são editáveis no partial; estados `step`, `errors`, `complete`, `name`, `email`, `company`, `area`, `note` pertencem à instância `tpForm`.

### Navegação

**Arquivos:** `header.html`, `institutional-header.html`, `dropdown.html`, `tabs.html`, `faq.html`; paginação incorporada no partial `table.html`. **Uso:** header para ambientes, menu institucional para conteúdo, abas para alternativas do mesmo nível, acordeão para dúvidas independentes. Não usar tabs para encaminhar a outra página nem inventar suporte ao padrão ARIA menu em um simples conjunto de links.

**Dropdown:** botão com `aria-haspopup="menu"`, `aria-expanded`, `aria-controls`; itens `menuitem`. Abertura foca o primeiro item; setas percorrem, Home/End vão às extremidades; Escape fecha e retorna ao botão; escolher uma ação também retorna. Clique externo fecha. Itens não enviam nem alteram dados reais.

**Abas:** roving tabindex (somente a ativa entra no Tab), `role="tablist/tab/tabpanel"`, IDs e seleção sincronizados. Setas direita/esquerda respeitam RTL, Home/End selecionam extremos. Painel é focalizável. Conteúdo consultivo por RH, Vendas, Marketing, Relacionamento e Financeiro vem da interpretação editorial dos contextos do guia.

**FAQ:** `details/summary` nativos, sem plugin e sem JavaScript obrigatório. Enter/Espaço abrem e fecham. Múltiplas respostas podem permanecer abertas. **Header/mega menu:** links normais, controle expandido, Escape/retorno ao acionador, versão mobile com links para âncoras. O logo integral permanece no header; a 320 px os controles passam para outra linha.

**Tokens:** ação, superfície, borda, foco e tipografia operacional. Menus e tabs herdam tema; menus têm largura limitada ao viewport; abas quebram linha.

### Tabela, filtros, cards e detalhes

**Arquivos:** `table.html`, `drawer.html`. **Anatomia:** toolbar, busca/estado, seleção em lote, caption, cabeçalho, linhas, status, paginação e feedback. **Uso:** comparar registros e agir sobre conjuntos explícitos. Não esconder seleção fora da página: o contador informa o conjunto total escolhido, e “Desmarcar tudo” limpa o conjunto.

**Dados:** seis registros sintéticos fixos, com IDs `DEMO-*`. Busca normaliza acentos e consulta nome, área e ID. Filtro por situação. Ordenação por nome e `aria-sort`. Quatro registros por página. Seleção por linha com checkbox e por página com checkbox indeterminado. Ação em lote apenas mostra quantos registros seriam revisados; nada é exportado ou enviado.

**Configuração `tpTable`:** `rows`, `query`, `status`, `page`, `pageSize`, `selected`, `sortAsc`, `notice`; getters `filtered`, `visible`, `pages`, `allSelected`, `someSelected`. A filtragem redefine a página para 1, evitando páginas invisíveis. `clear()` limpa filtros; `toggleAll()` afeta apenas a página visível.

**Estados:** preenchido, linha selecionada, sem resultado, ordenação crescente/decrescente, anterior/próxima desabilitadas, sucesso de ação local; caption identifica dados fictícios. O conjunto original não é removido pela confirmação de exemplo. A modal demonstra a confirmação, sem representar regra real de arquivamento.

**Acessibilidade:** tabela semântica com `scope`; região rolável focalizável e nomeada; caption; labels dos checkboxes incluem nome do registro. Cabeçalho de linha preserva título longo em múltiplas linhas. **Responsividade:** rolagem restrita à tabela, nunca à página. **Densidade:** `data-density` no ancestral muda células e controles; numeração tabular. **Tokens:** `--tp-text`, `--tp-muted`, `--tp-page`, `--tp-surface`, `--tp-border`, `--tp-soft`.

Cards compartilham `.tp-card` para métricas, conteúdo, formulários e painéis. Use heading + explicação + ação opcional. Métricas têm legenda e indicação de demonstração; não invente estatísticas da empresa. Timeline do drawer apresenta sequência textual e estado da próxima etapa.

### Sobreposições

**Arquivos:** `modal.html`, `drawer.html`. **Anatomia:** acionador, `<dialog>`, título acessível, descrição quando aplicável, ação segura e ação de confirmação. **Uso:** decisão que exige atenção ou detalhe contextual. Não utilizar modal para orientação não bloqueante.

**Contrato `tpOverlay`:** `show(event)`, `close()`, `confirm()`, `trap(event)`; refs `dialog`; `opener` para retorno de foco. `showModal()` nativo torna o fundo inerte; focus trap complementa navegação de Tab. Escape usa evento cancel; backdrop fecha somente quando o alvo é o próprio dialog; fechar retorna ao elemento acionador. A primeira ação da confirmação é segura (“Manter registro”). Drawer tem fechamento visível e retorno de foco.

**Responsividade:** modal limitada ao viewport com rolagem interna; drawer lateral ocupa quase a largura em mobile. Não cortar conteúdo para preservar altura fixa. **Tema:** texto, superfície, borda e overlay via tokens; raio lógico adaptado a RTL. **Estado:** fechado, aberto e confirmação anunciada. A aprovação final é local e reversível por recarregamento, sem backend.

### Feedback

**Arquivo:** `feedback.html`. **Cobertura:** badges/tags, alertas de informação/erro/sucesso, notificação persistente até fechamento, tooltip, popover, progress, spinner, skeleton e estado vazio.

Use alertas para contexto relevante; toast persistente para confirmação demonstrativa; erro com ação de recuperação. Não depender apenas de cor, não afirmar recebimento real e não retirar mensagem antes da leitura. O texto “Carregamento ilustrativo” mantém o contexto; o spinner é decorativo.

Tooltip abre por hover e foco, fecha ao sair/Escape e está associado por `aria-describedby`. Conteúdo adicional acionável deve usar popover em vez de tooltip; o exemplo de popover é texto explicativo com `aria-controls/expanded`. Progress utiliza elemento nativo e rótulo; o skeleton é `aria-hidden`. Avatar sem fotografia tem nome acessível e iniciais fictícias, sem foto de pessoa real.

**Tokens:** funções de estado, superfície e borda. **Estado:** sem mensagem, mensagem visível/fechada; tooltip/popover expandido; progresso de 3/4. **Movimento:** animações cessam com `prefers-reduced-motion: reduce`. **Tema/responsividade:** tokens semânticos, texto quebrável, tooltip com dimensão limitada. Mensagens dinâmicas usam `role="status"` onde adequado.

## Iconografia funcional

O portal apresenta SVGs outline simples no contrato de 24 × 24 / traço 2. Esses desenhos são extensão técnica funcional, não símbolos oficiais nem uma alegação de importação da biblioteca Material Symbols Rounded. A referência dessa biblioteca continua documentada no guia HTML, seção 10. O template existente mantém seu inventário local de SVG; não foi instalada dependência adicional.

| Conceito | Representação / equivalência de uso |
| --- | --- |
| Usuários, participantes | Pessoa; somente ícone decorativo junto a texto ou controle com nome |
| Empresas | Edifício |
| Atendimento, mensagens | Balão de conversa |
| Relatórios, financeiro | Barras; dados financeiros ainda exigem rótulo textual |
| Premiação, benefícios | Presente |
| Conquistas | Troféu |
| Documentos | Folha |
| Segurança | Escudo |
| Configurações, integrações | Controles e navegação textual nas jornadas; famílias legadas locais no template |
| Catálogo, saldo, notificações | Rótulos e cards com texto explícito; não assumir símbolo oficial |

Não misturar 3D, preenchido e outline na mesma família funcional. SVG decorativo tem `aria-hidden="true"`; controle somente ícone tem `aria-label`. As áreas de referência de 48 × 48 do manual não obrigam todos os controles operacionais a esse tamanho.

## Matriz de componentes e exemplos

| Família | Partial compartilhado | Demonstração / variantes | Verificação necessária e limites |
| --- | --- | --- | --- |
| Ações | `actions.html` | Portal + ERP; primária, secundária, ghost, terciária, inverse, accent, 3 tamanhos | mouse/Tab/Enter; disabled/loading/pressed |
| Entradas | `inputs.html` | Portal + ERP; tipos nativos, leitura, switch | teclado; datas conforme navegador; seleção sem envio |
| Etapas | `form.html` | Portal + ERP + institucional | erro, foco, voltar, concluir, reset; sem backend |
| Dropdown | `dropdown.html` | Portal + ERP | setas/Home/End/Escape e retorno |
| Tabs | `tabs.html` | Portal + institucional | seleção, setas, RTL, IDs únicos |
| FAQ | `faq.html` | Portal + institucional | abertura nativa, múltiplas instâncias |
| Modal | `modal.html` | Portal + ERP | foco inicial/contido, Escape, backdrop, retorno |
| Drawer | `drawer.html` | Portal + ERP | contexto, scroll, fechamento, retorno |
| Tabela | `table.html` | Portal + ERP | busca sem acentos, estado, sort, paginação, lote |
| Feedback | `feedback.html` | Portal + ERP | status, tooltip, popover, progress e movimento |
| Atendimento | `atendimento.html` | Portal; inbox, conversa, contato e composer | busca/filtros, status, SLA, nota interna, anexo local, loading e retry |
| Marca | `../brand.html` | Todas as páginas novas | proporção, mínimo, proteção, temas |
| Header | `header.html`, `institutional-header.html` | Portal/ERP/institucional | menu mobile e mega menu; layout 320 px |
| Recursos legados | Partials e módulos existentes | Gráficos, calendários, mapas, carrosséis | evidências e exceções na validação geral |

Os testes efetivamente executados são registrados em `validacao.md`, junto às limitações do ambiente. Esta matriz define o roteiro necessário, não afirma sua execução. Aprovação institucional permanece separada. Consulte também `matriz-de-cobertura.md` para rastrear requisitos sem confundir implementado, documentado, testado e homologado.

## Evolução

Altere primeiro o partial e seu contrato; valide pelo menos as duas páginas consumidoras. Mudança de comportamento ou semântica exige revisão do código e documentação. Propostas de novos elementos visuais passam por estratégia, conteúdo, design e QA. Mudança de nome de classe, token ou método público deve ter nota de migração e compatibilidade. Não copie o CSS do portal para criar uma dependência oculta no núcleo.
