Split Sign In With Quote

sirius

Welcome back

Sign in to pick the day up exactly where your team left it.

Forgot?
or
Continue with SSO

New to Sirius? Create a workspace

A healthcare professional smiling in a bright clinic

The front desk stopped asking me where things were. That is the whole review.

Elena Rourke, Practice manager, Brightwell Group

About this block

Split Sign In With QuotePRO

A hairline sign-in panel with a lowercase wordmark, email and password fields, an inline forgot link, a remember toggle, and an SSO fallback, set beside a full-height photo carrying a gradient customer quote.

Auth49: Split Sign In With Quote

Sign-in panel split down the middle: a lowercase wordmark over email and password fields with an inline forgot link, a remember toggle, and an SSO fallback on one side, and a full-height photo carrying a customer quote over a gradient scrim on the other.

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/auth49?email=YOUR_EMAIL&license_key=YOUR_KEY"

Base UI flavor

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

This installs the block to components/beste/block/auth49.tsx plus the button21 component it uses for the submit and SSO actions.

Quick start

The installed file exports auth49Demo alongside the block: the exact props behind the preview above. Spread it to get a working sign-in screen in one line.

tsx
import { Auth49, auth49Demo } from "@/components/beste/block/auth49";

export default function SignInPage() {
  return <Auth49 {...auth49Demo} />;
}

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

tsx
import { Auth49 } from "@/components/beste/block/auth49";

export default function SignInPage() {
  return (
    <Auth49
      wordmark="sirius"
      heading="Welcome back"
      description="Sign in to pick the day up where your team left it."
      form={{
        email: { label: "Work email", placeholder: "[email protected]" },
        password: { label: "Password", placeholder: "Your password" },
        forgot: { label: "Forgot?", href: "/reset" },
        rememberLabel: "Keep me signed in on this device",
        submitLabel: "Sign in",
        dividerLabel: "or",
        ssoButton: { label: "Continue with SSO", href: "/sso" },
      }}
      footer={{ label: "New here?", link: { label: "Create a workspace", href: "/signup" } }}
      image={{ src: "/images/clinic.jpg", alt: "A clinician in a bright clinic" }}
      quote={{
        text: "The front desk stopped asking me where things were.",
        name: "Elena Rourke",
        role: "Practice manager",
      }}
    />
  );
}

Props

PropTypeDefaultDescription
wordmarkstring–Lowercase brand mark at the top of the form column
headingstring–Screen title, rendered as the h1
descriptionstring–Line under the heading
formAuthForm–Every field, label, and action in the form column
footer{ label: string; link: ActionLink }–Sign-up prompt under the form
image{ src: string; alt: string }–Photo column beside the form
quoteQuote–Testimonial over the photo, needs image to render
classNamestring–Extra classes for the outer <section>
ts
type ActionLink = { label: string; href: string };

type Field = { label: string; placeholder: string };

type AuthForm = {
  email: Field;
  password: Field;
  forgot: ActionLink;
  rememberLabel: string;
  submitLabel: string;
  dividerLabel: string;
  ssoButton: ActionLink;
};

type Quote = { text: string; name: string; role: string };

Behavior notes

  • There is no <form> element, no onSubmit, and no state on the inputs: the fields are uncontrolled markup and the submit button is a plain Button21. Authentication is entirely the integrator's to add.
  • Field ids come from React's useId, and each label is tied to its input through htmlFor, so two instances of the block on one page never collide and clicking a label still focuses the field.
  • The remember checkbox is a native input tinted with accent-primary rather than a component, which keeps the block free of a checkbox dependency.
  • The quote only renders inside the photo column, so passing quote without image shows nothing. The gradient scrim is tied to the quote too, so an image without a quote renders clean.
  • The photo is ordered first on mobile (order-first) as a short band above the form and returns to its DOM position as a full-height column at lg, which keeps the form first in the source for keyboard and screen reader order.
  • The photo column is a fixed dark surface, so its copy uses the fixed text-background tokens rather than the adaptive ones the rest of the block uses.
  • The divider is two flex rules with the label between them, not a bordered pseudo-element, so it stays centred whatever the label says.

Wiring the form up

This block ships the form markup only; state, validation, and submit are yours to add. Our guide wires field markup like this to React Hook Form, TanStack Form, and Formisch on one field system.

More Auth blocks

View all Auth
PRO

auth50

Split Sign Up With Proof

PRO

auth9

Split-Screen Sign In

PRO

auth54

Quiet Sign In

Get Pro access