Sections
Newsletter
An email capture form.
Client componentSource
Import
import { Newsletter } from '@the_viveksingh/vivek-ui'Inline signup
Return a promise and the button stays busy until it settles, so a slow signup cannot be submitted twice. The result is announced in a live region.
<Newsletter
title="Stay in the loop"
description="New components, release notes, and the occasional deep dive."
note="No spam. Unsubscribe any time."
onSubscribe={async (email) => {
await fetch('/api/subscribe', { method: 'POST', body: JSON.stringify({ email }) })
}}
/>Stacked, for a sidebar
<Newsletter layout="stacked" title="Product updates" onSubscribe={subscribe} />Props
Generated from the package's own type declarations, so this table cannot drift from the code.
| Prop | Type | Default | Description |
|---|---|---|---|
title | ReactNode | — | — |
description | ReactNode | — | — |
placeholder | string | — | Placeholder for the email field. Never a substitute for the label — see `label`. |
label | string | — | The field's accessible name. Default `"Email address"`. Visually hidden by default because the layout reads as a single control, but present: a placeholder disappears the moment you type, so it cannot be the only label. |
buttonLabel | ReactNode | — | — |
onSubscribe | (email: string) => void | Promise<void> | — | Called with the email. Return a promise and the button shows a busy state until it settles, so a slow signup cannot be double-submitted. |
status | NewsletterStatus | — | Drive the state yourself instead of letting the promise drive it. |
successMessage | ReactNode | — | — |
errorMessage | ReactNode | — | — |
note | ReactNode | — | Small print under the field — the GDPR line, usually. |
layout | 'inline' | 'stacked' | — | — |
Every remaining prop is spread onto the root element, so all standard HTML and ARIA attributes work. className and style are merged with the library's own, never replaced, and the ref forwards to the root DOM node.
Rendering
Client component
Newsletter declares 'use client' because it needs state, effects or event handlers. Importing it into a Server Component creates a client boundary at this component — everything above it stays on the server.