Login Page React block for Tailwind CSS v4
v1.1.0Updated in 1.9.0
A React login page with password, magic link or code sign-in, Google, Apple and Microsoft buttons, two-step codes and password recovery.
Sign in with email and password: fields validate when you leave them and as you fix them, Enter submits, a failed attempt shows a red alert above the form and keeps the email (a second failure also clears the password). The eye button reveals the password without moving the caret, and Caps Lock shows a warning. "Forgot password?" in the password label row carries the typed email to the recovery form. "Email me a sign-in link" and "Use your password" switch between the password form and the email link (or code) form. Provider buttons show a spinner on the one you pressed. After an email is sent, the "Check your email" view shows the address, opens Gmail or Outlook when the domain matches, and offers a resend that waits with a countdown ("Resend in 0:24") that survives a reload. Codes: type or paste the 6 digits and the sixth one submits; a wrong code shakes the cells and says how many tries are left, three wrong codes lock the input for a minute with a live countdown; two-step verification can switch to a 10 character backup code. The new password shows a strength meter and a checklist and must match its confirmation; the last view draws a bouncy check. Every secondary view has "Back to sign in"; each view slides in from the side it belongs to, focus moves to its title and the change is announced. On phones the form fills the screen with 48px fields and the hero is gone; with reduced motion views cross-fade.
Login Page is a Pro React block in the React blocks category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add login-page, together with Marketing Section, Alert, Avatar, Button, Checkbox and 12 more and the npm packages motion, lucide-react, react-hook-form and zod.
Built with
The sections this page is made of. In the full-screen preview, hold Alt to outline each one on the page.
Add to a project
Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup
npx wingo-ui@latest add login-pageLogin Page is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans
Usage
Import LoginPage from @/components/blocks/login-page.
// app/(auth)/login/page.tsx
"use client";
import { useRouter } from "next/navigation";
import { LoginPage } from "@/components/blocks/login-page";
export default function Page() {
const router = useRouter();
return (
<LoginPage
heroImage="/images/office.jpg"
twoFactor
onSignIn={async ({ email, password, remember }) => {
const response = await fetch("/api/login", { method: "POST", body: JSON.stringify({ email, password, remember }) });
if (!response.ok) throw new Error("The email or the password is not correct");
}}
onSuccess={() => router.push("/")}
/>
);
}Props
defaultViewdefault"sign-in"LoginViewThe view shown first (uncontrolled); view / onViewChange control it.
viewLoginViewThe current view, controlled. An unknown value shows sign-in.
onViewChange(view: LoginView) => voidRuns on every view change (mirror it to the URL hash or the router).
layoutdefault"split""split" | "centered" | "card"split: the form beside a hero from 1024px; centered: no hero, the form in a card from 640px; card: no hero, the form in a raised card at every width, centered on the page background (dots unless background is set) with the logo above and the links below.
heroSidedefault"end""start" | "end"Which side the hero sits on in the split layout.
backgrounddefault"soft""plain" | "soft" | "glow" | "aurora" | "grid" | "dots"The page background: plain is the bare page color; the others tint the page and add a glow, an aurora, a grid or dots over the first screen. The layout picks one unless you set it (split: soft; centered: glow; card: dots).
backgroundColordefault"oklch(0.62 0.14 275)"stringThe tint and glow color of the page background.
heroImagedefault""stringA photo behind the hero with a dark scrim and white text; empty keeps the neutral card hero. The demo passes /demo/city.jpg.
heroReactNodeReplaces the hero content (testimonial, badge and customer names from LOGIN_PAGE_SAMPLE).
logoReactNodeTop-left of the form column; default the Northwind CRM mark and name.
methodsLoginMethod[]How people sign in, default ["password", "magic-link"]; "otp" emails a 6 digit code. The first is the form shown first; [] with providers leaves only the providers (SSO).
providersAuthProvider[]Social buttons, default AUTH_PROVIDERS (Google, Apple, Microsoft); [] hides them and the divider.
showProvidersdefaulttruebooleanShortcut for providers={[]} when false.
providerLayoutdefault"stack""stack" | "row"stack: full-width "Continue with Google" buttons; row: icon buttons side by side.
twoFactordefaultfalsebooleanAfter a correct password the flow asks for the authenticator code.
rememberdefaulttruebooleanShows the "Remember me for 30 days" checkbox.
defaultEmaildefault""stringPrefills the email everywhere (a returning user).
resendSecondsdefault30numberWait before a link or a code can be sent again (use-cooldown, kept across reloads under the key login-resend).
passwordMinLengthdefault8numberMinimum length of a new password in the reset view (rule, checklist and strength).
onSignIn(values: SignInValues) => (void | Promise<unknown>)Email, password and remember. Default: simulated, rejects "The email or the password is not correct" below 8 characters.
onMagicLink(email: string) => (void | Promise<unknown>)Sends the sign-in link (and resends it). Default: simulated.
onSendCode(email: string) => (void | Promise<unknown>)Sends the 6 digit code for the otp method (and resends it). Default: simulated.
onVerifyCode(code: string, context: VerifyCodeContext) => (void | Promise<unknown>)Checks an otp, two-factor or backup code. Default: 123456 (or any 10 character backup code) passes, anything else rejects "Wrong code. 2 attempts left."; three failures lock the input for 60 s.
onForgot(email: string) => (void | Promise<unknown>)Requests the reset link. Default: simulated and always resolves, so the page never reveals whether an account exists.
onReset(password: string) => (void | Promise<unknown>)Saves the new password. Default: simulated.
onProvider(id: string) => (void | Promise<unknown>)Starts a social sign-in; the button spins until it settles. Default: simulated for 1.2 s.
onSuccess() => voidAfter a sign-in, a verified code, a provider or the reset-done button. Default: the toast "Welcome back, Emma" (the page mounts its own Toaster then).
registerHrefdefault"/signup"stringThe "Create one" link; "" hides it.
termsHrefdefault"/terms"stringThe "Terms" link in the footer; "" hides it.
privacyHrefdefault"/privacy"stringThe "Privacy" link; "" hides it.
helpHrefdefault"/help"stringThe "Help" link; "" hides it.
sizedefault"lg""md" | "lg"Fields and buttons: lg is 48px, md 40px (44px on touch); the code cells stay 48px.
tonedefault"neutral"ToneThe primary buttons and the checkbox.
radiusdefault"md""sm" | "md" | "lg"The hero, the card, the icon tiles and the controls' corners.
animateIndefaulttruebooleanThe logo, form, footer and hero rise in once when the page mounts on the client (server html is already final).
labelsPartial<LoginPageLabels>Every visible string, merged over DEFAULT_LOGIN_PAGE_LABELS; validation takes form-validation messages.
localedefault"en-US"stringSets the page language (lang).
linkComponent(props: LinkComponentProps) => ReactNodeThe router link for the sign-up and footer links (next/link); default <a>.
classNamesPartial<Record<LoginPageSlot, string>>Classes for formColumn, header, body, footer, hero, view, title and form.
Parts
AuthFrame
componentThe layout of the auth screens on its own: a form column that fills the phone, with a hero beside it from 1024px, or a centered or raised card. Use it for sign-up, invite and other auth pages so they match.
layoutdefault"split""split" | "centered" | "card"split: form column plus hero from 1024px; centered: the form in a card from 640px; card: a raised card at every width.
heroSidedefault"end""start" | "end"Which side the hero sits on in the split layout.
radiusdefault"md""sm" | "md" | "lg"Corner size of the hero and the card.
logoReactNodeThe top of the form column.
footerReactNodeThe bottom of the form column: a sign-up link, legal links.
heroReactNodeThe hero column's content, shown from 1024px in the split layout.
heroLabelstringThe accessible name of the hero aside.
slotdefault"auth-frame"stringThe data-slot prefix of the parts.
animateIndefaulttruebooleanThe header, body, footer and hero rise in once when mounted on the client.
classNamesPartial<Record<"formColumn" | "header" | "body" | "footer" | "hero", string>>Extra classes for the inner parts.
childrenReactNodeThe form.
DEFAULT_LOGIN_PAGE_LABELS
constantEvery English string of the sign-in, code, two-step and password recovery views. Spread it and override what you translate.
LOGIN_PAGE_LABELS_EN
constantAn alias of DEFAULT_LOGIN_PAGE_LABELS, kept so older imports keep working.
AUTH_PROVIDERS
constantThe default social buttons: Google, Apple and Microsoft with their marks. Filter it or add your own { id, label, icon }.
LOGIN_PAGE_SAMPLE
constantThe demo content: the email typed in, the hero testimonial, the customer wordmarks and the code that passes the checks. Replace it with your own copy through the hero prop.
AuthProvider
typeA social sign-in button: { id, label, icon }. onProvider receives the id.
SignInValues
typeWhat onSignIn receives from the password form: { email, password, remember }.
Examples
Forgot password
The forgot password page: the typed email carries over and the request never reveals whether an account exists.
Check your email
After the reset request: Open Gmail for a Gmail address and a resend that waits with a countdown.
Set a new password
Strength meter, rules checklist and a matching confirmation; submit empty to see every error.
Two-step verification
Six digit authenticator code (123456 passes) with a switch to a 10 character backup code.
Code by email
methods={["otp", "password"]}: the first form sends a 6 digit code instead of a link.
Centered card, brand
layout="centered" without providers and with tone="brand" on the primary actions.
Card layout
layout="card": the form in a raised card on a dotted page background, the logo above it and the links below.
Neutral hero, en-GB
locale en-GB and the neutral hero (no photo).
Dependencies
Files
- components/blocks/login-page.tsx
- components/blocks/login-page-frame.tsx
- components/blocks/login-page-data.ts
FAQ
Is the React Login Page block free?
The preview, props and docs are free; copying the source needs a Pro plan. See plans.
How do I install Login Page?
Run npx wingo-ui@latest add login-page. It also adds the Wingo UI items it builds on (Marketing Section, Alert, Avatar, Button, Checkbox and 12 more) and the npm packages motion, lucide-react, react-hook-form and zod. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/login-page.
How does Login Page behave on phones?
On phones the form fills the screen with 48px fields and the hero is gone; with reduced motion views cross-fade.
See also
More React blocks
Articles using this component
- Antigravity MCP Setup: The Right Config Path and Prompts
Building UI with AI agents10 min read
- Codex Frontend Design Skill: Pair It With Real Components
Building UI with AI agents10 min read
- Is shadcn Free for Commercial Use? MIT vs Paid Kits
Comparisons and alternatives10 min read
- OpenCode MCP Setup: opencode.json for v1 and v2
Building UI with AI agents11 min read