# Reset password

New password and confirmation fields that must match, for the screen a reset link opens.

[Documentation](https://eoria.adamtrip.pt/blocks/reset-password/)

[Registry source](https://eoria.adamtrip.pt/r/reset-password.json)

npm dependencies: @eoria/core, lucide-react-native, react-native-unistyles.

Registry dependencies: alert, button, field, keyboard, password-input, stack, text.

```sh
npx @eoria/cli add reset-password
```

The CLI also adds `alert`, `button`, `field`, `keyboard`, `password-input`, `stack` and `text`. The file lands at `components/blocks/reset-password.tsx` and is yours to edit.

The form scrolls inside `KeyboardScrollView`, so the app needs `KeyboardProvider` at its root. The [Keyboard page](https://eoria.adamtrip.pt/components/keyboard.md) has the setup.

## Usage

```tsx
// app/reset-password.tsx, opened by a link such as myapp://reset-password?token=abc
import { router, useLocalSearchParams } from 'expo-router'
import { ResetPassword } from '@/components/blocks/reset-password'
import { toast } from '@/components/ui/toast'
import { resetPassword } from '@/lib/auth'

export default function ResetPasswordRoute() {
  const { token } = useLocalSearchParams<{ token: string }>()
  return (
    <ResetPassword
      onSubmit={async (password) => {
        await resetPassword(token, password)
        toast({ title: 'Password changed' })
        router.replace('/sign-in')
      }}
      onBack={() => router.replace('/sign-in')}
    />
  )
}
```

The snippet uses `toast`, which is a separate item. Add it with `npx @eoria/cli add toast` or drop those two lines.

## Props

| Prop       | Type                                          | Notes                                                                                                                      |
| ---------- | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `onSubmit` | `(password: string) => void \| Promise<void>` | Gets the new password once both fields pass.                                                                               |
| `onBack`   | `() => void`                                  | Renders the "Back to sign in" link.                                                                                        |
| `insetTop` | `boolean`                                     | Pads the top by the safe area. Pass `insetTop={false}` when the screen sits under a navigation header. Defaults to `true`. |
| `style`    | `StyleProp<ViewStyle>`                        | Merged into the root, after the block's own styles.                                                                        |

## Notes

- The root fills the screen, paints `theme.colors.background` and pads the top and bottom by the safe area. Under a navigation header pass `insetTop={false}`, because the header already covers the top inset.
- The password needs 8 characters and the confirmation must equal it. Errors stay hidden until the first submit, then update as the user types.
- Both fields set `autoComplete="new-password"` and `textContentType="newPassword"`. Each has its own reveal toggle. The second toggle reads "Show confirmation" so a screen reader user can tell the two apart.
- The block has no success screen. Your `onSubmit` decides what comes next, and the usual choice is a toast and a `router.replace` to sign-in. An expired token should reject with a message such as "This link has expired. Ask for a new one." The block shows it in a destructive Alert above the form.
- When `onSubmit` returns a promise, the block sets `loading` on the button until the promise settles. The button shows a spinner, ignores presses and keeps its colours. The block skips state updates after it unmounts, so replacing the route inside `onSubmit` is safe.
- The return key on the first field moves focus to the confirmation. The return key on the confirmation submits.
- To use a form library, replace the two `useState` calls and the `Error` constants with the library's values and errors. Keep `Field`, `FieldControl` and `FieldError`.
- Change `MIN_PASSWORD` first if your backend has a different rule. The helper text and the error both read it.

## Source

[`registry/blocks/reset-password.tsx`](https://github.com/adamtrip-solutions/eoria/blob/main/registry/blocks/reset-password.tsx)
