Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Form examples · Patterns

Login Form for React

A login form with a welcome heading, email and password fields, a forgot password link and a sign up prompt.

Framework
UI library

Every app needs a way in. This login form has a Welcome back heading, an email and a password field, a forgot password link beside the password label, a full-width Sign In button and a sign up prompt. Each field is a Field with its FieldLabel and FieldError, wired to React Hook Form by a Controller and checked by a Zod schema. The max-w-sm form keeps it focused, for login pages, app entry points or member portals.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.

FAQ

What do email and password have to satisfy?

email is z.email("Please enter a valid email address.") and password is .min(8) with "Password must be at least 8 characters." Each field's FieldError shows its message when it fails.

How are the two inputs set up?

Email has type="email" and the placeholder you@example.com; password has type="password" and "Enter your password". Each Controller spreads field onto its Input, and defaultValues sets both to "".

What is the text above the fields?

An h1 says Welcome back and a muted paragraph says "Enter your credentials to access your account", centered in a flex flex-col gap-2 text-center block at the top of the FieldGroup.

Where does Forgot password go?

The password label row is flex items-center justify-between, with the FieldLabel on one side and an a with href="#" on the other. Point it at your reset page or open a dialog.

What is the line under Sign In?

A centered muted paragraph: Don't have an account? with a Sign up link to href="#". It sits with the w-full Sign In button in the last Field.

When does Sign In validate?

On submit, since mode is the default. form.handleSubmit(onSubmit) runs the schema and logs { email, password } to the console once both pass. Replace onSubmit with your sign-in request, and show a failed login above the button rather than on a field.