Locked Product Preview

Product Preview

Get a first look before we flip the switch.

We're in the final stretch of building something we think you'll love. Join the list to be handed the keys the moment it's ready.

Early birds get an extra month, on us.

polaris.app
A blurred preview of the product dashboard
Preview locked until launch
About this block

Locked Product PreviewPRO

A two-column coming-soon section with a square eyebrow, a heading and a working email notify form, beside a browser-window mockup showing a blurred, lock-badged product preview.

ComingSoon54: Locked Product Preview

A Polaris two-column coming-soon section that pairs a square eyebrow, a heading, a description, and a working email notify form with a browser-window mockup showing a blurred, lock-badged product preview.

Upgrade to Pro

Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.

Upgrade Now

Installation

Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.

Radix flavor

bash
npx shadcn add "https://ui.beste.co/r/comingsoon54?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

bash
npx shadcn add "https://ui.beste.co/r-base/comingsoon54?email=YOUR_EMAIL&license_key=YOUR_KEY"

This installs the block to components/beste/block/comingsoon54.tsx.

Quick start

The installed file exports comingsoon54Demo alongside the block: the exact props behind the preview above. Spread it to get a working preview page in one line.

tsx
import { ComingSoon54, comingsoon54Demo } from "@/components/beste/block/comingsoon54";

export default function Page() {
  return <ComingSoon54 {...comingsoon54Demo} />;
}

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsx
import { ComingSoon54 } from "@/components/beste/block/comingsoon54";

export default function Page() {
  return (
    <ComingSoon54
      label="Product preview"
      heading="Get a first look before we flip the switch."
      description="We're in the final stretch of building something we think you'll love. Join the list to be handed the keys."
      image={{ src: "/dashboard.jpg", alt: "A blurred preview of the product dashboard" }}
      labels={{
        urlText: "yourapp.com",
        lockedText: "Preview locked until launch",
        placeholder: "Enter your email",
        success: "You're in. We'll unlock your preview on launch day.",
        note: "Early birds get an extra month, on us.",
      }}
    />
  );
}

Props

PropTypeDefaultDescription
labelstring–Square eyebrow rendered above the heading via Badge6
labelsComingSoon54Labels{}Mockup URL, locked badge, and form placeholder, success, and note strings
headingstring–Notify heading
descriptionstring–Supporting paragraph under the heading
imageImageItem–Preview screenshot shown blurred inside the browser mockup
classNamestring–Extra classes for the outer <section>
ts
type ImageItem = {
  src: string;
  alt: string;
};

type ComingSoon54Labels = {
  urlText?: string;
  lockedText?: string;
  placeholder?: string;
  success?: string;
  note?: string;
};

Behavior notes

  • The notify form owns its email state and swaps to a success panel on submit; handleSubmit calls preventDefault and only flips when the trimmed email is non-empty, so there is no external callback to wire.
  • The browser mockup renders only when image is set: a card with a three-dot title bar and an optional labels.urlText address pill, wrapping a 4:3 frame.
  • Inside the frame the plain <img> sits absolutely under a bg-foreground/30 backdrop-blur-sm overlay, which centers a Lock-badged pill whenever labels.lockedText is present.
  • The eyebrow, heading, and description each render only when their prop is present, and the note line renders under the form only while the form has not been submitted.
  • Every string is plain text with no inline markup parsing, so HTML passed in shows as escaped text.

Wiring the form up

The form ships with local state and a success message but no backend, so submissions are not sent anywhere until you connect one. Point handleSubmit at your own route handler or email platform, or wire in a form library. For a walkthrough of the options, see React Hook Form, TanStack Form, and Formisch.

More Coming Soon blocks

View all Coming Soon
PRO

comingsoon22

Coming Soon Notify Page

PRO

comingsoon63

Product Pre-Order Teaser

PRO

comingsoon53

Next Issue Magazine

Get Pro access