# PasswordChecklist

> The rules a new password must meet, ticked off as the user types.

URL: https://apogee.avaui.dev/docs/password-checklist
Last updated: 2026-10-15

The rules a new password must meet, ticked off as the user types.

Last updated October 15, 2026

Uses JavaScript

Marks each rule met or not as the user types, adds the list to the field’s description, and keeps the field invalid until every rule holds, so the form will not submit early. A `match` rule re-checks when the other field changes.

**Without JS:** The rules show as a plain list, so the user still reads them before typing. Put the hard limits on the input itself (\`minlength\`, \`pattern\`) so the browser enforces them on submit.

```astro
<Input id="new-password" label="Password" type="password" />
<PasswordChecklist for="new-password" rules={[
{ label: 'At least 8 characters', minLength: 8 },
{ label: 'One special character', pattern: '[^A-Za-z0-9]' },
]} />
```

## Add

```sh
npx @ava-ui/apogee add password-checklist
```

Uses `@lucide/astro` for the circle and check icons. Ships one small JS island.

## Usage

```astro
---
import Input from '@/components/apogee/Input/Input.astro'
import PasswordChecklist from '@/components/apogee/PasswordChecklist/PasswordChecklist.astro'
---
<Input id="password" name="password" label="Password" type="password" minlength="8" autocomplete="new-password" />
<PasswordChecklist for="password" rules={[{ label: 'At least 8 characters', minLength: 8 }]} />
```

## API

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `for` | `string` | — | Id of the password input the rules apply to. |
| `rules` | `{ label, minLength?, pattern?, match? }[]` | — | A rule is met when every check it has passes: `minLength` characters, the `pattern` regular expression finds a match, the value equals the input with id `match`. |
| `size` | `'small' \| 'medium'` | `'medium'` | Text and icon size. |
| `id` | `string` | generated | The list’s id; the input’s `aria-describedby` points at it. |

## Variants

```astro
<PasswordChecklist size="small" for="…" rules={…} />
<PasswordChecklist size="medium" for="…" rules={…} />
```

## States

A rule shows a hollow circle until it is met, then a check and full-strength text. Type in the field to see both.

```astro
<Input id="pw" label="Password" type="password" value="longenough" />
<PasswordChecklist for="pw" rules={[{ label: 'At least 8 characters', minLength: 8 }, { label: 'One special character', pattern: '[^A-Za-z0-9]' }]} />
```

## Examples

A new password and its confirmation. The confirm field stays invalid until it matches, and re-checks if the password changes.

```astro
<form>
<Input id="password" label="Password" type="password" autocomplete="new-password" />
<PasswordChecklist for="password" rules={[
  { label: 'At least 8 characters', minLength: 8 },
  { label: 'One special character', pattern: '[^A-Za-z0-9]' },
]} />
<Input id="password-confirm" label="Confirm password" type="password" autocomplete="new-password" />
<PasswordChecklist for="password-confirm" rules={[{ label: 'Passwords match', match: 'password' }]} />
<Button type="submit">Continue</Button>
</form>
```

## Accessibility

-   The input’s `aria-describedby` gains the list, so screen readers read the rules with the field.
-   Each rule carries hidden text, “met” or “not met”, that changes as the user types. There is no live region: the state is read when the user asks for the description, not announced on every key.
-   An unmet rule sets the field’s validity message to that rule’s label, so the browser blocks submit and names what is missing.
-   Met and unmet differ in icon shape (circle, check), not only colour.

## Tokens

| Token | Used for |
| --- | --- |
| `--foreground-neutral-faded` | Unmet rules |
| `--foreground-neutral` | Met rules |
| `--foreground-positive` | The check icon |

## Do / Don’t

-   **Do** keep the hard limits on the input (`minlength`, `pattern`) as well, so they hold without JS.
-   **Don’t** list more than four rules. Long password rules push users to weaker, predictable passwords.

## Content

-   Write each rule as the condition to meet: “At least 8 characters”, “One number”. Not “Password too short”.
-   Keep the confirm rule to “Passwords match”.

## Related

[

InputA labeled text field with hint/error messaging, wired for accessibility — plus a pure-CSS floating label.

](https://apogee.avaui.dev/docs/input)[

FieldThe labeled-field scaffold — label, control, and hint/error — wired for accessibility.

](https://apogee.avaui.dev/docs/field)[

ProgressIndicatorStep N of M as a row of segments, for onboarding flows, wizards and carousels. Zero JS.

](https://apogee.avaui.dev/docs/progress-indicator)
