Skip to content

PasswordField

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/password-field.json
See it liveMasked, revealed, and inside a Field with an error.

The 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