A newsletter CTA that asks before it asks for an address: subjects, then cadence, then the email, and the column swaps itself for a confirmation that reads back exactly what was chosen.
A newsletter CTA that asks before it asks for an address: subjects, then cadence, then the email. The column swaps itself for a confirmation that reads back exactly what was chosen.
Free block
This block is free. No license or account is required: install it with the CLI and use it in unlimited projects.
Radix flavor
npx shadcn add "https://ui.beste.co/r/cta92"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/cta92"That installs the block file, the badge6 eyebrow and button1 seal CTA it is built from, and the questionnaire primitive.
import { Cta92, cta92Demo } from "@/components/beste/block/cta92";
export default function Page() {
return <Cta92 {...cta92Demo} />;
}import { Cta92 } from "@/components/beste/block/cta92";
export default function Page() {
return (
<Cta92
badge={{ label: "Newsletter" }}
meta="4,100 readers"
heading="Subscribe to the parts you actually read"
description="One list, three subjects, and a cadence you choose."
promises={[
{
title: "You pick the subjects",
description: "Anything you leave out is never sent.",
},
{
title: "Leaving is one click",
description: "The unsubscribe link sits at the top of every email.",
},
]}
image={{
src: "https://images.unsplash.com/photo-1585241645927-c7a8e5840c42",
alt: "Printed newsletter issues stacked on a desk",
}}
caption="Every issue is written, edited, and sent by the same two people."
note="No sponsorships, and the list is never shared."
button={{ label: "Read the last issue", href: "https://beste.co" }}
shortcuts="numbers"
topicsStep={{ title: "What should we send you?", description: "Pick as many as you like." }}
topics={[
{ value: "notes", label: "Engineering notes", description: "What we changed." },
{ value: "design", label: "Design teardowns" },
]}
cadenceStep={{ title: "How often is welcome?" }}
cadences={[
{ value: "weekly", label: "Weekly", description: "Thursday mornings." },
{ value: "monthly", label: "Monthly" },
]}
emailStep={{
title: "Where should it arrive?",
label: "Email address",
placeholder: "you@company.com",
}}
labels={{ submit: "Confirm my subscription", confirmationTitle: "Check your inbox" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | Badge | – | Eyebrow above the rule, rendered with Badge6. |
meta | string | – | Short line beside the eyebrow, across the hairline divider. |
heading | string | – | Section heading. |
description | string | – | Section description under the heading. |
image | CoverImage | – | Photograph in the left column, at a fixed height. |
caption | string | – | Line under the photograph. |
promises | PromiseItem[] | [] | Bordered cells in a three-up row under both columns: what the subscription is and is not. |
note | string | – | Muted line under the promise cells. |
topicsStep | Step | – | Copy for the first question. Omit it to drop the step. |
topics | Option[] | [] | Checkbox choices for the first question. |
cadenceStep | Step | – | Copy for the second question. Omit it to drop the step. |
cadences | Option[] | [] | Radio choices for the second question. |
emailStep | EmailStep | – | Copy and placeholder for the address step. |
shortcuts | "letters" | "numbers" | – | Prints a shortcut on every choice of the active step. |
button | ActionButton | – | Button1 seal CTA under the confirmation. |
labels | Cta92Labels | {} | Overrides for the buttons and the confirmation copy. |
className | string | – | Merged onto the section element. |
type Badge = { label: string };
type ActionButton = { label: string; href: string };
type CoverImage = { src: string; alt: string };
type PromiseItem = { title: string; description: string };
type Option = { value: string; label: string; description?: string };
type Step = { title: string; description?: string };
type EmailStep = Step & { label: string; placeholder?: string };
type Cta92Labels = {
previous?: string;
next?: string;
submit?: string;
restart?: string;
confirmationTitle?: string;
confirmationDescription?: string;
topicsSummary?: string;
cadenceSummary?: string;
emailSummary?: string;
};topics, cadence, and email, which is what lets the confirmation read the answers back in words instead of values.topics, cadence, and email to your own handler at the point where the confirmation is set.topicsStep or cadenceStep removes that question, and the confirmation row for it then reads as empty rather than breaking.cta8
Minimal centered call-to-action with heading, description, and action buttons. Perfect for newsletter signups and conversion sections.
cta27
Call-to-action with scattered topic pills and tags showing what subscribers receive. Perfect for newsletter and content subscription sections.
cta31
Preview card showing a sample newsletter issue with subscribe call-to-action. Perfect for giving visitors a taste of content before subscribing.