Newsletter signup
An email signup framed by a stack of past issues; subscribing drops the next issue, addressed to you, onto the front.
Preview
Newsletter signup preview
Live · keyboard ready
When to use
- Collecting emails for a newsletter, digest, or changelog that has real issues to show.
- The end of a blog post or docs page.
When not to use
- Account creation with a password. Use Signup form.
- Longer forms with several fields. Use Contact section.
- A launch waitlist at the top of a page. Use Hero signup.
shadcn CLI
Also installs (4)
- manicat-foundation
- animated-counter
- segmented-control
- switch
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "newsletter-signup",
"type": "registry:block",
"title": "Newsletter signup",
"description": "An email signup framed by a stack of past issues; subscribing drops the next issue, addressed to you, onto the front.",
"categories": [
"blocks"
],
"dependencies": [
"@radix-ui/react-switch",
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json",
"https://manicat.viraza.net/r/animated-counter.json",
"https://manicat.viraza.net/r/segmented-control.json",
"https://manicat.viraza.net/r/switch.json"
],
"files": [
{
"path": "registry/blocks/newsletter-signup/newsletter-signup.tsx",
"type": "registry:component",
"target": "@components/manicat/blocks/newsletter-signup/newsletter-signup.tsx"
},
{
"path": "registry/blocks/newsletter-signup/newsletter-signup-data.ts",
"type": "registry:component",
"target": "@components/manicat/blocks/newsletter-signup/newsletter-signup-data.ts"
},
{
"path": "lib/media.ts",
"type": "registry:lib",
"target": "@components/manicat/lib/media.ts"
},
{
"path": "registry/blocks/newsletter-signup/newsletter-signup.module.css",
"type": "registry:component",
"target": "@components/manicat/blocks/newsletter-signup/newsletter-signup.module.css"
},
{
"path": "registry/components/switch/switch.tsx",
"type": "registry:component",
"target": "@components/manicat/switch/switch.tsx"
},
{
"path": "registry/components/switch/switch.module.css",
"type": "registry:component",
"target": "@components/manicat/switch/switch.module.css"
},
{
"path": "registry/components/segmented-control/segmented-control.tsx",
"type": "registry:component",
"target": "@components/manicat/segmented-control/segmented-control.tsx"
},
{
"path": "registry/components/segmented-control/segmented-control.module.css",
"type": "registry:component",
"target": "@components/manicat/segmented-control/segmented-control.module.css"
},
{
"path": "registry/components/animated-counter/animated-counter.tsx",
"type": "registry:component",
"target": "@components/manicat/animated-counter/animated-counter.tsx"
},
{
"path": "registry/components/animated-counter/animated-counter.module.css",
"type": "registry:component",
"target": "@components/manicat/animated-counter/animated-counter.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/blocks/newsletter-signup",
"meta": {
"tier": "free",
"kind": "block",
"docs": "https://manicat.viraza.net/components/blocks/newsletter-signup",
"markdown": "https://uiarc.dev/components/blocks/newsletter-signup/markdown"
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { NewsletterSignup } from "manicat/registry/blocks/newsletter-signup/newsletter-signup";
export function NewsletterSignupExample() {
// Size containers have no width of their own: give the demo the whole row.
return <div className="w-full"><NewsletterSignup /></div>;
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Newsletter box Collect an email and handle the subscription yourself.
Newsletter box
Collect an email and handle the subscription yourself. preview
Live · keyboard ready
newsletter-box-collect-an-email-and-handle-the-subscription-yourself-.tsxtsx
Keyboard interactions
| Keys | Action |
|---|---|
| Enter | In the email field, submits the form. The phone keyboard shows a send key. |
| Tab | Moves from the field to the button, the privacy link, and after success to "Use a different email". |
Accessibility
- The email field has a visually hidden label, type email, inputmode email, autocomplete email, and aria-invalid when the address is wrong.
- The line under the field is its description: privacy note, error, or confirmation. Errors use role alert; the line is a polite live region and names the address the link went to.
- Validation starts when the field loses focus with text in it, then updates as you type. On an invalid submit, focus stays in the field.
- While sending, the button sets aria-busy and aria-disabled and ignores repeat submits. On success, focus moves to "Use a different email", which restores the form and refocuses the field.
- Only the front issue is exposed to assistive technology; the issues behind it and the thumbnails are hidden as decoration.
Motion
- On success the next issue, addressed to you, rises onto the front of the stack while the others step back and the oldest drops away. It is one no-overshoot spring, and opacity resolves fast so two issues never read through each other.
- The reader count rolls up by one, and "including you" fades in after it.
- An invalid or failed submit shakes the field a few pixels and tints its border; the message swaps in place of the note.
- Every message, button label, and issue has its space reserved, so nothing below the form moves between states.
- Reduced motion places the issues at once with a short fade, removes the shake and the roll, and keeps the check and labels as quick fades.
Responsive behavior
- Inline puts the stack under the copy and form below 860px container width.
- Below 400px read times hide and an addressed issue shows the recipient instead of the date.
- When the form is narrower than 300px the field and button separate and stack, both full width.
- The card is at most 460px wide; its tray crops the stack and fades it out at the edge.
Performance
- Issue thumbnails and faces use next/image at their rendered size.
- Motion is transform and opacity only; no layout animation.
- No network code: bring your own onSubscribe.
Notes for AI
- Pass onSubscribe and throw on failure; the component handles validation, busy, error, retry, and success states.
- Give it your own publication so the stack shows real past issues. Use short subjects and story titles; titles clamp at two lines.
- Keep the privacy note honest and specific.
- Use inline between page sections; use card in a sidebar, at the end of a post, or centered in a footer band.
- Edit newsletter-signup-data.ts for copy, issues, and reader faces.














