Skip to content

Subscribe Input

E-mail field in a pill whose round button carries sending, success and failure.

From the Findit template — see it in context

Try any address, or one ending in .test to see the failure.

Installation

$ npx shadcn@latest add https://framebrick.co/r/subscribe-input.json

Usage

import { SubscribeInput } from "@/components/ui/subscribe-input";

<SubscribeInput onSubmit={async (email) => { await subscribe(email); }} />

Props

PropTypeDefaultDescription
onSubmit(email: string) => void | Promise<void>—Does the work — a server action, a fetch, anything. Throwing means failure.
placeholderstring"Your email"Placeholder, and the field's accessible name unless `label` is given.
labelstring—Accessible name of the field.
submitLabelstring"Subscribe"Accessible name of the round button.
successMessagestring—Announced when it worked.
errorMessagestring—Announced when it failed.
onStatusChange(status) => void—Follows "idle" → "pending" → "success" | "error", for a message of your own.
  • The button carries the result: a spinner while sending, a check on success (the field clears), the arrow again on failure (the field keeps what was typed).
  • Every state is announced through a polite live region; typing again returns the button to its arrow.
  • A hidden honeypot field drops bots that fill everything.
  • The spinner keeps spinning with reduced motion on purpose — it is the only sign that something is happening.

AI prompt

Paste into v0, Lovable, Bolt or Claude to rebuild this component in your own project.

Create a React + Tailwind CSS component called SubscribeInput (no animation library).
- A pill: h-12, rounded-full, 1px border, bg-background, focus-within:border-ring and ring-[3px] ring-ring/50,
  holding an e-mail input (flex-1, text-sm, transparent, no outline) and a 36px round submit button
  (bg-primary text-primary-foreground).
- The button shows the state: while sending, a spinner made of a conic-gradient circle with a radial mask
  (animate-spin); on success, a check; otherwise an up-right arrow. Disabled and aria-busy while sending.
- onSubmit(email) may return a promise; resolving is success (reset the form), throwing is failure (keep the value).
  Typing again returns the state to idle.
- A visually hidden honeypot input named "company" (tabIndex -1, aria-hidden): if it is filled, do nothing.
- A visually hidden aria-live="polite" paragraph carries the success or error message.

Be the first to know

Get new templates and components first

One short email when we release a template or a free component. No spam — unsubscribe anytime.

We use your email only for Framebrick updates. Privacy policy