Basic Change Password
A three-field change-password form - current, new and confirm - with a show/hide toggle and live mismatch feedback.
3 frameworksBeginner
A new-password field over a live checklist of rules that tick green as each is satisfied.
<form class="w-full max-w-sm space-y-4" novalidate>
<h2 class="text-base font-semibold text-gray-900 dark:text-gray-100">Choose a new password</h2>
<div>
<label for="cp-new" class="block text-sm font-medium text-gray-700 dark:text-gray-300">New password</label>
<input id="cp-new" name="newPassword" type="password" autocomplete="new-password" aria-describedby="cp-rules"
class="mt-1.5 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:focus-visible:ring-blue-400" />
</div>
<!-- The list is the live region: as rules pass it re-announces politely, so the check state reaches a screen reader. -->
<ul id="cp-rules" aria-live="polite" class="space-y-1.5">
<li class="flex items-center gap-2 text-xs">
<span aria-hidden="true" class="flex h-4 w-4 items-center justify-center rounded-full bg-green-500 text-white">✓</span>
<span class="text-gray-700 dark:text-gray-300">At least 8 characters</span>
<span class="sr-only">met</span>
</li>
<li class="flex items-center gap-2 text-xs">
<span aria-hidden="true" class="flex h-4 w-4 items-center justify-center rounded-full bg-gray-200 text-transparent dark:bg-gray-700">✓</span>
<span class="text-gray-500 dark:text-gray-400">One uppercase letter</span>
<span class="sr-only">not met</span>
</li>
<li class="flex items-center gap-2 text-xs">
<span aria-hidden="true" class="flex h-4 w-4 items-center justify-center rounded-full bg-gray-200 text-transparent dark:bg-gray-700">✓</span>
<span class="text-gray-500 dark:text-gray-400">One number</span>
<span class="sr-only">not met</span>
</li>
<li class="flex items-center gap-2 text-xs">
<span aria-hidden="true" class="flex h-4 w-4 items-center justify-center rounded-full bg-gray-200 text-transparent dark:bg-gray-700">✓</span>
<span class="text-gray-500 dark:text-gray-400">One symbol</span>
<span class="sr-only">not met</span>
</li>
</ul>
<button type="submit" disabled
class="inline-flex w-full items-center justify-center rounded-lg bg-blue-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-blue-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white disabled:cursor-not-allowed disabled:opacity-50 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950">
Update password
</button>
</form>| Prop | Type | Default | Description |
|---|---|---|---|
onSubmit | (values: { newPassword: string }) => void | - | Called with the form's values when it is submitted. |
className | string | - | Additional classes merged onto the root element. |
The rules list is the `aria-live` region: as each check passes it re-announces politely, and every row carries an `sr-only` "met"/"not met" so the state is never colour-only. The submit button stays disabled until all rules pass. Edit the `rules` array to match your policy.