PasswordField
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/password-field.jsonThe reveal is the component, and it is not a convenience. A masked field is the only one in a form where a typo cannot be seen, so people either paste or type slowly and get it wrong anyway. The toggle is what turns an unverifiable field into a checkable one, and it is why long passphrases became usable.
What it costs is a moment where the password is on the screen, so the component states its two rules rather than leaving them to each product:
- it always starts masked, and there is no prop to start it revealed;
- revealing is the reader’s own action — never a default, and never something a form can turn on for them.
<PasswordField value={password} onValueChange={setPassword} showLabel="Show password" hideLabel="Hide password" autoComplete="current-password"/>The two labels are required. The button’s name is what a screen reader announces, and it changes with the state — it describes the action, not the condition. A default here would be English shipped inside a primitive.
autoComplete is not defaulted either. current-password on a login,
new-password on a sign-up; getting it wrong is how a password manager fills
the wrong box, and only the product knows which form this is.
The button is type="button". One that defaults to submit sends the form
on the first click, with the password half typed.
| Prop | Type | Default | |
|---|---|---|---|
value |
string |
Controlled | |
defaultValue |
string |
Uncontrolled | |
onValueChange |
(value) => void |
||
showLabel |
string |
Required. The button while masked | |
hideLabel |
string |
Required. The button while showing | |
autoComplete |
string |
current-password or new-password |
|
disabled, readOnly, required |
boolean |
false |