# Ficha — Botão (seed-componentes.md §1, v2.00)

> Gerada por `06-validacao/geradores/gen-vitrine.py` a partir do canon. Esta é a ficha INTEIRA: todas as linhas, com o texto completo de cada célula (a página mostra uma versão de uma tela, encurtada). Onde a seção não tem o item em subseção própria, a ficha diz "ver a seção" e não inventa. Seção completa: https://ds.seed.eng.br/canon/seed-componentes/01-botao-estavel/ · fatia em Markdown: https://ds.seed.eng.br/10-publicacao/ia/seed-componentes/01-botao-estavel.md

## Anatomia e partes

| Parte · Elemento | Regras |
|---|---|
| A · Ícone (opcional) | 16px (sm), 20px (md/lg); à esquerda do rótulo por padrão (à direita só para direção: "Avançar →"); gap `sp-2` (8px); herda a cor do texto |
| B · Rótulo | Montserrat SemiBold (600); sentence case; nunca some no loading |
| C · Container | Radius `--seed-radius-md` (8px); padding horizontal por tamanho; borda 1px (transparente exceto outline) |

No canon: [§1.2 Anatomia](https://ds.seed.eng.br/canon/seed-componentes/01-botao-estavel/#sec-1-2-anatomia)

## Propriedades e variantes

| Variante | Quando usar · Fundo / texto (light) |
|---|---|
| primary · ALTA | A ação principal da tela/seção — máx. 1 por contexto · FILL SÓLIDO: `action-primary` (verde institucional, 4.60:1) / `text-on-action-primary` (v1.44; era `text-on-brand`, que mede 2,95 no claro — LC-06) |
| secondary · MÉDIA | Ações relevantes não-principais; par do primário · TINT + BORDA DE MARCA: fundo `action-secondary-bg` (turquesa-50) + borda turquesa-600 (4.60:1 — é ela que identifica o controle) / texto turquesa-800 (8.73:1) |
| outline · MÉDIA-BAIXA | Ações neutras/utilitárias (cancelar, voltar, exportar) · BORDA NEUTRA: transparente + borda cinza-600 (4.74:1) / `text-primary` |
| ghost · BAIXA | Ações terciárias, barras de ferramenta, densidade (>3 ações no grupo → use ghost) · SÓ TEXTO: transparente / turquesa-700 (6.32:1); hover `action-ghost-hover` |
| destructive | Ações irreversíveis (excluir, cancelar contrato) · `action-destructive` / branco |
| link | Ação inline em texto corrido · transparente / `text-link`, sublinhado no hover; padding zero |

No canon: [§1.3 Variantes (5 + link)](https://ds.seed.eng.br/canon/seed-componentes/01-botao-estavel/#sec-1-3-variantes-5-link) · [§1.4 Tamanhos](https://ds.seed.eng.br/canon/seed-componentes/01-botao-estavel/#sec-1-4-tamanhos)

## Estados

| Estado | Primary (light) · Regra geral |
|---|---|
| default | `action-primary` |
| hover | `action-primary-hover` (turquesa-700) · escurece 1 stop; transição 100ms. Por variante (LC-05, 2026-09-15): secondary `action-secondary-bg-hover` (turquesa-100 · escuro turquesa-800; substitui o `filter: brightness(.96)`, véu que a régua da casa não mede — §71.6) · outline e ghost `action-ghost-hover` (já era) · destructive `action-destructive-hover` (já era) |
| active | `action-primary-active` (turquesa-800 · escuro turquesa-100 desde a v1.29 — V-HV4.2 = a, MANIFESTO §226: era turquesa-400 e o primário escuro clareava no sobrevoo e escurecia no pressionado abaixo da base, a única família não-monotônica do sistema; agora 300 → 200 → 100, tinta `#00352F` 11,37) · escurece 2 stops no claro, clareia 2 stops no escuro; sem "pulo" de layout. Por variante (LC-05): secondary `action-secondary-bg-active` (turquesa-200 · escuro turquesa-700) · outline e ghost `action-ghost-active` (claro = `surface-sunken` #E3EBF0, escuro = `surface-overlay` #273137 — o par de `action-ghost-hover`, um passo além na mesma direção) · destructive `action-destructive-active` (vermelho-800 · escuro vermelho-200). Regra: o pressionado é SEMPRE um fundo por token, um passo além do sobrevoo, na mesma direção (§71.2 · §71.6); nunca véu/`filter`. Contraste da tinta sobre cada fundo novo, medido nos dois temas: 5,24 a 11,37 (claro) · 5,31 a 10,90 (escuro), todos ≥ 4,5 (HV1-c). Descartado com número: `action-neutral-active` para outline/ghost — no escuro vale #0B1419 = `surface-page`, e o pressionado ficaria igual ao repouso (pixel: Δ ≤ 1/255); vermelho-500 no destrutivo escuro, 3,38 |
| focus-visible | + `--seed-focus-ring` · anel 2px branco + 2px turquesa; visível em QUALQUER variante |
| disabled | `surface-sunken` + `text-disabled` · `cursor: not-allowed`; sem hover; manter contraste legível do rótulo (o usuário precisa ler o que está indisponível) |
| loading | fundo do estado default + spinner 16px · spinner À ESQUERDA, rótulo permanece (sem layout shift, sem perder contexto); `aria-busy="true"`; cliques ignorados |
| selected (só em toggles) | fill sólido turquesa-800 + texto/ícone branco + troca de ícone · estado persistente de alternância — ver §1.5.1; `aria-pressed="true"` |

No canon: [§1.5 Estados (os 6 obrigatórios)](https://ds.seed.eng.br/canon/seed-componentes/01-botao-estavel/#sec-1-5-estados-os-6-obrigatorios)

## Acessibilidade

`<button type="button|submit">` real (nunca div clicável) · foco visível sempre · `aria-busy` no loading · `aria-label` em icon-only · contraste do rótulo AA em todas as variantes/estados (auditado nos tokens: primary 4.60:1, destructive 5.19:1) · não comunicar estado só por cor (disabled também muda cursor e remove hover; loading tem spinner).

No canon: [§1.8 Acessibilidade](https://ds.seed.eng.br/canon/seed-componentes/01-botao-estavel/#sec-1-8-acessibilidade)

## Faça · não faça

As decisões do canon (faça) e a alternativa que cada uma descartou (não faça) — todas as 17, na ordem do canon.

| faça (decisão) | não faça (descartado) |
|---|---|
| `md` = 44px (não 40px) | 40px + pseudo-elemento de expansão (complexidade que alguém esquece) |
| Loading mantém rótulo + spinner à esquerda | Substituir texto por spinner (padrão v1 informal) |
| Outline mantida como variante própria | Fundir outline+secondary (perderia o caso de uso) |
| Disabled com fundo sunken (não opacidade) | `opacity: .5` (rótulo ilegível, falha WCAG) |
| Link como variante do componente | Componente separado (duplicação) |
| Escada de MECANISMOS (v0.2, após crítica do Rafael) | Diferençar só por tom de tint (reprova em escala de cinza e baixa visão) |
| Tokens de componente com par light/dark obrigatório (v0.5, bug de dark pego pelo Rafael) | Confiar que "primitivo resolve" (primitivo não troca de modo; só semântico e componente-com-par trocam) |
| Pressionado por TOKEN DE FUNDO em todas as variantes (LC-05, 2026-09-15) | `action-neutral-active` em outline/ghost (escuro = página: pressionado igual ao repouso, medido no pixel); vermelho-500 no destrutivo escuro (3,38); manter o `filter` (contraste não medível) |
| Estado selected com sinais visuais no próprio botão (v0.3→v0.4, dois refinamentos do Rafael) | v0.3 sugeria label visível como sinal e redigia "ícone cortado" ambíguo — corrigido para: tooltip como sinal textual, mesmo glifo contorno↔preenchido (spec M3 literal), rasura só na exceção de negação de mídia |
| FB1 — É a forma ESTREITA do botão primário da vista, para uma ação CONSTRUTIVA (criar). Um por tela; enquanto ele está na tela, não há outro primário (regra do um, §1.12-5). Acima do limiar do §95 AB3 (860 px de contêiner `app`), a mesma ação volta a ser o botão primário `md` no cabeçalho do conteúdo. Nunca destrutivo, nunca navegação, nunca ação secundária | FAB para qualquer ação · FAB e botão primário no topo ao mesmo tempo |
| FB2 (V-FB1 c) — Forma = ESTENDIDO: ícone + rótulo verbo+objeto (§1.7), 56 de altura; padding `0 sp-5 0 sp-4`, rótulo 14 px peso 600, ícone 24 | 56 × 56 raio 16 só ícone (V-FB1 a, o que o SEED Chat usa hoje) · 56 × 56 círculo (b) · 80 × 80 (d) · sem FAB (e) |
| FB3 — Medidas: altura/lado 56 = `sp-12` + 2 × `sp-1` (a mesma composição do rail recolhido, SH19 — 56 não é passo da escala, é soma de passos); raio `radius-xl` (16); recolhido (FB7), 56 × 56 | inventar número fora da escala |
| FB4 — Cor e material: `action-primary` + tinta `text-on-action-primary` + receita `metal_acao` (MA2: metal na ação primária) + `shadow-overlay` (ele flutua). Foco: anel do §1.5 | sombra só do metal (não lê como flutuante) · cor própria de FAB |
| FB5 — Posição: canto inferior direito da peça de conteúdo, `sp-4` das bordas dela (= 28 px da tela com a calha `sp-3` do CP1), acima da barra de abas; `z-index` 60 (faixa de chrome: abaixo de modal 65, toast 70, popover 75) | 16 px da borda da TELA (sairia da peça de conteúdo e encostaria na calha) |
| FB6 — Reserva: o conteúdo que rola reserva no fim `altura do FAB + 2 × sp-4` (`padding-bottom` + `scroll-padding-bottom`), derivada do tamanho do botão — uma fonte só | reserva constante |
| FB7 (V-FB2 b) — Ao rolar: ao DESCER, o estendido recolhe para 56 × 56 (só o "+"); ao SUBIR ou no topo, estende de novo. Nunca some. Muda só quando a direção muda (histerese de ±2 px); `prefers-reduced-motion` tira a transição | nada muda (V-FB2 a) · sumir ao descer e voltar ao subir (c) |
| FB8 — Acessibilidade: `<button>` real; nome = o rótulo visível (estendido) ou `aria-label` (recolhido/só ícone); recolhido, o rótulo sai da vista e FICA NO DOM (clip de 1 px, como o rail recolhido do SH19), nunca `display:none`. Na ordem do DOM, logo após o cabeçalho do conteúdo (onde o botão primário vive no desktop) | `display:none` no rótulo · `title` como nome |

No canon: [§1.11 Decisões deste bloco (com alternativas descartadas)](https://ds.seed.eng.br/canon/seed-componentes/01-botao-estavel/#sec-1-11-decisoes-deste-bloco-com-alternativas-descartadas) · [§1.14 Botão flutuante (FAB) — `decidido` (2026-10-10) · FB1–FB8 · LC-18 · pedido `PC-2026-0008`](https://ds.seed.eng.br/canon/seed-componentes/01-botao-estavel/#sec-1-14-botao-flutuante-fab-decidido-2026-10-10-fb1-fb8-lc-18)

## Relacionados

Todas as seções do componentes citadas no texto desta seção (8), da mais citada para a menos:

- §71 [HV1 — a RESPOSTA AO PONTEIRO e o PRESSIONADO DISTINTO](https://ds.seed.eng.br/canon/seed-componentes/71-hv1-a-resposta-ao-ponteiro-e-o-pressionado/) — 4×
- §95 [Barra de abas de aplicativo](https://ds.seed.eng.br/canon/seed-componentes/95-barra-de-abas-de-aplicativo-estavel-decidida-em/) — 2×
- §0 [Fundamentos de componente](https://ds.seed.eng.br/canon/seed-componentes/00-fundamentos-de-componente-valem-para-todos-os/) — 1×
- §4 [Busca](https://ds.seed.eng.br/canon/seed-componentes/04-busca-estavel-validado-pelo-rafael-em-2026-08/) — 1×
- §6 [Textarea](https://ds.seed.eng.br/canon/seed-componentes/06-textarea-estavel-validado-pelo-rafael-em-2026/) — 1×
- §8 [Switch](https://ds.seed.eng.br/canon/seed-componentes/08-switch-estavel-validado-pelo-rafael-em-2026-08/) — 1×
- §11 [Combobox](https://ds.seed.eng.br/canon/seed-componentes/11-combobox-estavel-validado-pelo-rafael-em-2026/) — 1×
- §14 [Upload](https://ds.seed.eng.br/canon/seed-componentes/14-upload-estavel-validado-pelo-rafael-em-2026-08/) — 1×
