# Newsletter

> Componentes / Institucional · Estado: **Em andamento** — Implementado e utilizável, mas ainda sem a validação completa de acessibilidade.

Seção de assinatura da newsletter: chamada, o e-mail num FormField, o consentimento no Checkbox com o link da Política de Privacidade e o botão verde "Assinar gratuitamente", com uma ilustração ao lado. Ligada por `onSubmit` (E73, decisão de 2026-09-28).

- Função: Institucional
- Também chamado de: newsletter, assinar, captação de e-mail, inscrição por e-mail
- Mora em: `app/components/organisms/Newsletter.tsx`
- Página: [https://phorte-design-system.vercel.app/styleguide/peca/Newsletter](https://phorte-design-system.vercel.app/styleguide/peca/Newsletter)
- Ficha no Storybook: [components-complex-newsletter](https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-newsletter--docs)
- Prévia ao vivo, sozinha: [https://phorte-design-system.vercel.app/previa/Newsletter/0](https://phorte-design-system.vercel.app/previa/Newsletter/0)
- Todas as peças: [https://phorte-design-system.vercel.app/llms.txt](https://phorte-design-system.vercel.app/llms.txt)

## Como usar no código

```tsx
import Newsletter from '@/app/components/organisms/Newsletter';

<Newsletter />
```

## Uso

### Variantes na ficha

1. [Padrão](https://phorte-design-system.vercel.app/previa/Newsletter/0)
2. [Sem envio](https://phorte-design-system.vercel.app/previa/Newsletter/1)

Perto do fim da página inicial ou de um artigo, para captar a assinatura.

### Quando não usar

Numa página de campanha, em faixa escura, use a NewsletterStrip. Para um contato com mensagem, o ContactForm.

### Faça

- Passe `onSubmit`: ele recebe o e-mail e faz a assinatura. **Sem ele, o formulário não aparece** — só a chamada.
- Faça o `onSubmit` lançar erro quando o serviço falhar: o componente mostra "Não conseguimos assinar agora".

### Evite

- Um formulário "de mentira" para a vitrine: a prop existe para que não haja botão que não envia.

### Anatomia

1. **Chamada** — Chapéu verde, título e a frase de apoio.
2. **E-mail** — FormField "E-mail" (obrigatório) com o Input, `autocomplete="email"`.
3. **Consentimento** — O Checkbox do sistema, opcional, com o link para a Política de Privacidade no rótulo.
4. **Assinar** — Button `secondary` (o verde de interface), na largura toda.
5. **Retorno** — Parágrafo `role="status"`, que recebe o foco depois do envio.
6. **Ilustração** — Decorativa (`alt=""`), à direita a partir de 768px.

### Estados

| Estado | O que muda |
| --- | --- |
| Sem `onSubmit` | Só a chamada e a ilustração: nada de formulário. |
| Erro | E-mail vazio ou sem @: o erro em pt-BR embaixo do campo, que fica `aria-invalid` — conferido no teste da ficha. |
| Enviando | O botão em `isLoading` ("Assinando…"), focável. |
| Enviado | "Pronto! A newsletter vai chegar em <e-mail>." no retorno, com o foco nele. |
| Falhou | "Não conseguimos assinar agora. Tente de novo em alguns minutos." |

### Comportamento

| Situação | O que acontece |
| --- | --- |
| Assinar com e-mail válido | Chama `onSubmit` com o e-mail e leva o foco ao retorno — conferido no teste da ficha. A página não recarrega. |
| Clique no link da política | Abre a política e **não** marca a caixa: o `label` não ativa o controle quando o clique é num link (é o HTML) — conferido no teste da ficha. |

### Relacionados

- [NewsletterStrip](https://phorte-design-system.vercel.app/styleguide/md/NewsletterStrip.md) — A faixa de campanha, com a mesma lógica de envio.
- [FormField](https://phorte-design-system.vercel.app/styleguide/md/FormField.md) — O campo com rótulo e erro.
- [Checkbox](https://phorte-design-system.vercel.app/styleguide/md/Checkbox.md) — O consentimento.

## Especificação

### Propriedades

| Prop | Tipo | Padrão | Obrigatória | Descrição |
| --- | --- | --- | --- | --- |
| `onSubmit` | `(email: string) => void \| Promise<void>` | — | não | Recebe o e-mail e faz a assinatura (E73, decisão de 2026-09-28: ligar por prop). **Sem ela, o formulário não aparece**: era um "Assinar" que recarregava a página e não assinava nada. |

### Tokens de cor

| Token | Valor | Usado como |
| --- | --- | --- |
| `--card` | #FFFFFF | `bg-card` |
| `--foreground` | #1A1A1A | `text-ink` |
| `--muted` | #F4F6F9 | `bg-muted` |
| `--muted-foreground` | #595959 | `text-muted-foreground` |
| `--secondary` | #0B8434 | `bg-secondary/20` |
| `--secondary-dark` | #0D6B2E | `text-secondary-dark` |

## Acessibilidade

### Teclado

| Tecla | Faz |
| --- | --- |
| Tab | Passa pelo campo, pela caixa, pelo link da política e por "Assinar gratuitamente". |
| Espaço | Na caixa, marca ou desmarca. |
| Enter | No campo ou no botão, envia. |

### Leitor de tela

- O erro fica ligado ao campo (`aria-describedby`) pelo FormField, e o resultado sai numa região viva que recebe o foco.
- A validação é do componente, em pt-BR (`noValidate`): a do navegador falava a língua do sistema.

### O que sustenta o estado

Usa os padrões: regiaoViva. Falta ouvir com leitor de tela: regiaoViva.

## Status e recursos

| Tipo | Recurso | Status |
| --- | --- | --- |
| Código | `app/components/organisms/Newsletter.tsx` | Disponível |
| Ficha | https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-complex-newsletter--docs | Disponível |
| Teste de acessibilidade | axe em `npm run test` | No gate de todo commit |
| Leitor de tela | Passada da E33 | Falta ouvir |
| Design | Figma | Desativado até a Fase 2 |

### Histórico

- `0298af8` 2026-09-30 — E147: fechamento da Entrega 11 — REPORT.md, verificação cross-agent e o gate estático estrito
- Histórico completo no GitHub: https://github.com/srbunnie/Pos-Phorte-Design-System/commits/main/app/components/organisms/Newsletter.tsx
