# Password Input

URL: https://ark-ui.com/docs/components/password-input
LLM: https://ark-ui.com/llms.txt/components/password-input

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

---



## Anatomy



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

## Examples

```tsx
import { PasswordInput } from '@ark-ui/react/password-input'
import { EyeIcon, EyeOffIcon } from 'lucide-react'
import styles from 'styles/password-input.module.css'

export const Basic = () => (
  <PasswordInput.Root className={styles.Root}>
    <PasswordInput.Label className={styles.Label}>Password</PasswordInput.Label>
    <PasswordInput.Control className={styles.Control}>
      <PasswordInput.Input className={styles.Input} />
      <PasswordInput.VisibilityTrigger className={styles.VisibilityTrigger}>
        <PasswordInput.Indicator className={styles.Indicator} fallback={<EyeOffIcon />}>
          <EyeIcon />
        </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.

```tsx
import { PasswordInput } from '@ark-ui/react/password-input'
import { EyeIcon, EyeOffIcon } from 'lucide-react'
import styles from 'styles/password-input.module.css'

export const Autocomplete = () => (
  <PasswordInput.Root className={styles.Root} autoComplete="new-password">
    <PasswordInput.Label className={styles.Label}>Password</PasswordInput.Label>
    <PasswordInput.Control className={styles.Control}>
      <PasswordInput.Input className={styles.Input} />
      <PasswordInput.VisibilityTrigger className={styles.VisibilityTrigger}>
        <PasswordInput.Indicator className={styles.Indicator} fallback={<EyeOffIcon />}>
          <EyeIcon />
        </PasswordInput.Indicator>
      </PasswordInput.VisibilityTrigger>
    </PasswordInput.Control>
  </PasswordInput.Root>
)
```

### Controlled Visibility

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

```tsx
import { PasswordInput } from '@ark-ui/react/password-input'
import { EyeIcon, EyeOffIcon } from 'lucide-react'
import { useState } from 'react'
import styles from 'styles/password-input.module.css'

export const ControlledVisibility = () => {
  const [visible, setVisible] = useState(false)
  return (
    <PasswordInput.Root className={styles.Root} visible={visible} onVisibilityChange={(e) => setVisible(e.visible)}>
      <PasswordInput.Label className={styles.Label}>Password is {visible ? 'visible' : 'hidden'}</PasswordInput.Label>
      <PasswordInput.Control className={styles.Control}>
        <PasswordInput.Input className={styles.Input} />
        <PasswordInput.VisibilityTrigger className={styles.VisibilityTrigger}>
          <PasswordInput.Indicator className={styles.Indicator} fallback={<EyeOffIcon />}>
            <EyeIcon />
          </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.

```tsx
import { PasswordInput, usePasswordInput } from '@ark-ui/react/password-input'
import { EyeIcon, EyeOffIcon } from 'lucide-react'
import styles from 'styles/password-input.module.css'

export const RootProvider = () => {
  const passwordInput = usePasswordInput()

  return (
    <div className="stack">
      <output>password input is {passwordInput.visible ? 'visible' : 'hidden'}</output>
      <PasswordInput.RootProvider className={styles.Root} value={passwordInput}>
        <PasswordInput.Label className={styles.Label}>Password</PasswordInput.Label>
        <PasswordInput.Control className={styles.Control}>
          <PasswordInput.Input className={styles.Input} />
          <PasswordInput.VisibilityTrigger className={styles.VisibilityTrigger}>
            <PasswordInput.Indicator className={styles.Indicator} fallback={<EyeOffIcon />}>
              <EyeIcon />
            </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.

```tsx
import { Field } from '@ark-ui/react/field'
import { PasswordInput } from '@ark-ui/react/password-input'
import { EyeIcon, EyeOffIcon } from 'lucide-react'
import field from 'styles/field.module.css'
import styles from 'styles/password-input.module.css'

export const WithField = () => (
  <Field.Root className={field.Root}>
    <PasswordInput.Root className={styles.Root}>
      <PasswordInput.Label className={styles.Label}>Password</PasswordInput.Label>
      <PasswordInput.Control className={styles.Control}>
        <PasswordInput.Input className={styles.Input} />
        <PasswordInput.VisibilityTrigger className={styles.VisibilityTrigger}>
          <PasswordInput.Indicator className={styles.Indicator} fallback={<EyeOffIcon />}>
            <EyeIcon />
          </PasswordInput.Indicator>
        </PasswordInput.VisibilityTrigger>
      </PasswordInput.Control>
    </PasswordInput.Root>
    <Field.HelperText className={field.HelperText}>Enter your password</Field.HelperText>
    <Field.ErrorText className={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.**

```tsx
import { PasswordInput } from '@ark-ui/react/password-input'
import { EyeIcon, EyeOffIcon } from 'lucide-react'
import styles from 'styles/password-input.module.css'

export const IgnorePasswordManager = () => (
  <PasswordInput.Root className={styles.Root} ignorePasswordManagers>
    <PasswordInput.Label className={styles.Label}>API Key</PasswordInput.Label>
    <PasswordInput.Control className={styles.Control}>
      <PasswordInput.Input className={styles.Input} defaultValue="spd_1234567890" />
      <PasswordInput.VisibilityTrigger className={styles.VisibilityTrigger}>
        <PasswordInput.Indicator className={styles.Indicator} fallback={<EyeOffIcon />}>
          <EyeIcon />
        </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.

```tsx
import { PasswordInput } from '@ark-ui/react/password-input'
import { passwordStrength, type Options } from 'check-password-strength'
import { EyeIcon, EyeOffIcon } from 'lucide-react'
import { useMemo, useState } from 'react'
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 const StrengthMeter = () => {
  const [password, setPassword] = useState('asdfasdf')

  const strength = useMemo(() => {
    if (!password) return null
    const { value } = passwordStrength(password, strengthOptions)
    return value
  }, [password])

  return (
    <PasswordInput.Root className={styles.Root}>
      <PasswordInput.Label className={styles.Label}>Password</PasswordInput.Label>
      <PasswordInput.Control className={styles.Control}>
        <PasswordInput.Input
          className={styles.Input}
          value={password}
          onChange={(e) => setPassword(e.currentTarget.value)}
          placeholder="Enter your password"
        />
        <PasswordInput.VisibilityTrigger className={styles.VisibilityTrigger}>
          <PasswordInput.Indicator className={styles.Indicator} fallback={<EyeOffIcon />}>
            <EyeIcon />
          </PasswordInput.Indicator>
        </PasswordInput.VisibilityTrigger>
      </PasswordInput.Control>
      {strength && (
        <div className={styles.StrengthMeter}>
          <div className={styles.StrengthBar}>
            <div className={styles.StrengthFill} data-strength={strength} />
          </div>
          <div className={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.

```tsx
import { PasswordInput } from '@ark-ui/react/password-input'
import { EyeIcon, EyeOffIcon } from 'lucide-react'
import { useMemo, useState } from 'react'
import styles from 'styles/password-input.module.css'

export const WithValidation = () => {
  const [password, setPassword] = useState('')
  const isValid = useMemo(() => password.length >= 8, [password])

  return (
    <PasswordInput.Root className={styles.Root} invalid={!isValid && password.length > 0}>
      <PasswordInput.Label className={styles.Label}>Password (min 8 characters)</PasswordInput.Label>
      <PasswordInput.Control className={styles.Control}>
        <PasswordInput.Input
          className={styles.Input}
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="Enter your password"
        />
        <PasswordInput.VisibilityTrigger className={styles.VisibilityTrigger}>
          <PasswordInput.Indicator className={styles.Indicator} fallback={<EyeOffIcon />}>
            <EyeIcon />
          </PasswordInput.Indicator>
        </PasswordInput.VisibilityTrigger>
      </PasswordInput.Control>
      {password.length > 0 && !isValid && (
        <p className={styles.ValidationMessage} data-valid="false">
          Password must be at least 8 characters
        </p>
      )}
      {isValid && password.length > 0 && (
        <p className={styles.ValidationMessage} data-valid="true">
          Password is valid
        </p>
      )}
    </PasswordInput.Root>
  )
}
```

## API Reference

### Props

### Root

#### Props

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

**`autoComplete`**
Type: `'current-password' | 'new-password'`
Required: false
Default Value: `"current-password"`
Description: The autocomplete attribute for the password input.

**`defaultVisible`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: The default visibility of the password input.

**`disabled`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Whether the password input is disabled.

**`id`**
Type: `string`
Required: false
Default Value: `undefined`
Description: The unique identifier of the machine.

**`ids`**
Type: `Partial<{ input: string; visibilityTrigger: string }>`
Required: false
Default Value: `undefined`
Description: The ids of the password input parts

**`ignorePasswordManagers`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: When `true`, the input will ignore password managers.

**Only works for the following password managers**
- 1Password, LastPass, Bitwarden, Dashlane, Proton Pass

**`invalid`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: The invalid state of the password input.

**`name`**
Type: `string`
Required: false
Default Value: `undefined`
Description: The name of the password input.

**`onVisibilityChange`**
Type: `(details: VisibilityChangeDetails) => void`
Required: false
Default Value: `undefined`
Description: Function called when the visibility changes.

**`readOnly`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Whether the password input is read only.

**`required`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Whether the password input is required.

**`translations`**
Type: `Partial<{ visibilityTrigger: ((visible: boolean) => string) | undefined }>`
Required: false
Default Value: `undefined`
Description: The localized messages to use.

**`visible`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Whether the password input is visible.

#### Data Attributes

**`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

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

#### Data Attributes

**`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

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

**`fallback`**
Type: `string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<...>`
Required: false
Default Value: `undefined`
Description: The fallback content to display when the password is not visible.

#### Data Attributes

**`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

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

#### Data Attributes

**`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

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

#### Data Attributes

**`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

**`value`**
Type: `UsePasswordInputReturn`
Required: true
Default Value: `undefined`
Description: undefined

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

### VisibilityTrigger

#### Props

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

#### Data Attributes

**`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. |
