# ChangePasswordForm

> Change-password form with current, new (strength meter) and confirm fields, an option to sign out other sessions, client checks, server field errors and a success message, driven by one async onSubmit.

Source: https://docs.nasaqui.com/components/change-password-form

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/change-password-form.json
```

The form for a signed-in person to change their password. It checks the obvious things on the client,
then calls your `onSubmit`. It does not talk to a server itself.

## When to use

- The security page of an account.

## When not to use

- Forgotten password: use the reset-password form; there is no current password to ask for.

## Import

```tsx
import { ChangePasswordForm } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"
```

## Quick start

```tsx
import { ChangePasswordForm } from "@fadymondy/nasaq/web";

declare const api: { changePassword(v: { currentPassword: string; newPassword: string; signOutOthers: boolean }): Promise<{ ok: boolean }> };

export function Password() {
  return (
    <ChangePasswordForm
      onSubmit={async (values) => {
        const res = await api.changePassword(values);
        if (!res.ok) return { fieldErrors: { currentPassword: "That is not your current password." } };
      }}
    />
  );
}
```

## Anatomy

```
ChangePasswordForm                 data-slot="change-password-form" (form, noValidate)
├─ Alert                           success or server error
├─ Field  current password         autocomplete="current-password"
├─ Field  new password             autocomplete="new-password", PasswordInput with strength meter
├─ Field  confirm                  autocomplete="new-password"
├─ Checkbox  sign out other sessions
└─ Button  Change password         loading while pending
```

## API

**ChangePasswordForm**: every `form` prop except `onSubmit` and `children`, plus:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `onSubmit` | `(values: { currentPassword, newPassword, signOutOthers }) => Promise<void \| { error?, fieldErrors? }>` | required | Called when the client checks pass. Resolve for success. Return `error` for a form-level message and `fieldErrors` (`currentPassword`, `newPassword`, `confirmPassword`) for field messages. A throw shows a generic error. |
| `minLength` | `number` | `8` | Minimum length of the new password. |
| `showSignOutOthers` | `boolean` | `true` | Show the checkbox. |
| `defaultSignOutOthers` | `boolean` | `true` | Its initial state. |
| `labels` | `Partial<ChangePasswordLabels>` | | Override any string. |

Client checks: every field is required, the new password meets `minLength` and differs from the current
one, and the confirmation matches. On success the fields are cleared and a success alert shows.

## Examples

**Without the sign-out option**

```tsx
import { ChangePasswordForm } from "@fadymondy/nasaq/web";

export function Simple({ save }: { save: (v: { newPassword: string }) => Promise<void> }) {
  return <ChangePasswordForm showSignOutOthers={false} onSubmit={(v) => save(v)} />;
}
```

## Accessibility

- Each field has a visible label, and errors are attached with `FieldError` and the invalid border, never colour alone.
- `autocomplete` is `current-password` for the first field and `new-password` for the other two, so password managers fill and save correctly.
- Each password field has the show/hide toggle from `PasswordInput`.
- The form has `noValidate`: messages come from the component, in the page language.
- The success and error alerts are announced (`status` and `alert`).

## RTL & i18n

- English and Arabic strings follow the Nasaq locale. Pass `labels` for other languages.
- The toggles sit at the inline end. Use `ltr` inside a custom field if you need the typed value pinned left-to-right.

## Styling & tokens

- `Field`, `PasswordInput`, `Alert` and `--nq-*` tokens. Target `[data-slot="change-password-form"]`.

## Do / Don't

- Do enforce the password policy on the server; the meter is only a hint.
- Do offer to sign out other sessions, and end them on the server when it is checked.
- Don't reveal whether an account exists in a field error.

## Related

- [`PasswordInput`](https://docs.nasaqui.com/components/password-input)
- [`Field`](https://docs.nasaqui.com/components/field)
- [`TwoFactorSetup`](https://docs.nasaqui.com/components/two-factor-setup)

## Lab

https://docs.nasaqui.com/?path=/docs/components-account-change-password-form--docs

## Code

### React

```tsx
import { ChangePasswordForm } from "@fadymondy/nasaq/web";

declare const api: { changePassword(v: { currentPassword: string; newPassword: string; signOutOthers: boolean }): Promise<{ ok: boolean }> };

export function Password() {
  return (
    <ChangePasswordForm
      onSubmit={async (values) => {
        const res = await api.changePassword(values);
        if (!res.ok) return { fieldErrors: { currentPassword: "That is not your current password." } };
      }}
    />
  );
}
```

### shadcn

```tsx
import { ChangePasswordForm } from "@/components/ui/change-password-form";

declare const api: { changePassword(v: { currentPassword: string; newPassword: string; signOutOthers: boolean }): Promise<{ ok: boolean }> };

export function Password() {
  return (
    <ChangePasswordForm
      onSubmit={async (values) => {
        const res = await api.changePassword(values);
        if (!res.ok) return { fieldErrors: { currentPassword: "That is not your current password." } };
      }}
    />
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { NqChangePasswordForm, type ChangePasswordValues } from "@fadymondy/nasaq/vue";

// Your API call. Return { fieldErrors: { currentPassword: "..." } } for a wrong current password.
async function change(values: ChangePasswordValues) {
  await new Promise((r) => setTimeout(r, 400));
  if (values.currentPassword !== "correct-horse") {
    return { fieldErrors: { currentPassword: "That is not your current password." } };
  }
}
</script>

<template>
  <NqChangePasswordForm :on-submit="change" />
</template>
```

### Blade

```blade
{{-- Your API call. Resolve { fieldErrors: { currentPassword: "…" } } for a wrong current password. --}}
<x-nq::change-password-form
    x-on:nq-change-password="$event.detail.waitUntil(new Promise((done) => setTimeout(() => done($event.detail.currentPassword === 'correct-horse' ? undefined : { fieldErrors: { currentPassword: 'That is not your current password.' } }), 300)))" />
```

### HTML + Alpine

```html
<form data-slot="change-password-form" novalidate x-data="nqChangePasswordForm(JSON.parse('{\u0022minLength\u0022:8,\u0022showSignOutOthers\u0022:true,\u0022labels\u0022:{\u0022current\u0022:\u0022Current password\u0022,\u0022next\u0022:\u0022New password\u0022,\u0022nextHint\u0022:\u0022At least 8 characters.\u0022,\u0022confirm\u0022:\u0022Confirm new password\u0022,\u0022signOutOthers\u0022:\u0022Sign out of all other sessions\u0022,\u0022signOutOthersHint\u0022:\u0022Recommended if you think someone else knows your old password.\u0022,\u0022submit\u0022:\u0022Change password\u0022,\u0022success\u0022:\u0022Your password was changed.\u0022,\u0022required\u0022:\u0022Enter this to continue.\u0022,\u0022tooShort\u0022:\u0022Use at least {n} characters.\u0022,\u0022mismatch\u0022:\u0022The passwords do not match.\u0022,\u0022same\u0022:\u0022Choose a password different from your current one.\u0022,\u0022genericError\u0022:\u0022Could not change your password. Try again.\u0022}}'))" x-on:submit.prevent="submit()"
    x-on:nq-change-password="$event.detail.waitUntil(new Promise((done) =&gt; setTimeout(() =&gt; done($event.detail.currentPassword === &#039;correct-horse&#039; ? undefined : { fieldErrors: { currentPassword: &#039;That is not your current password.&#039; } }), 300)))" class="flex w-full max-w-md flex-col gap-4">
    <div data-slot="alert" data-tone="success" role="status"
        x-show="done" style="display: none" class="relative grid grid-cols-[auto_1fr_auto] items-start gap-x-3 rounded-card border p-3 text-start border-nq-success/30 bg-nq-success-soft">
    <svg aria-hidden="true" data-slot="alert-icon" class="mt-0.5 size-4 text-nq-success-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"/>
  <path d="m9 12 2 2 4-4"/>
</svg>    <div data-slot="alert-body" class="flex min-w-0 flex-col gap-0.5">
                            <div data-slot="alert-description" class="text-body-sm text-foreground">Your password was changed.</div>
            </div>
    </div>
    <div data-slot="alert" data-tone="danger" role="alert"
        x-show="formError" style="display: none" class="relative grid grid-cols-[auto_1fr_auto] items-start gap-x-3 rounded-card border p-3 text-start border-nq-danger/30 bg-nq-danger-soft">
    <svg aria-hidden="true" data-slot="alert-icon" class="mt-0.5 size-4 text-nq-danger-text" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <circle cx="12" cy="12" r="10"/>
  <path d="m15 9-6 6"/>
  <path d="m9 9 6 6"/>
</svg>    <div data-slot="alert-body" class="flex min-w-0 flex-col gap-0.5">
                            <div data-slot="alert-description" class="text-body-sm text-foreground"><span x-text="formError"></span></div>
            </div>
    </div>
    <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     x-model="bad.currentPassword" class="flex flex-col gap-1.5">
    <label data-slot="field-label"  for="nq-cpw-6f2871-current" class="text-label text-foreground data-disabled:opacity-50">Current password</label>
        <div data-slot="password-input" x-data="nqPasswordInput('', JSON.parse('{\u0022visible\u0022:false,\u0022score\u0022:null,\u0022rules\u0022:null,\u0022levels\u0022:[\u0022Very weak\u0022,\u0022Weak\u0022,\u0022Fair\u0022,\u0022Good\u0022,\u0022Strong\u0022]}'))" x-modelable="value"
    class="flex w-full flex-col gap-2">
    <div role="group" data-slot="input-group"
    class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><input data-slot="input-group-input"     x-model="value" x-bind:type="shown ? &#039;text&#039; : &#039;password&#039;" type="password" value="" autocapitalize="none" autocorrect="off" spellcheck="false" id="nq-cpw-6f2871-current" name="currentPassword" autocomplete="current-password" required="required" aria-describedby="nq-cpw-6f2871-current-error" x-bind:disabled="pending" x-bind:aria-invalid="bad.currentPassword ? &#039;true&#039; : null" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px]" />
        <div data-slot="input-group-addon" data-align="end"
    class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&_svg]:size-4 order-last ps-1 pe-1.5"><button data-slot="password-input-toggle"
     type="button"                         x-bind="toggle" aria-label="Show password" aria-pressed="false" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg x-show="shown" x-cloak="1" style="display: none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"/>
  <path d="M14.084 14.158a3 3 0 0 1-4.242-4.242"/>
  <path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"/>
  <path d="m2 2 20 20"/>
</svg>                <svg x-show="!shown" x-cloak="1" style="" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/>
  <circle cx="12" cy="12" r="3"/>
</svg></button></div></div>
        </div>
        <div data-slot="field-error" role="alert" x-show="invalid"  style="display: none"  id="nq-cpw-6f2871-current-error" class="text-caption text-nq-danger-text"><span x-text="errors.currentPassword"></span></div>
</div>
    <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     x-model="bad.newPassword" class="flex flex-col gap-1.5">
    <label data-slot="field-label"  for="nq-cpw-6f2871-next" class="text-label text-foreground data-disabled:opacity-50">New password</label>
        <div data-slot="password-input" x-data="nqPasswordInput('', JSON.parse('{\u0022visible\u0022:false,\u0022score\u0022:null,\u0022rules\u0022:null,\u0022levels\u0022:[\u0022Very weak\u0022,\u0022Weak\u0022,\u0022Fair\u0022,\u0022Good\u0022,\u0022Strong\u0022]}'))" x-modelable="value"
    class="flex w-full flex-col gap-2">
    <div role="group" data-slot="input-group"
    class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><input data-slot="input-group-input"     x-model="value" x-bind:type="shown ? &#039;text&#039; : &#039;password&#039;" type="password" value="" autocapitalize="none" autocorrect="off" spellcheck="false" id="nq-cpw-6f2871-next" name="newPassword" autocomplete="new-password" minlength="8" required="required" aria-describedby="nq-cpw-6f2871-next-hint nq-cpw-6f2871-next-error" x-bind:disabled="pending" x-bind:aria-invalid="bad.newPassword ? &#039;true&#039; : null" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px]" />
        <div data-slot="input-group-addon" data-align="end"
    class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&_svg]:size-4 order-last ps-1 pe-1.5"><button data-slot="password-input-toggle"
     type="button"                         x-bind="toggle" aria-label="Show password" aria-pressed="false" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg x-show="shown" x-cloak="1" style="display: none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"/>
  <path d="M14.084 14.158a3 3 0 0 1-4.242-4.242"/>
  <path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"/>
  <path d="m2 2 20 20"/>
</svg>                <svg x-show="!shown" x-cloak="1" style="" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/>
  <circle cx="12" cy="12" r="3"/>
</svg></button></div></div>
            <div data-slot="password-input-strength" data-score="0" class="flex flex-col gap-1 opacity-60" x-bind="strengthBox">
            <div data-slot="meter" role="meter" aria-label="Password strength" aria-valuemin="0" aria-valuemax="4" aria-valuenow="0"
                data-tone="danger" x-bind="meter" class="flex w-full flex-col gap-1.5">
                <div data-slot="meter-track" class="relative block h-1 w-full overflow-hidden rounded-full bg-nq-surface-soft">
                    <div data-slot="meter-indicator" style="inset-inline-start:0;width:0%" x-bind="meterFill"
                        class="block h-full rounded-full transition-[width] duration-300 ease-nq motion-reduce:transition-none bg-nq-danger"></div>
                </div>
            </div>
            <div class="flex items-baseline justify-between gap-3 text-caption text-muted-foreground">
                <span>Password strength</span>
                <span aria-live="polite" class="text-foreground" x-text="levelText()"></span>
            </div>
        </div>
        </div>
        <div data-slot="field-error" role="alert" x-show="invalid"  style="display: none"  id="nq-cpw-6f2871-next-error" class="text-caption text-nq-danger-text"><span x-text="errors.newPassword"></span></div>
        <p data-slot="field-description" id="nq-cpw-6f2871-next-hint" x-show="! bad.newPassword" class="text-caption text-muted-foreground">At least 8 characters.</p>
</div>
    <div data-slot="field" x-data="nqField(false)" x-modelable="invalid" x-id="['nq-field']"
         data-valid     x-model="bad.confirmPassword" class="flex flex-col gap-1.5">
    <label data-slot="field-label"  for="nq-cpw-6f2871-confirm" class="text-label text-foreground data-disabled:opacity-50">Confirm new password</label>
        <div data-slot="password-input" x-data="nqPasswordInput('', JSON.parse('{\u0022visible\u0022:false,\u0022score\u0022:null,\u0022rules\u0022:null,\u0022levels\u0022:[\u0022Very weak\u0022,\u0022Weak\u0022,\u0022Fair\u0022,\u0022Good\u0022,\u0022Strong\u0022]}'))" x-modelable="value"
    class="flex w-full flex-col gap-2">
    <div role="group" data-slot="input-group"
    class="group/input-group flex h-control min-h-[var(--nq-touch-min,0px)] w-full min-w-0 items-center overflow-hidden rounded-control border border-input bg-card text-body text-foreground transition-colors duration-150 ease-nq focus-within:border-nq-focus focus-within:outline-1 focus-within:outline-nq-focus has-[[data-invalid]]:border-nq-danger has-[[aria-invalid=true]]:border-nq-danger has-[input:disabled]:cursor-not-allowed has-[input:disabled]:opacity-50"><input data-slot="input-group-input"     x-model="value" x-bind:type="shown ? &#039;text&#039; : &#039;password&#039;" type="password" value="" autocapitalize="none" autocorrect="off" spellcheck="false" id="nq-cpw-6f2871-confirm" name="confirmPassword" autocomplete="new-password" required="required" aria-describedby="nq-cpw-6f2871-confirm-error" x-bind:disabled="pending" x-bind:aria-invalid="bad.confirmPassword ? &#039;true&#039; : null" class="h-full min-w-0 flex-1 border-0 bg-transparent px-3 text-body text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed pointer-coarse:text-[16px]" />
        <div data-slot="input-group-addon" data-align="end"
    class="flex h-full shrink-0 items-center gap-1.5 text-body-sm text-muted-foreground [&_svg]:size-4 order-last ps-1 pe-1.5"><button data-slot="password-input-toggle"
     type="button"                         x-bind="toggle" aria-label="Show password" aria-pressed="false" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-foreground hover:bg-nq-hover size-control-sm p-0">
        <svg x-show="shown" x-cloak="1" style="display: none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"/>
  <path d="M14.084 14.158a3 3 0 0 1-4.242-4.242"/>
  <path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"/>
  <path d="m2 2 20 20"/>
</svg>                <svg x-show="!shown" x-cloak="1" style="" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/>
  <circle cx="12" cy="12" r="3"/>
</svg></button></div></div>
        </div>
        <div data-slot="field-error" role="alert" x-show="invalid"  style="display: none"  id="nq-cpw-6f2871-confirm-error" class="text-caption text-nq-danger-text"><span x-text="errors.confirmPassword"></span></div>
</div>
            <div class="flex items-start gap-2">
            <button type="button" role="checkbox" data-slot="checkbox" x-data="nqCheckbox(true, false)" x-modelable="checked" x-bind="root"
    aria-checked="true"
     data-checked                 id="nq-cpw-6f2871-check" x-model="signOutOthers" x-bind:disabled="pending" x-bind:data-disabled="pending ? &#039;&#039; : null" class="relative inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-nq-line-strong bg-card text-primary-foreground outline-none transition-colors duration-150 ease-nq data-checked:border-primary data-checked:bg-primary data-indeterminate:border-primary data-indeterminate:bg-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus data-disabled:cursor-not-allowed data-disabled:opacity-50 after:absolute after:-inset-1 mt-0.5">
    <span data-slot="checkbox-indicator" class="flex items-center justify-center [&_svg]:size-3 [&_svg]:stroke-3" x-show="checked || indeterminate" >
        <svg aria-hidden="true" x-show="indeterminate" style="display: none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M5 12h14"/>
</svg>        <svg aria-hidden="true" x-show="! indeterminate" style="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M20 6 9 17l-5-5"/>
</svg>    </span>
    <input type="hidden" name="signOutOthers" value="1" x-bind:disabled="! checked" ></button>
            <div class="flex flex-col gap-0.5">
                <label for="nq-cpw-6f2871-check" class="text-body-sm text-foreground">Sign out of all other sessions</label>
                <p class="text-caption text-muted-foreground">Recommended if you think someone else knows your old password.</p>
            </div>
        </div>
        <div>
        <button data-slot="button"
     type="submit"                         x-bind:disabled="pending" x-bind:data-disabled="pending ? &#039;&#039; : null" x-bind:aria-busy="pending ? &#039;true&#039; : null" class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border border-transparent font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--nq-action)_88%,var(--nq-fg))] h-control px-[var(--nq-control-pad)]">
        <template x-if="pending"><svg data-slot="spinner" aria-hidden="true" class="size-4 animate-spin motion-reduce:animate-none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg></template>
            Change password</button>
    </div>
</form>
```
