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.
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.
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
npx shadcn add "https://ui.beste.co/r/auth49?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
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.
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.
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:
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: "you@practice.com" },
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",
}}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
wordmark | string | – | Lowercase brand mark at the top of the form column |
heading | string | – | Screen title, rendered as the h1 |
description | string | – | Line under the heading |
form | AuthForm | – | 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 |
quote | Quote | – | Testimonial over the photo, needs image to render |
className | string | – | Extra classes for the outer <section> |
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 };<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.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.accent-primary rather than a component, which keeps the block free of a checkbox dependency.quote without image shows nothing. The gradient scrim is tied to the quote too, so an image without a quote renders clean.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.text-background tokens rather than the adaptive ones the rest of the block uses.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.
auth50
A hairline sign-up panel carrying a lowercase wordmark, name, work email, and password fields with an SSO fallback and terms note, beside a soft column of checked benefits over an image tile that floats a live customer quote card.
auth9
Two-column sign-in screen pairing a full sign-in form (social providers, email, password with show/hide, remember me) with a brand panel that lists product highlights. Includes a left/right panel position toggle.
auth32
Two-column editorial sign-in pairing an oversized typographic brand panel with a clean email and password form. Stacks the panel above the form on mobile. Perfect for brands that want a minimal, editorial first impression.
auth2
Two-column registration screen pairing a sign-up form (social providers, name, email, password with show/hide, terms checkbox) with a full-bleed image showcase and customer testimonial. Includes a left/right image position toggle.