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

Last updated

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.

  • At least 8 characters, not met
  • One special character, not met
Show code
<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

npx @ava-ui/apogee add password-checklist

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

Usage

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

  • At least 8 characters, not met
  • One number, not met
  • At least 8 characters, not met
  • One number, not met
Show code
<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.

  • At least 8 characters, not met
  • One special character, not met
Show code
<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.

  • At least 8 characters, not met
  • One special character, not met
  • Passwords match, not met
Show code
<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”.