eoria
Block

Reset password

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

Reset password rendered on iOS, light mode
Reset password rendered on iOS, dark mode
iPhone, zinc preset. Captured from the example app.
Terminal window
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 has the setup.

Usage

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