Password strength
Show how strong a new password is while it is typed.
passwordstrength metervalidation
Preview
Password strength preview
Live · keyboard ready
- At least 12 characters, not met
- Upper and lowercase letters, not met
- At least one number, not met
- At least one symbol, not met
Strength is the share of rules met, spread over four steps.
When to use
- Sign up and change password forms.
- Password rules that should check off live as the person types.
When not to use
- Use password-field for sign in.
- Use progress for measurable progress unrelated to passwords.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "password-strength",
"type": "registry:ui",
"title": "Password strength",
"description": "Show how strong a new password is while it is typed.",
"categories": [
"inputs"
],
"dependencies": [
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/password-strength/password-strength.tsx",
"type": "registry:component",
"target": "@components/manicat/password-strength/password-strength.tsx"
},
{
"path": "registry/components/password-strength/password-strength.module.css",
"type": "registry:component",
"target": "@components/manicat/password-strength/password-strength.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/password-strength",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/password-strength",
"markdown": "https://uiarc.dev/components/password-strength/markdown",
"tags": [
"password",
"strength meter",
"validation"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { useState } from "react";
import { PasswordStrength } from "@/components/manicat/password-strength/password-strength";
export function PasswordStrengthExample() {
const [value, setValue] = useState("");
return (
<div className="grid w-full max-w-sm gap-4">
<PasswordStrength label="Password" value={value} onValueChange={(next) => setValue(next)} />
<p className="text-sm text-(color:--text-muted)">Strength is the share of rules met, spread over four steps.</p>
</div>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Strength meter The meter on its own, driven by whatever the user has typed so far.
Strength meter
The meter on its own, driven by whatever the user has typed so far. preview
Live · keyboard ready
- At least 12 characters, not met
- Upper and lowercase letters, not met
- At least one number, not met
- At least one symbol, not met
Add digits, symbols and length to move the meter.
strength-meter-the-meter-on-its-own-driven-by-whatever-the-user-has-typed-so-far-.tsxtsx
"use client";
import { useState } from "react";
import { PasswordStrength } from "@/components/manicat/password-strength/password-strength";
export function PasswordStrengthLiveExample() {
const [value, setValue] = useState("manicat");
return (
<div className="grid w-full max-w-sm gap-3">
<PasswordStrength label="Password" value={value} onValueChange={setValue} />
<p className="text-sm text-(color:--text-muted)">Add digits, symbols and length to move the meter.</p>
</div>
);
}
Keyboard interactions
| Keys | Action |
|---|---|
| Enter / Space | On the reveal button, shows or hides the password. |
Accessibility
- The meter is role="meter" with aria-valuenow 0 to 4 and aria-valuetext set to the strength word.
- The rules list is linked to the input through aria-describedby along with any error; errors set aria-invalid.
- A role="status" region summarizes strength and rules met; the reveal button uses aria-pressed and aria-controls.
Motion
- Segments fill and change tone in a staggered wave, rules check off with drawn ticks, remaining counts roll, and the word morphs up or down with strength.
- Reduced motion, applied after hydration, drops the shake, wave, and roll in favor of instant changes.
Responsive behavior
- On coarse pointers the input grows to the base font size, so iOS does not zoom on focus.
- The four-segment meter shares the row width evenly and shrinks with the column.
Performance
- Scoring runs on the device on every keystroke with simple rule tests; there is no dictionary check.
- One ResizeObserver per field measures the helper row for its height spring; cheap for a form, but avoid hundreds in a table.
Notes for AI
- Use when creating or changing a password. Use password-field for sign in.
- Controlled or uncontrolled; read strength from onValueChange to gate submit. Scoring runs on the device.
- Also exports estimateStrength(password, rules, { shortLength, levels, countCharacters }), defaultPasswordRules, and createPasswordRules({ minLength, labels, countCharacters }) for server-side checks, translated rule labels, or your own length policy.
- To translate, pass messages for the component's own copy and build rules with createPasswordRules({ labels }) for the rule labels. Keep shortLength and the rules' minLength in line with your server's policy.