# Password input

A secret field, such as an API key or an SMTP password, with a button that shows or hides the value.

- **Import:** `import { PasswordInput } from "@booleanpress/ui/password-input"`
- **Page:** <https://ui.booleanpress.com/components/password-input> · @booleanpress/ui 0.1.0

## Usage

`PasswordInput` is an `InputGroup` with a show/hide button. It is the products' own composition, not a stock component. Name it with a `Label` whose `htmlFor` is its `id`.

```tsx
import { Label } from "@booleanpress/ui/label"
import { PasswordInput } from "@booleanpress/ui/password-input"

export function ApiKey() {
  return (
    <div className="flex flex-col gap-2">
      <Label htmlFor="api-key">API key</Label>
      <PasswordInput id="api-key" />
    </div>
  )
}
```

It takes the attributes of a native `input` except `type`, and `className` goes on the group. It starts hidden and keeps its own show/hide state. It is for a provider secret, not a sign-in: it sets `autocomplete="new-password"` and the 1Password and LastPass ignore attributes, so a password manager does not fill in the site's saved login. Pass your own `autoComplete` to override that. The button's name comes from the provider string `showPassword`; `aria-pressed` says whether the value is shown.

## Examples

### Basic

A hidden value; the button shows it.

```tsx
import { Label } from "@booleanpress/ui/label"
import { PasswordInput } from "@booleanpress/ui/password-input"

export default function PasswordInputBasic() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <Label htmlFor="api-key">API key</Label>
      <PasswordInput id="api-key" defaultValue="sk_live_51Hx0example" />
    </div>
  )
}
```

### Invalid

`aria-invalid` draws the error border around the group; `aria-describedby` reads the message.

```tsx
import { Label } from "@booleanpress/ui/label"
import { PasswordInput } from "@booleanpress/ui/password-input"

export default function PasswordInputInvalid() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <Label htmlFor="smtp-password">SMTP password</Label>
      <PasswordInput id="smtp-password" aria-invalid aria-describedby="smtp-password-error" />
      <p id="smtp-password-error" className="text-sm text-destructive">
        Enter the password your provider gave you.
      </p>
    </div>
  )
}
```

### Disabled

Neither the input nor the show/hide button can be used.

```tsx
import { Label } from "@booleanpress/ui/label"
import { PasswordInput } from "@booleanpress/ui/password-input"

export default function PasswordInputDisabled() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <Label htmlFor="locked-key">Licence key</Label>
      <PasswordInput id="locked-key" defaultValue="BSMTP-0000-0000" disabled />
    </div>
  )
}
```

## Accessibility

**Semantics.** A native `input` (`type="password"`, or `text` while shown) and a native toggle `button`: one name, "Show password", and `aria-pressed` that is true while the value is shown.

**Labels.** Name the input with a `Label htmlFor` or `aria-label`. The button is named by the provider string `showPassword`; translate it with `BooleanUIProvider`.

**Focus.** The button is in the tab order after the input, so a keyboard user can reveal the value. The focus ring is drawn on the group when the input has keyboard focus.

**Known limits.**

- A password input has no `textbox` role, so find it by its label, not by role.

### Keyboard

| Key | Behaviour |
| --- | --- |
| Enter + Space | On the show/hide button: switches between showing and hiding the value. |

## API

### PasswordInput

Renders a `input` and passes it every other prop.

Every part takes `className`, merged with its defaults by `cn()`, and `ref`, which reaches the element it renders.

**Provider strings:** `showPassword` (`BooleanUIProvider`'s `strings`).

## Theming
