Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Eligibility Capture CTA Block for React

A reverse split call to action that follows the page theme: a framed form with an email field that checks the address as you type and says whether it qualifies, and a Shine Button that stays unavailable, and explains why, until it does.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

A call to action that qualifies the visitor before it asks for anything, for React with Base UI. The page's solid side rails and a divider that meets the top rule split the block in two. At the end side: a "Student program" pill, a headline that offers half price while enrolled and a sentence with a bold lead. At the start side, in a panel framed by hairlines with a plus mark on each corner: a labelled "School email" field with a mail icon that answers as you type. A line below it says "Use your school email" while the address is incomplete, "Student address recognised" once it ends in .edu or .ac. and a country code, and "That isn't a school address" when it is complete but doesn't qualify. The "Claim 50% off" Shine Button is unavailable until the address qualifies, and is described by that same line, so the reason is always on screen and read aloud. Submitting shows the button's spinner, then swaps the form for a confirmation in the same space. On a phone the copy comes first and the form stacks under a rule. It's built from Announcement, Field, Input Group, Guides, Shine Button and Lucide icons, with Tailwind CSS and a CSS entrance that stays still under reduced motion, and it follows the page theme. Made for student, nonprofit and partner programs where the offer is only for an audience you can recognise from the address.

FAQ

How does it decide that an address qualifies?

Two patterns at the top of the file. COMPLETE recognises an address that looks finished (something, an @, a domain and a suffix), so the line doesn't scold while someone is still typing. SCHOOL then tests the domain: it must end in .edu, or in .ac. followed by a two-letter country code, and subdomains such as cs.university.edu pass. Change SCHOOL to match your program: a list of partner domains, a company suffix, or a call to your own endpoint.

Is the check enough to give away a discount?

No. It only reads the text of the address in the browser, which anyone can fake, and the line under the button says so honestly: "We only look at the part after the @". The confirmation sends a link to the address, so the real proof is that the visitor opens it. Do the verification on your server, with an inbox link or a verification service, and treat this block as the front door.

Why is the button marked unavailable instead of being disabled?

A disabled button leaves the tab order and can't carry a description for a screen reader. This one stays focusable and is marked aria-disabled, with aria-describedby pointing at the status line, so a keyboard or screen-reader user reaches it and hears why it can't be pressed yet. It looks faded and ignores pointer presses. Pressing Enter in the field while the address doesn't qualify does nothing but return focus to the field, because the line already says what's wrong.

What does a screen reader hear while typing?

The field's name is "School email". The line under it is a polite status region, so it speaks when its message changes, to "Student address recognised" or "That isn't a school address", and not on every key: an unfinished address keeps the neutral message. The icon beside it is decorative. After a successful submit, focus moves to the confirmation so it is read from its start.

How do I connect the form to my verification flow?

The request is simulated in submit: when the address qualifies, phase goes to "sending", the button shows its spinner and the field turns read-only, and a timer (LATENCY, 0.9 seconds) sets it to "done". Replace the timer with your request, set "done" when it succeeds, and on failure return to "idle" and show the reason in the status line. The timer is cleared when the block unmounts, so cancel a real request there too.

How does it fit a phone?

Below lg the copy comes first and the form panel stacks under it, with a rule between them. The field, the status line and the button always stack, the status line reserves three lines on a phone (two from sm) so the block doesn't jump when its message gets longer, and a long address in the confirmation breaks anywhere instead of pushing the panel wider than the screen.

  • Pro

    A call to action between solid rails that follows the page theme, in a card in card with a two-step email capture: an email field and a Shine Button, then a six-digit code that verifies on the sixth digit and turns into a confirmation in the same space.

  • Pro

    Light Email Capture CTA

    Forms and capture

    A newsletter CTA as a band between solid rails: a headline and a sentence at the start, and at the end one Shine Button that opens in place into an email field with its own Shine submit, closes on Escape and ends in a confirmation.

  • Pro

    A newsletter call to action in a framed form panel where the topics are toggle chips, each with its author's avatar: pick at least one, add an email, and the confirmation lists what you chose.

  • Pro

    A centred call to action between solid rails, built around one fully round capsule that holds the email field and a Shine Button, framed by + marks, growing slightly while you type and settling into a confirmation in place.

  • Pro

    A compact centered newsletter hero with the email field in a full-width band between two hairlines: a Shine Button subscribes, then a confirmation replaces the form, over a row of subscriber proof.

  • Pro

    Copy Link Share CTA

    Forms and capture

    A band call to action for a referral programme that follows your theme: the pitch beside a read-only invite field with a Shine Button that copies it, real email and system share links, and a closing band counting invites.