Password Input
A masked password field with an independent, keyboard-accessible visibility toggle. Uses Input borders, focus and validation, and Phosphor Eye/EyeSlash icons.
Installation
Add the component and its dependencies from the registry running on your computer.
npx shadcn@latest add https://brutallab.facilito.dev/r/password-input.jsonUsage
Import the component into your project and keep the source code under your control.
'use client';
import { PasswordInput } from '@/components/ui/password-input';
import { Label } from '@/components/ui/label';
export default function Demo() {
return (
<div className="grid w-full max-w-md gap-6">
<div className="grid gap-2">
<Label htmlFor="password-demo">Password</Label>
<PasswordInput id="password-demo" autoComplete="new-password" placeholder="Enter a password" />
</div>
<div className="grid gap-2">
<Label htmlFor="password-error">Invalid password</Label>
<PasswordInput id="password-error" aria-invalid="true" aria-describedby="password-error-message" defaultValue="short" autoComplete="new-password" />
<p id="password-error-message" className="bl-type-small text-destructive">Use at least 10 characters.</p>
</div>
<div className="grid gap-2">
<Label htmlFor="password-disabled">Disabled</Label>
<PasswordInput id="password-disabled" disabled defaultValue="not-editable" />
</div>
</div>
);
}
States & interaction
Appearance, behavior and keyboard checks.
- Masked initially. Eye reveals the password; EyeSlash masks it without changing the typed value. Each field has independent state.
- The ghost button changes surface and border on hover. Tab shows focus; Enter and Space toggle visibility without submitting the form.
- Invalid uses the Input error border and an associated message. Disabled disables both the field and the button.
- Test the example with Tab and Shift+Tab. Focus must stay visible in both themes.
API Reference
BrutalLab-specific properties. Native attributes are supported as well.
| Prop | Type | Default | Description |
|---|---|---|---|
| locale | en / es | en | Language of the visibility button label. |
| showLabel / hideLabel | string | Show password / Hide password | Override accessible names and tooltips; distinguish current and new passwords in the same form. |
| containerClassName | string | — | Styles the wrapper. className styles the input; reserve room for the trailing button. |
| Native input props | ComponentProps<'input'> except type | — | Supports ref, id, value, onChange, disabled, required, autoComplete, aria-invalid and aria-describedby. Visibility never changes the value. |
Accessibility
Rules that should remain intact when adapting the component to a product.
Place a visible label before the component and associate it through htmlFor and id. Do not wrap the input and button inside a label.
Tab reaches the input and visibility button; Enter or Space on the button toggles visibility without submitting the form. The accessible name and tooltip describe the next action.
Masked by default. Each field has its own state. Disabled also disables the visibility button. Read-only fields remain revealable.
Show errors through aria-invalid and an associated message. Only the consuming application validates passwords.