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 dialog-styled change-password card with a title, close button and current/new fields.
<div class="relative w-full max-w-md">
<div class="absolute inset-0 rounded-2xl bg-black/40" aria-hidden="true"></div>
<!-- role=dialog + aria-modal + aria-labelledby is the contract; wire focus-trap and Escape in JS. -->
<div role="dialog" aria-modal="true" aria-labelledby="cp-title"
class="relative rounded-2xl border border-gray-200 bg-white p-6 shadow-xl dark:border-gray-800 dark:bg-gray-950">
<div class="flex items-start justify-between gap-4">
<div>
<h2 id="cp-title" class="text-lg font-semibold text-gray-900 dark:text-gray-100">Change password</h2>
<p class="mt-1 text-sm text-gray-500 dark:text-gray-400">Enter your current password to confirm.</p>
</div>
<button type="button" aria-label="Close"
class="-m-1 rounded-lg p-1 text-gray-400 hover:text-gray-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:hover:text-gray-200">
<svg viewBox="0 0 20 20" class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path d="m5 5 10 10M15 5 5 15" stroke-linecap="round" />
</svg>
</button>
</div>
<form class="mt-5 space-y-4" novalidate>
<div>
<label for="cp-current" class="block text-sm font-medium text-gray-700 dark:text-gray-300">Current password</label>
<input id="cp-current" name="currentPassword" type="password" autocomplete="current-password"
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>
<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"
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>
<div class="flex flex-col-reverse gap-2 pt-1 sm:flex-row sm:justify-end">
<button type="button"
class="inline-flex items-center justify-center rounded-lg border border-gray-300 bg-white px-4 py-2.5 text-sm font-semibold text-gray-700 hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 dark:border-gray-700 dark:bg-transparent dark:text-gray-200 dark:hover:bg-gray-800">
Cancel
</button>
<button type="submit"
class="inline-flex 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 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950">
Update password
</button>
</div>
</form>
</div>
</div>| Prop | Type | Default | Description |
|---|---|---|---|
onSubmit | (values: { currentPassword: string; newPassword: string }) => void | - | Called with the form's values when it is submitted. |
onClose | () => void | - | Called when the component asks to close: Escape, the backdrop, or the close control. |
className | string | - | Additional classes merged onto the root element. |
The shell wires `role="dialog"`, `aria-modal` and `aria-labelledby`; the focus-trap, Escape-to-close and body-scroll-lock are host concerns and belong at the call site. The action row stacks on phones and the close button is a labelled icon target.