Components / Blocks
CtaSection
A call to action as a centered closing section, a split beside a setup card that completes itself, or a dismissible banner.
Install
npx shadcn@latest add https://irisui.dev/r/cta-section.jsonimport { CtaSection } from "@/components/iris/blocks/cta-section/cta-section";Preview
CtaSection
A call to action as a centered closing section, a split layout beside a setup card that completes itself in view, or a compact dismissible banner.
When to use
centeredas the last section of a landing page, after the proof.splitwhen a small product visual (visual) or a list of benefitpointshelps the decision.bannerfor a one-line announcement at the top of a page or above content, which people can dismiss.- Not for the first screen of a page: use
HeroSection. Not for system notices: useAlertorToast.
Usage
import { CtaSection } from "@/components/iris/blocks/cta-section/cta-section";
h(CtaSection, {
variant: "centered",
title: "Keep your docs where your code is",
description: "Connect a repository, write the first spec, and let your agents edit the same files.",
primaryAction: { label: "Start for free", href: "/signup" },
secondaryAction: { label: "Compare plans", href: "/pricing" },
note: "Solo €12/month, Team €39/month",
faces: [], // or up to 4 avatar URLs
});
h(CtaSection, {
variant: "banner",
title: "The workspace fits a phone",
primaryAction: { label: "See the changelog", href: "/changelog" },
onDismiss: () => save("banner-dismissed"),
});
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
"centered" | "split" | "banner" |
"centered" |
Layout. |
title / description |
string |
per variant sample copy | Heading and supporting line. |
primaryAction |
CtaAction |
per variant | { label, href?, onClick?, confirmedLabel? }. With no href or onClick, the button confirms in place with confirmedLabel. |
secondaryAction |
CtaAction | null |
per variant | Not shown in the banner. null hides it. |
note |
string |
sample line | Small print under the actions in centered. |
faces |
string[] |
4 sample initials avatars | Avatar image URLs beside the note in centered (at most 4 show). Pass [] to hide them. |
points |
string[] |
3 sample points | Benefit lines in split. |
visual |
ReactNode |
setup card | Replaces the split variant's self-completing setup card. |
onDismiss |
() => void |
none | Banner only: shows a dismiss button and is called after the banner closes its gap. |
className |
string |
none | Extra class. |
Notes
- The sample copy is for notdocs, a markdown workspace that lives in a git repository. Pass your own
title,description, actions andnote, andfaces={[]}or your own image URLs: the default faces are flat initials avatars drawn as inline SVG. - The default
splitsetup card (a notdocs project, "Launch site", ticking through "Write the first spec", "Connect an agent" and "Invite 4 teammates") cannot be edited; pass your ownvisualwhen you usesplit. The preview showscenteredandbanner. - Buttons without
hreforonClickconfirm in place and announce the new label (aria-live); links keep native navigation. The arrow on the primary action leans forward on hover. - Reads the
ink,ink-2,ink-3,line,surface,hoverandgreentokens; the layout follows its own width (container queries at 860 and 560 px). - The banner animates its own height to zero when dismissed so content below closes the gap; under reduced motion it disappears without animating.