# Password Input

> A password field with a caret-safe reveal toggle, a Caps Lock warning and, for sign-up, a strength meter, rules checklist and generator.

- Type: React component (Inputs)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add password-input`
- Docs: https://wingo-ui.com/components/password-input

## Interaction

Tap the eye and the dots turn into text with the icon turning a quarter over; the caret and any selection stay exactly where they were, and the button stays in the Tab order. With Caps Lock on, a small amber warning slides in under the box and leaves when you release it or leave the field. With strength on, four bars fill left to right as you type, red, then amber, then green, with the verdict next to them, and a checklist opens on focus with each rule drawing its check the moment it is met; it stays open while there is text, so the submit button never jumps away under your finger. The wand fills a random 16-character password, reveals it until you leave the field and scores it Strong. On a phone both buttons have 44px hit areas, iOS never zooms and the checklist scrolls into view above the keyboard.

## Installation

```bash
npx wingo-ui@latest add password-input
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/password-input` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `components/ui/password-input.tsx`

npm dependencies: `npm i motion lucide-react`

Wingo UI dependencies (installed automatically):

- [Input](https://wingo-ui.com/components/input) ([Markdown](https://wingo-ui.com/components/input.md))
- [Field](https://wingo-ui.com/components/field) ([Markdown](https://wingo-ui.com/components/field.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [useControllableState](https://wingo-ui.com/components/use-controllable-state) ([Markdown](https://wingo-ui.com/components/use-controllable-state.md))
- [useMediaQuery](https://wingo-ui.com/components/use-media-query) ([Markdown](https://wingo-ui.com/components/use-media-query.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))

## Usage

```tsx
import { PasswordInput, passwordRules } from "@/components/ui/password-input"

const rules = passwordRules({
  minLength: 10,
  labels: { length: (n) => "At least " + n + " characters", lower: "One lowercase letter", upper: "One uppercase letter", number: "One digit", symbol: "One symbol" },
})

export function SignUp() {
  return (
    <form className="flex flex-col gap-4">
      <PasswordInput
        name="password"
        label="Password"
        strength
        rules={rules}
        strengthLabels={["Too weak", "Weak", "Okay", "Good", "Strong"]}
        generate
        required
      />
    </form>
  )
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label?` | `ReactNode` | `""` | The label above the box, linked with htmlFor. |
| `description?` | `ReactNode` | `""` | Helper text under the box, linked with aria-describedby. The error takes its place while it shows. |
| `error?` | `ReactNode` | `""` | Replaces the description, slides in and marks the field invalid. |
| `required?` | `boolean` | `false` | The red mark after the label and the native required attribute. |
| `disabled?` | `boolean` | `false` | Dims the field and blocks input and the reveal toggle; the generator hides. |
| `invalid?` | `boolean` | `false` | The red ring and aria-invalid without a message, when the form shows the error elsewhere. |
| `readOnly?` | `boolean` | `false` | The password stays selectable and can still be revealed, but cannot change; the generator hides. The demo fills in a sample value. |
| `placeholder?` | `string` | `""` | Hint text while the field is empty. |
| `defaultValue?` | `string` | `""` | The starting password while uncontrolled; value and onValueChange control it. The meter scores this first value until the field is focused, so a password manager filling the field never makes it flash. |
| `showLabel?` | `string` | `"Show password"` | The toggle's aria-label and hover title while the password is hidden. |
| `hideLabel?` | `string` | `"Hide password"` | The toggle's aria-label and hover title while the password shows. |
| `capsLockLabel?` | `ReactNode` | `"Caps Lock is on"` | The warning under the box. |
| `strengthCaption?` | `string` | `"Password strength"` | The caption under the meter, left of the verdict, and the prefix screen readers hear. |
| `generateLabel?` | `string` | `"Generate a strong password"` | The wand button's aria-label and hover title. |
| `ruleMetLabel?` | `string` | `"met"` | Read by screen readers after a met rule, visually hidden. |
| `ruleUnmetLabel?` | `string` | `"not met"` | Read by screen readers after a rule that is not met yet, visually hidden. |
| `size?` | `"sm" \| "md" \| "lg"` | `"md"` | Height 32 / 40 / 48px like every field (md 44px on touch); the eye and wand buttons follow. |
| `variant?` | `"soft" \| "outline" \| "underline" \| "ghost"` | `"soft"` | The field box look, shared with Input. |
| `radius?` | `"none" \| "sm" \| "md" \| "lg" \| "full"` | `"md"` | Corner shape, scaled with the size; full makes a pill. |
| `accent?` | `string` | `""` | Any CSS color for the focus ring and the caret. Empty uses the ring token. |
| `floatingLabel?` | `boolean` | `false` | The label rests inside the box and floats up on focus or when filled, like Input. |
| `defaultVisible?` | `boolean` | `false` | Starts with the password shown as text. Use visible and onVisibleChange to control it. |
| `showToggle?` | `boolean` | `true` | The eye button at the end of the box. It is a real button in the Tab order with aria-pressed and aria-controls; switching keeps the caret and selection. |
| `strength?` | `boolean` | `false` | Turns the field into a sign-up field: the four-bar meter with its verdict, the rules checklist and autoComplete new-password. The verdict is announced politely 500ms after typing stops. |
| `showRules?` | `"focus" \| "always" \| "never"` | `"focus"` | When strength is on: the checklist opens on focus and stays while there is text (so the button under it never moves on blur), always shows, or never shows. |
| `capsLockWarning?` | `boolean` | `true` | Reads Caps Lock from the key and pointer events while the field is focused and shows the warning (role status). Hidden on blur; phones never report it. |
| `generate?` | `boolean` | `false` | A wand button before the eye: fills a random password from crypto.getRandomValues (no 0 O l 1 I, at least one lowercase, uppercase, digit and symbol, no runs), fires onChange like typing, and reveals it until focus leaves the field. |
| `generateLength?` | `number` | `16` | Length of a generated password. |
| `maxLength?` | `number` | `0` | The native character limit, also applied to typing after a generated password. 0 means no limit. |
| `visible?` | `boolean` |  | Shown as text, controlled. Without onVisibleChange the toggle does nothing. |
| `onVisibleChange?` | `(visible: boolean) => void` |  | Fires when the toggle, the generator or the blur after a generated password changes the visibility. |
| `rules?` | `PasswordRule[]` |  | The checklist, { id, label, test(password) }. Defaults to passwordRules(): at least 8 characters, a lowercase letter, an uppercase letter, a number, a symbol. The rule with id length also sets the minimum for the score. |
| `score?` | `(password: string) => PasswordScore` |  | Replaces the scorer, e.g. with zxcvbn loaded by the app. Defaults to scorePassword (see Parts), a quick guide rather than a guarantee. |
| `strengthLabels?` | `[string, string, string, string, string]` | `"[\"Too weak\", \"Weak\", \"Fair\", \"Good\", \"Strong\"]"` | The verdict per score, default ["Too weak", "Weak", "Fair", "Good", "Strong"]. |
| `onGenerate?` | `(password: string) => void` |  | Called with the generated password, e.g. to offer a copy button. |
| `showIcon?` | `ReactNode` |  | The toggle icon while hidden (Eye by default). |
| `hideIcon?` | `ReactNode` |  | The toggle icon while shown (EyeOff by default). |
| `generateIcon?` | `ReactNode` |  | The generator icon (WandSparkles by default). |
| `autoComplete?` | `string` |  | Defaults to "current-password", or "new-password" with strength or generate, so password managers save and suggest correctly. A manager's own icon may sit over the end of the box; there is room for it before the toggle. |
| `enterKeyHint?` | `"enter" \| "done" \| "go" \| "next" \| "previous" \| "search" \| "send"` |  | The label of the phone keyboard's return key: "go" for a login field, "next" with strength (a sign-up form usually continues). |
| `value?` | `string` |  | The password, controlled, with onValueChange. Every other Input prop works too: name, onBlur, prefix, leftIcon, fieldProps... (not clearable, loading, showCount or rightIcon: the eye and wand own the end of the box). |
| `onValueChange?` | `(value: string) => void` |  | Fires with the new password on every edit, including a generated one. |
| `onChange?` | `(event: ChangeEvent<HTMLInputElement>) => void` |  | The native change event, untouched. A generated password fires it too, like typing. |
| `prefix?` | `ReactNode` |  | Text or an element before the input, in the muted addon look. |
| `suffix?` | `ReactNode` |  | Text or an element after the input, placed before the wand and eye buttons. |
| `leftIcon?` | `ReactNode` |  | A leading icon such as a lock; unsized svgs follow the size (14 / 16 / 18px). |
| `fieldProps?` | `Partial<FieldProps>` |  | Anything else for the Field wrapper, e.g. labelAction: <a href="/reset">Forgot password?</a>. |
| `ref?` | `RefObject<HTMLInputElement \| null> or (node) => void` |  | The native input. |
| `classNames?` | `Partial<Record<InputSlot \| "root" \| "toggle" \| "generate" \| "strength" \| "meter" \| "segment" \| "strengthLabel" \| "rules" \| "rule" \| "capsLock", string>>` |  | Extra classes for the inner parts: the Input keys (box, input, label...) plus the password parts. |
| `className?` | `string` |  | Classes for the root wrapper around the field, the warning, the meter and the checklist. |

## Parts

### passwordRules (function)

Builds the default checklist (length, lowercase, uppercase, number, symbol) with your minimum length and translated labels. Letters are Unicode aware, so é and Ø count.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `minLength?` | `number` | `8` | The length rule's minimum; also the length below which scorePassword returns 0. |
| `labels?` | `Partial<PasswordRuleLabels>` |  | Text per rule: length (a node or (min) => node), lower, upper, number, symbol. |
| `returns?` | `PasswordRule[]` |  | Rules to pass to the rules prop. |

### scorePassword (function)

The default strength score from 0 to 4: 0 when empty, short or common (password, qwerty...), +1 per met rule beyond length (max 3), +1 for 12+ characters, -1 for repeats or runs like 1234.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `password` | `string` |  | The text to score. |
| `rules?` | `PasswordRule[]` | `"passwordRules()"` | The checklist; its length rule sets the minimum. |
| `returns?` | `0 \| 1 \| 2 \| 3 \| 4` |  | The score the meter shows. |

### generatePassword (function)

A random password with at least one lowercase letter, uppercase letter, digit and symbol, drawn with crypto.getRandomValues and free of look-alikes (0, O, l, 1, I). The wand button uses it.

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `length?` | `number` | `16` | Characters, clamped to 4 to 128. |
| `returns?` | `string` |  | The new password. |

### PasswordRule (type)

One checklist row: { id, label, test(password) => boolean }.

### PasswordScore (type)

The strength score, 0 (too weak) to 4 (strong).

## Examples

- **Sign-up with rules**: Custom rule copy from passwordRules({ minLength: 10, labels }) and custom verdicts: the bars fill as you type and each rule draws its check when met.
- **Caps Lock warning**: Turn Caps Lock on and type: an amber warning slides in under the box, and leaves when you turn it off or leave the field.
- **Generator**: The wand fills a random 16-character password (no look-alike characters), reveals it until you leave the field and scores it strong; the copy button sits outside.
- **Confirm password**: A second field checks the match on blur and turns green once both are the same.
- **Controlled visibility**: visible and onVisibleChange driven by one checkbox for two fields, with showToggle off.
- **Sizes and variants**: sm, md and lg, then outline with the generator, underline, and a ghost pill that starts visible.

## See also

- [Input](https://wingo-ui.com/components/input) ([Markdown](https://wingo-ui.com/components/input.md))
- [Field](https://wingo-ui.com/components/field) ([Markdown](https://wingo-ui.com/components/field.md))
- [OTP Input](https://wingo-ui.com/components/otp-input) ([Markdown](https://wingo-ui.com/components/otp-input.md))
- [Button](https://wingo-ui.com/components/button) ([Markdown](https://wingo-ui.com/components/button.md))

---

Canonical: https://wingo-ui.com/components/password-input
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
