# Newsletter Form

> Email signup with consent, validation, submission, success, and duplicate-email states.

- Category: Marketing
- Kind: component
- Page: https://uaiblocks.dev/components/newsletter-form
- Registry item: https://uaiblocks.dev/r/newsletter-form.json
- Source: https://github.com/victor-teles/uai/blob/main/src/registry/uai/components/newsletter-form.tsx

## Install

```bash
bunx shadcn@latest add https://uaiblocks.dev/r/newsletter-form.json
```

## Usage

```tsx
"use client";

import {
  NewsletterForm,
  NewsletterFormConsent,
  NewsletterFormField,
  NewsletterFormInput,
  NewsletterFormLabel,
  NewsletterFormMessage,
  NewsletterFormSubmit,
  type NewsletterFormVariant,
  type NewsletterSubmission,
} from "@/components/ui/uai/newsletter-form";

const subscribers = new Set(["ana@example.com"]);

async function subscribe({ email }: NewsletterSubmission) {
  await new Promise((resolve) => setTimeout(resolve, 700));
  if (email.endsWith("@fail.test")) return "error" as const;
  if (subscribers.has(email.toLowerCase())) return "duplicate" as const;
  subscribers.add(email.toLowerCase());
  return "success" as const;
}

export function NewsletterFormPreview({ variant = "inline" }: { variant?: NewsletterFormVariant }) {
  return (
    <NewsletterForm variant={variant} onSubscribe={subscribe}>
      <NewsletterFormLabel>Get the monthly product letter</NewsletterFormLabel>
      <NewsletterFormField>
        <NewsletterFormInput placeholder="you@company.com" />
        <NewsletterFormSubmit>Subscribe</NewsletterFormSubmit>
      </NewsletterFormField>
      <NewsletterFormConsent>
        Send me one email a month about releases. Unsubscribe from any issue.
      </NewsletterFormConsent>
      <NewsletterFormMessage>
        Try ana@example.com to see the already-subscribed state.
      </NewsletterFormMessage>
    </NewsletterForm>
  );
}
```

## Anatomy

- `NewsletterForm`
  - `NewsletterFormLabel`
  - `NewsletterFormField`
    - `NewsletterFormInput`
    - `NewsletterFormSubmit`
  - `NewsletterFormConsent`
  - `NewsletterFormMessage`

## Accessibility

- The email input is labelled, uses type email with autocomplete, and is described by the status message.
- Invalid email or missing consent moves focus to the field that needs attention and announces the reason.
- Submission stays focusable with aria-disabled while pending. onSubscribe owns delivery and returns success, duplicate, or error.
