AuthForm
A complete, controlled authentication form. Two modes share the same layout: login shows email + password + optional forgot-password link; signup adds a confirmPassword field and hides the forgot link. AuthForm never validates internally — validation belongs in the Screen that owns the data.
When to use: Login screens, signup screens, password reset flows.
When not to use: General-purpose forms — build them with FormField + Button. Forms with custom field arrangements — compose FormField manually.
Import
Section titled “Import”import { AuthForm } from '@/components';<AuthForm mode="login" email={email} onChangeEmail={setEmail} password={password} onChangePassword={setPassword} emailError={errors.email} passwordError={errors.password} isLoading={isSubmitting} onSubmit={handleLogin} onForgotPassword={() => router.push('/forgot-password')} footerText="Don't have an account?" footerActionLabel="Sign up" onFooterAction={() => router.push('/signup')}/>| Prop | Type | Default | Description |
|---|---|---|---|
mode | 'login' | 'signup' | 'login' | Which fields and labels to show |
email | string | — | Email field value (required) |
onChangeEmail | (v: string) => void | — | Email change handler (required) |
password | string | — | Password field value (required) |
onChangePassword | (v: string) => void | — | Password change handler (required) |
confirmPassword | string | — | Confirm password value (signup mode) |
onChangeConfirmPassword | (v: string) => void | — | Confirm change handler (signup mode) |
emailError | string | — | Error shown under email field |
passwordError | string | — | Error shown under password field |
confirmPasswordError | string | — | Error shown under confirm field |
isLoading | boolean | false | Shows spinner on submit button |
onSubmit | () => void | — | Submit handler (required) |
onForgotPassword | () => void | — | Forgot password link handler |
socialActions | AuthFormSocialAction[] | [] | OAuth provider buttons |
footerText | string | — | Footer line (“Don’t have an account?”) |
footerActionLabel | string | — | Footer CTA (“Sign up”) |
onFooterAction | () => void | — | Footer CTA handler |
testID | string | — |
socialActions item shape
Section titled “socialActions item shape”interface AuthFormSocialAction { label: string; onPress: () => void;}Login screen pattern
Section titled “Login screen pattern”export function LoginScreen() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [errors, setErrors] = useState({ email: '', password: '' }); const [isLoading, setIsLoading] = useState(false);
async function handleSubmit() { const errs = { email: '', password: '' }; if (!email.includes('@')) errs.email = 'Enter a valid email address'; if (password.length < 8) errs.password = 'Must be at least 8 characters'; setErrors(errs); if (errs.email || errs.password) return;
setIsLoading(true); try { await login(email, password); router.replace('/home'); } catch (e) { setErrors({ email: '', password: 'Incorrect email or password' }); } finally { setIsLoading(false); } }
return ( <AuthLayout title="Welcome back" subtitle="Log in to continue"> <AuthForm mode="login" email={email} onChangeEmail={setEmail} password={password} onChangePassword={setPassword} emailError={errors.email} passwordError={errors.password} isLoading={isLoading} onSubmit={handleSubmit} onForgotPassword={() => router.push('/forgot-password')} footerText="New here?" footerActionLabel="Create account" onFooterAction={() => router.push('/signup')} /> </AuthLayout> );}Do / Don’t
Section titled “Do / Don’t”Do: Keep validation in the Screen. Pass errors back as props.
Don’t: Add validation logic inside AuthForm — it’s a controlled, display-only organism.
Don’t: Use AuthForm for non-auth forms. Build them from FormField + Button.
Related
Section titled “Related”AuthLayout— layout shell for auth screensFormField— building block used inside AuthForm