# Password Input

URL: https://ark-ui.com/docs/components/password-input
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/password-input.mdx

A component that allows users to enter secure text like (passwords and api keys)

---

<ComponentPreview id="PasswordInput" />

## Anatomy

<Anatomy id="password-input" />

```tsx
<PasswordInput.Root>
  <PasswordInput.Label />
  <PasswordInput.Control>
    <PasswordInput.Input />
    <PasswordInput.VisibilityTrigger>
      <PasswordInput.Indicator />
    </PasswordInput.VisibilityTrigger>
  </PasswordInput.Control>
</PasswordInput.Root>
```

## Examples

**Example: basic**

```ripple
import { PasswordInput } from 'ark-ripple/password-input';
import { Eye, EyeOff } from 'lucide-ripple';
import styles from 'styles/password-input.module.css';

export component Basic() {
  <PasswordInput.Root class={styles.Root}>
    <PasswordInput.Label class={styles.Label}>{'Password'}</PasswordInput.Label>
    <PasswordInput.Control class={styles.Control}>
      <PasswordInput.Input class={styles.Input} />
      <PasswordInput.VisibilityTrigger class={styles.VisibilityTrigger}>
        <PasswordInput.Indicator class={styles.Indicator} fallback={EyeOff}>
          <Eye />
        </PasswordInput.Indicator>
      </PasswordInput.VisibilityTrigger>
    </PasswordInput.Control>
  </PasswordInput.Root>
}

```

### Autocomplete

Use the `autoComplete` prop to manage autocompletion in the input.

- `new-password` — The user is creating a new password.
- `current-password` — The user is entering an existing password.

**Example: autocomplete**

```ripple
import { PasswordInput } from 'ark-ripple/password-input';
import { Eye, EyeOff } from 'lucide-ripple';
import styles from 'styles/password-input.module.css';

export component Autocomplete() {
  <PasswordInput.Root class={styles.Root} autoComplete="new-password">
    <PasswordInput.Label class={styles.Label}>{'Password'}</PasswordInput.Label>
    <PasswordInput.Control class={styles.Control}>
      <PasswordInput.Input class={styles.Input} />
      <PasswordInput.VisibilityTrigger class={styles.VisibilityTrigger}>
        <PasswordInput.Indicator class={styles.Indicator} fallback={EyeOff}>
          <Eye />
        </PasswordInput.Indicator>
      </PasswordInput.VisibilityTrigger>
    </PasswordInput.Control>
  </PasswordInput.Root>
}

```

### Controlled Visibility

Use the `visible` and `onVisibilityChange` props to control the visibility of the password input.

**Example: controlled-visibility**

```ripple
import { PasswordInput } from 'ark-ripple/password-input';
import { Eye, EyeOff } from 'lucide-ripple';
import { track } from 'ripple';
import styles from 'styles/password-input.module.css';

export component ControlledVisibility() {
  let visible = track(false);

  <PasswordInput.Root
    class={styles.Root}
    {visible}
    onVisibilityChange={(e) => {
      @visible = e.visible;
    }}
  >
    <PasswordInput.Label class={styles.Label}>
      {'Password is '}
      {@visible ? 'visible' : 'hidden'}
    </PasswordInput.Label>
    <PasswordInput.Control class={styles.Control}>
      <PasswordInput.Input class={styles.Input} />
      <PasswordInput.VisibilityTrigger class={styles.VisibilityTrigger}>
        <PasswordInput.Indicator class={styles.Indicator} fallback={EyeOff}>
          <Eye />
        </PasswordInput.Indicator>
      </PasswordInput.VisibilityTrigger>
    </PasswordInput.Control>
  </PasswordInput.Root>
}

```

### Root Provider

An alternative way to control the password input is to use the `RootProvider` component and the `usePasswordInput` hook.
This way you can access the state and methods from outside the component.

**Example: root-provider**

```ripple
import { PasswordInput, usePasswordInput } from 'ark-ripple/password-input';
import { Eye, EyeOff } from 'lucide-ripple';
import styles from 'styles/password-input.module.css';

export component RootProvider() {
  const passwordInput = usePasswordInput();

  <div class="stack">
    <output>
      {'password input is '}
      {@passwordInput.visible ? 'visible' : 'hidden'}
    </output>
    <PasswordInput.RootProvider class={styles.Root} value={passwordInput}>
      <PasswordInput.Label class={styles.Label}>{'Password'}</PasswordInput.Label>
      <PasswordInput.Control class={styles.Control}>
        <PasswordInput.Input class={styles.Input} />
        <PasswordInput.VisibilityTrigger class={styles.VisibilityTrigger}>
          <PasswordInput.Indicator class={styles.Indicator} fallback={EyeOff}>
            <Eye />
          </PasswordInput.Indicator>
        </PasswordInput.VisibilityTrigger>
      </PasswordInput.Control>
    </PasswordInput.RootProvider>
  </div>
}

```

### Field

Here's an example of how to use the `PasswordInput` component with the `Field` component.

**Example: with-field**

```ripple
import { Field } from 'ark-ripple/field';
import { PasswordInput } from 'ark-ripple/password-input';
import { Eye, EyeOff } from 'lucide-ripple';
import field from 'styles/field.module.css';
import styles from 'styles/password-input.module.css';

export component WithField() {
  <Field.Root class={field.Root}>
    <PasswordInput.Root class={styles.Root}>
      <PasswordInput.Label class={styles.Label}>{'Password'}</PasswordInput.Label>
      <PasswordInput.Control class={styles.Control}>
        <PasswordInput.Input class={styles.Input} />
        <PasswordInput.VisibilityTrigger class={styles.VisibilityTrigger}>
          <PasswordInput.Indicator class={styles.Indicator} fallback={EyeOff}>
            <Eye />
          </PasswordInput.Indicator>
        </PasswordInput.VisibilityTrigger>
      </PasswordInput.Control>
    </PasswordInput.Root>
    <Field.HelperText class={field.HelperText}>{'Enter your password'}</Field.HelperText>
    <Field.ErrorText class={field.ErrorText}>{'Password is required'}</Field.ErrorText>
  </Field.Root>
}

```

### Password Managers

Use the `ignorePasswordManager` prop to ignore password managers like 1Password, LastPass, etc. This is useful for
non-login scenarios (e.g., "api keys", "secure notes", "temporary passwords")

> **Currently, this only works for 1Password, LastPass, Bitwarden, Dashlane, and Proton Pass.**

**Example: ignore-password-manager**

```ripple
import { PasswordInput } from 'ark-ripple/password-input';
import { Eye, EyeOff } from 'lucide-ripple';
import styles from 'styles/password-input.module.css';

export component IgnorePasswordManager() {
  <PasswordInput.Root class={styles.Root} ignorePasswordManagers>
    <PasswordInput.Label class={styles.Label}>{'API Key'}</PasswordInput.Label>
    <PasswordInput.Control class={styles.Control}>
      <PasswordInput.Input class={styles.Input} defaultValue="spd_1234567890" />
      <PasswordInput.VisibilityTrigger class={styles.VisibilityTrigger}>
        <PasswordInput.Indicator class={styles.Indicator} fallback={EyeOff}>
          <Eye />
        </PasswordInput.Indicator>
      </PasswordInput.VisibilityTrigger>
    </PasswordInput.Control>
  </PasswordInput.Root>
}

```

### Strength Meter

Combine the `PasswordInput` with a password strength library to show visual feedback about password strength. This
example uses the [`check-password-strength`](https://www.npmjs.com/package/check-password-strength) package to provide
real-time strength validation.

**Example: strength-meter**

```ripple
import { PasswordInput } from 'ark-ripple/password-input';
import { passwordStrength, type Options } from 'check-password-strength';
import { Eye, EyeOff } from 'lucide-ripple';
import { track } from 'ripple';
import styles from 'styles/password-input.module.css';

const strengthOptions: Options<string> = [
  { id: 0, value: 'weak', minDiversity: 0, minLength: 0 },
  { id: 1, value: 'medium', minDiversity: 2, minLength: 6 },
  { id: 2, value: 'strong', minDiversity: 4, minLength: 8 },
];

export component StrengthMeter() {
  let password = track('asdfasdf');

  let strength = track(() => {
    if (!@password) return null;
    const { value } = passwordStrength(@password, strengthOptions);
    return value;
  });

  <PasswordInput.Root class={styles.Root}>
    <PasswordInput.Label class={styles.Label}>{'Password'}</PasswordInput.Label>
    <PasswordInput.Control class={styles.Control}>
      <PasswordInput.Input
        class={styles.Input}
        value={password}
        onInput={(e) => {
          @password = e.currentTarget.value;
        }}
        placeholder="Enter your password"
      />
      <PasswordInput.VisibilityTrigger class={styles.VisibilityTrigger}>
        <PasswordInput.Indicator class={styles.Indicator} fallback={EyeOff}>
          <Eye />
        </PasswordInput.Indicator>
      </PasswordInput.VisibilityTrigger>
    </PasswordInput.Control>
    if (@strength) {
      <div class={styles.StrengthMeter}>
        <div class={styles.StrengthBar}>
          <div class={styles.StrengthFill} data-strength={@strength} />
        </div>
        <div class={styles.StrengthLabel}>
          {@strength}
          {' password'}
        </div>
      </div>
    }
  </PasswordInput.Root>
}

```

### Validation

Combine with custom validation logic to show real-time feedback. Use the `invalid` prop to indicate validation errors.

**Example: with-validation**

```ripple
import { PasswordInput } from 'ark-ripple/password-input';
import { Eye, EyeOff } from 'lucide-ripple';
import { track } from 'ripple';
import styles from 'styles/password-input.module.css';

export component WithValidation() {
  let password = track('');
  let isValid = track(() => @password.length >= 8);

  <PasswordInput.Root class={styles.Root} invalid={!@isValid && @password.length > 0}>
    <PasswordInput.Label class={styles.Label}>{'Password (min 8 characters)'}</PasswordInput.Label>
    <PasswordInput.Control class={styles.Control}>
      <PasswordInput.Input
        class={styles.Input}
        value={password}
        onInput={(e) => {
          @password = e.target.value;
        }}
        placeholder="Enter your password"
      />
      <PasswordInput.VisibilityTrigger class={styles.VisibilityTrigger}>
        <PasswordInput.Indicator class={styles.Indicator} fallback={EyeOff}>
          <Eye />
        </PasswordInput.Indicator>
      </PasswordInput.VisibilityTrigger>
    </PasswordInput.Control>
    if (@password.length > 0 && !@isValid) {
      <p class={styles.ValidationMessage} data-valid="false">
        {'Password must be at least 8 characters'}
      </p>
    }
    if (@isValid && @password.length > 0) {
      <p class={styles.ValidationMessage} data-valid="true">{'Password is valid'}</p>
    }
  </PasswordInput.Root>
}

```

## API Reference

### Props

**Component API Reference**

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `autoComplete` | `'current-password' | 'new-password'` | No | The autocomplete attribute for the password input. |
| `defaultVisible` | `boolean` | No | The default visibility of the password input. |
| `disabled` | `boolean` | No | Whether the password input is disabled. |
| `id` | `string` | No | The unique identifier of the machine. |
| `ids` | `Partial<{ input: string; visibilityTrigger: string }>` | No | The ids of the password input parts |
| `ignorePasswordManagers` | `boolean` | No | When `true`, the input will ignore password managers.

**Only works for the following password managers**
- 1Password, LastPass, Bitwarden, Dashlane, Proton Pass |
| `invalid` | `boolean` | No | The invalid state of the password input. |
| `name` | `string` | No | The name of the password input. |
| `onVisibilityChange` | `(details: VisibilityChangeDetails) => void` | No | Function called when the visibility changes. |
| `readOnly` | `boolean` | No | Whether the password input is read only. |
| `required` | `boolean` | No | Whether the password input is required. |
| `translations` | `Partial<{ visibilityTrigger: ((visible: boolean) => string) | undefined }>` | No | The localized messages to use. |
| `visible` | `boolean` | No | Whether the password input is visible. |


**Root Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | password-input |
| `[data-part]` | root |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |


**Control Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Control Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | password-input |
| `[data-part]` | control |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |


**Indicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `fallback` | `string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<...>` | No | The fallback content to display when the password is not visible. |


**Indicator Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | password-input |
| `[data-part]` | indicator |
| `[data-state]` | "visible" | "hidden" |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |


**Input Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Input Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | password-input |
| `[data-part]` | input |
| `[data-state]` | "visible" | "hidden" |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |


**Label Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Label Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | password-input |
| `[data-part]` | label |
| `[data-disabled]` | Present when disabled |
| `[data-invalid]` | Present when invalid |
| `[data-readonly]` | Present when read-only |
| `[data-required]` | Present when required |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UsePasswordInputReturn` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**VisibilityTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**VisibilityTrigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | password-input |
| `[data-part]` | visibility-trigger |
| `[data-readonly]` | Present when read-only |
| `[data-disabled]` | Present when disabled |
| `[data-state]` | "visible" | "hidden" |


### Context

**API:**

| Property | Type | Description |
|----------|------|-------------|
| `visible` | `boolean` | Whether the password input is visible. |
| `disabled` | `boolean` | Whether the password input is disabled. |
| `invalid` | `boolean` | Whether the password input is invalid. |
| `focus` | `VoidFunction` | Focus the password input. |
| `setVisible` | `(value: boolean) => void` | Set the visibility of the password input. |
| `toggleVisible` | `VoidFunction` | Toggle the visibility of the password input. |
