SignIn.EmailForm
Complete email/password authentication interface combining all form elements with validation, error handling, and customization options. Provides compound components for building flexible sign-in forms with built-in authentication logic.
Prerequisites
Before using the Sign-In module, you must configure your ovokClient with a valid tenant code.
Obtaining Your Tenant Code
To get your organization's tenant code, use the Ovok API to receive organization codes via email:
curl -X POST https://api.ovok.com/organizations/code/email \
-H "Content-Type: application/json" \
-d '{"email": "your-email@example.com"}'
For detailed API documentation, refer to the Ovok API Reference.
Configuring Your Client
Once you receive your tenant code, update your ovokClient configuration in app/_layout.tsx:
const ovokClient = new OvokClient({
...
tenantCode: "your-tenant-code-here", // Replace with your actual tenant code
});
Quick Start Example
import { AuthResponse } from "@ovok/core";
import { SignIn, useAppTheme } from "@ovok/native";
import React from "react";
import { StyleSheet } from "react-native";
// Static styles outside component
const styles = StyleSheet.create({
form: {
flex: 1,
},
});
const LoginScreen = () => {
const theme = useAppTheme();
const handleSuccess = (response: AuthResponse) => {
console.log("Login successful:", response);
// Handle successful authentication
};
const handleError = (error: Error) => {
console.error("Login failed:", error);
// Handle authentication error
};
return (
<SignIn.EmailForm
loginType="Patient"
tenantCode="your-tenant-code"
onSuccess={handleSuccess}
onError={handleError}
style={[
styles.form,
{
padding: theme.spacing(12),
gap: theme.spacing(12),
},
]}
>
<SignIn.EmailForm.Inputs />
<SignIn.EmailForm.ForgotPassword />
<SignIn.EmailForm.Spacing percentage={3} />
<SignIn.EmailForm.SigninButton />
</SignIn.EmailForm>
);
};
export default LoginScreen;
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
loginType | "Patient" | "Practitioner" | ✓ | - | User type for authentication |
tenantCode | string | ✓* | - | Organization tenant code (required for Patient login) |
onSuccess | (response: AuthResponse) => void | - | undefined | Callback for successful authentication |
onError | (error: Error) => void | - | undefined | Callback for authentication errors |
onSubmit | (values, formikHelpers) => Promise<void> | - | undefined | Custom submit handler (overrides default auth logic) |
customValidations | { [key]: Yup.StringSchema | Function } | - | undefined | Custom validation rules for form fields |
style | StyleProp<ViewStyle> | - | undefined | Container style overrides |
testID | string | - | undefined | Test identifier for automation |
children | ReactNode | - | undefined | Child components (Inputs, Button, etc.) |
Note: tenantCode is required when loginType is "Patient" and optional when loginType is "Practitioner".
Note: Either use onSuccess/onError for default authentication or onSubmit for custom handling. Both approaches cannot be used together.
Child Components
- SignIn.EmailForm.Inputs - Email and password input fields with validation
- SignIn.EmailForm.SigninButton - Submit button with loading states and error display
- SignIn.EmailForm.ForgotPassword - Forgot password link component
- SignIn.EmailForm.Spacing - Layout spacing component for consistent vertical spacing
Localization
The SignIn.EmailForm component uses these translation keys that should be defined in your localization files:
{
"sign-in": {
"email": "Email",
"password": "Password",
"button": "Sign In",
"forgot-password": "Forgot password?",
"form": {
"email": {
"invalid": "Invalid email address",
"required": "Email is required"
},
"password": {
"required": "Password is required"
}
}
}
}
Translation Key Usage
sign-in.email- Email input field labelsign-in.password- Password input field labelsign-in.button- Submit button textsign-in.forgot-password- Forgot password link textsign-in.form.email.invalid- Email validation error messagesign-in.form.email.required- Required email field errorsign-in.form.password.required- Required password field error
Common Patterns
With Custom Validation
import { SignIn, useAppTheme } from "@ovok/native";
import React from "react";
import { StyleSheet } from "react-native";
import * as Yup from "yup";
// Static styles outside component
const styles = StyleSheet.create({
form: {
flex: 1,
},
});
const customValidations = {
email: (existingRule: Yup.StringSchema) =>
existingRule
.email("Invalid email address")
.matches(/@ovok\.com$/, "Email must be from ovok.com domain"),
};
export const CustomValidationLoginForm = () => {
const theme = useAppTheme();
return (
<SignIn.EmailForm
loginType="Practitioner"
customValidations={customValidations}
style={[
styles.form,
{
gap: theme.spacing(4),
},
]}
>
<SignIn.EmailForm.Inputs />
<SignIn.EmailForm.SigninButton />
</SignIn.EmailForm>
);
};
Related Components
- SignIn - Main sign-in component container
- SignIn.Header - Header components for titles and descriptions
- SignIn.SocialLogins - Social authentication components