## Newsletter CTA (S—036)

A dark call-to-action block with email validation, pending, error and a success state that replaces the form.

- URL: https://sundaeui.dev/components/newsletter-cta
- Category: Page sections · Art direction: Refined
- Access: Sundae Pro (authenticated install)
- Stack: React 18+, TypeScript, Tailwind CSS; dependencies: none
- Install: `npx shadcn@latest add https://sundaeui.dev/r/newsletter-cta.json`
- Tags: tailwind, form, newsletter, section, react, cta, landing-page

A newsletter block that handles the boring parts properly. The address is validated before anything is sent, errors appear under the field in plain words, and the button shows a pending state. On success the form is replaced by a confirmation that names the address, so nobody submits twice.
It sits on a quiet ink panel with a faint grid that reads as texture, not decoration, and collapses to a stacked form on phones.
Use it at the end of articles, landing pages and footers. Pass your API call as onSubscribe. Double opt-in copy is already in the success message.

### Usage

```tsx
import { NewsletterCta } from '@/components/sundae/newsletter-cta'

<NewsletterCta title="One good email a month." onSubscribe={(email) => fetch('/api/subscribe', { method: 'POST', body: JSON.stringify({ email }) }).then((r) => { if (!r.ok) throw new Error('Try again') })} />
```

### Props

- `title` (`ReactNode`, required): Heading.
- `description` (`string`): Supporting copy.
- `note` (`string`): Small print under the form.
- `buttonLabel` (`string`, default `'Subscribe'`): Button text.
- `onSubscribe` (`(email) => Promise<void>`, required): Throw to show an error.

### Accessibility

- The input is labelled and its message is linked with aria-describedby. Errors use role="alert".
- The success state is a status message.
