Password input
A password field with a show/hide toggle, and an optional strength meter and requirement checklist for new passwords.
View as Markdown for coding assistants, or see llms.txt.
- New
- Group: Inputs
- Added in @azmr/ui 0.7.0
Usage
import { PasswordInput, passwordRequirements } from "@azmr/ui/password-input";<form
className="flex w-full max-w-sm flex-col gap-4"
onSubmit={(event) => event.preventDefault()}
>
<Field label="Email">
<Input name="email" type="email" autoComplete="username" />
</Field>
<Field label="Password">
<PasswordInput name="password" autoComplete="current-password" />
</Field>
</form>PasswordInput is an Input group with a show/hide button. Put it in a Field for its label, description and error. ref is the real <input>, so register() from React Hook Form works without a Controller.
It follows NCSC and NIST guidance for password fields:
autoCompletedefaults tocurrent-password. SetautoComplete="new-password"on sign-up and change-password forms, so password managers suggest a new one.- Paste is never blocked, so people can use a password manager.
- Spell check, autocorrect and autocapitalise are off.
- The password is hidden again when its form submits. A password manager only offers to save a field that is
type="password"at that moment.
Show and hide
The toggle is a button named "Show password" with aria-pressed. Its name stays the same, and screen readers announce "pressed" or "not pressed" as it changes, which says whether the password is visible. It is type="button", so it never submits the form. Change its name with toggleLabel, start shown with defaultVisible, or control it with visible and onVisibleChange.
New passwords
Try a few unrelated words.
- At least 12 characters, not done.
- A number, not done.
- A symbol, such as ! or #, not done.
<div className="w-full max-w-sm">
<Field label="New password" description="Try a few unrelated words.">
<PasswordInput
name="new-password"
autoComplete="new-password"
strength
requirements={RULES}
/>
</Field>
</div>For a new password, add strength for a meter and requirements for a checklist. Both are read with the input through aria-describedby. The meter is not announced on every key, which would be noisy while typing; when a rule in the checklist is met or stops being met, that change alone is announced politely, such as "A number: done".
Strength
strength uses a small built-in scorer that weighs length most, as NCSC and NIST advise, and marks down common and patterned passwords. It returns a score from 0 to 4 and, below "Strong", one suggestion. For a better estimate, pass your own scorer. zxcvbn-ts uses the same 0 to 4 scale:
import { zxcvbn } from "@zxcvbn-ts/core";
<PasswordInput
autoComplete="new-password"
strength={(password) => {
const result = zxcvbn(password);
return { score: result.score, suggestion: result.feedback.suggestions[0] };
}}
/>zxcvbn-ts is not a dependency of @azmr/ui; install it only if you use it. Rename the levels with strengthLabels.
The meter is guidance. Enforce the rules that matter on the server, and check new passwords against breached-password lists there.
Requirements
passwordRequirements has ready-made rules: minLength(n), lowercase(), uppercase(), number() and symbol(). Each takes an optional label. Write your own as { id, label, test }. The words read after each rule ("done" and "not done") can be changed with requirementStatus.
Keep the list short. A minimum length matters most; character-type rules push people towards predictable patterns such as Password1!.
With react-hook-form
<Field label="New password" error={errors.password?.message}>
<PasswordInput
autoComplete="new-password"
strength
requirements={[passwordRequirements.minLength(12)]}
{...register("password", { minLength: { value: 12, message: "Use at least 12 characters" } })}
/>
</Field>The meter and checklist read the value React Hook Form writes to the field, including defaultValues.
Props
Prop
Type
PasswordInput also takes every Input prop except type, including debounceMs and onCommit, for example to check a new password against a breached-password service once typing stops. className styles the wrapper that holds the input, meter and checklist.
Accessibility
- The toggle is a real button with a fixed name and
aria-pressed, so its state is announced without the name changing under the user. - The strength level and the requirement checklist are part of the input's description, read when it gets focus.
- Requirement changes are announced politely, only for the rules that changed.
- Each rule's state is given in words as well as by its icon and colour.
| Key | Action |
|---|---|
| Tab | Moves focus to the input, then to the show/hide button. |
| Enter | On the show/hide button, shows or hides the password. |
| Space | On the show/hide button, shows or hides the password. |