Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Password Strength Validation Form for React

A password that needs 8 characters, mixed case, a number, and a symbol, plus a matching confirmation.

Password must be 8 characters with an uppercase letter, a lowercase letter, a number, and a symbol. Confirm Password has to match, or it shows Passwords don't match.

Use it when a new account needs a strong password. A length check alone fits a Password Input. In React, Base UI does not score the password.

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.
Use email insteadNo credit card

Usage

<form
  className="w-full max-w-md"
  noValidate
  onSubmit={form.handleSubmit(onSubmit)}
>
  <FieldGroup>
    <Controller
      control={form.control}
      name="password"
      render={({ field, fieldState }) => (
        <Field invalid={fieldState.invalid}>
          <FieldLabel htmlFor="form-password-strength-validation-password">
            Password
          </FieldLabel>
          <Input
            {...field}
            id="form-password-strength-validation-password"
            placeholder="Enter password"
            type="password"
          />
          <FieldDescription>
            Must contain uppercase, lowercase, number, and special
            character.
          </FieldDescription>
          <FieldError>{fieldState.error?.message}</FieldError>
        </Field>
      )}
    />
    <Controller
      control={form.control}
      name="confirmPassword"
{/* The rest of the file is under Installation. */}

FAQ

Which password rules run, and which message shows?

.min(8, "Password must be at least 8 characters"), then regexes for [A-Z], [a-z], [0-9] and [^A-Za-z0-9], each with its own message. The FieldError shows the first one that fails, in that order.

How are the two passwords compared?

The object's refine checks data.password === data.confirmPassword and fails with "Passwords don't match" on path: ["confirmPassword"], so it shows under Confirm Password. confirmPassword itself is just z.string().

Where are the rules written before an error?

The password's FieldDescription says "Must contain uppercase, lowercase, number, and special character." Confirm Password's says "Re-enter your password to confirm."

Are both fields masked?

Yes. Both Inputs are type="password", with the placeholders "Enter password" and "Confirm password", and field spread onto them.

What is submitted for an empty form?

Nothing. defaultValues sets both strings to "", so the length rule fails first and "Password must be at least 8 characters" shows before any character-class message.

What does Create Account receive?

Create Account is a type="submit" button. form.handleSubmit(onSubmit) calls onSubmit with both strings only after every rule and the match pass, and the demo logs them.

API Reference

Field

Sets invalid={fieldState.invalid}, htmlFor="form-password-strength-validation-password", htmlFor and orientation="horizontal". The rest is on the Field page.

Input

Sets field, id="form-password-strength-validation-password", placeholder="Enter password", type="password", id and placeholder="Confirm password". The rest is on the Input page.

Button

Sets type="submit". The rest is on the Button page.