Sign up screen
ProReact Native · ExpoA complete sign-up screen: name, email and a password with a live strength meter whose segments fill and recolor while each rule's check draws itself in, a terms checkbox and an async Create account button.
Installation
$ npx shadcn@latest add @goodui-native-pro/sign-up-screenThen run npx expo install --fix so react-native-reanimated, react-native-svg match your Expo SDK. Files land in components/goodui-native/sign-up-screen.
Pro screens install from the license-gated @goodui-native-pro registry. Setup: Pro access.
Usage
// app/(auth)/sign-up.tsx
import { router } from "expo-router";
import { SignUpScreen } from "@/components/goodui-native/sign-up-screen/sign-up-screen";
import { auth } from "@/lib/auth";
export default function SignUpRoute() {
return (
<SignUpScreen
appName="Stride"
onCreateAccount={async ({ name, email, password }) => {
const result = await auth.signUp({ name, email, password });
if (result.error === "email_taken") {
throw { field: "email", message: "An account with this email already exists." };
}
}}
onCreated={({ email }) => router.replace({ pathname: "/verify", params: { email } })}
onOpenTerms={() => router.push("/legal/terms")}
onOpenPrivacy={() => router.push("/legal/privacy")}
onSignIn={() => router.replace("/sign-in")}
onBack={router.back}
/>
);
}When to use
- The create-account route of an app with email and password accounts.
- When you want password rules shown live and server errors (email taken) placed under the right field.
- Returning people: use sign-in-screen.
- Apple or Google only sign-up: those buttons live on sign-in-screen.
- Long multi-step profiles: keep this screen to the account and ask for the rest later.
Examples
Accept fair passwords
<SignUpScreen minStrength={2} onCreateAccount={createAccount} onCreated={next} />Use the same strength rules elsewhere
import { passwordStrength } from "@/components/goodui-native/sign-up-screen/sign-up-screen";
const ok = passwordStrength(newPassword) >= 3;API reference
| Prop | Type | Default |
|---|---|---|
| appName Product name used in the copy ("Join Stride"). | string | "Stride" |
| title Headline. Defaults to "Create your account". | string | "Create your account" |
| subtitle One line under the headline. | string | — |
| onCreateAccount Runs when Create account is pressed and every field passes. Return a promise: the button shows pending, then a check; reject with `{ field: "email", message: "An account with this email already exists." }` to put the message under that field, or with an `Error` to show its message in a banner above the button. | (details: SignUpDetails) => unknown | — |
| onCreated Called about 700 ms after `onCreateAccount` resolves, once the check has landed. Go to verification here. | (details: SignUpDetails) => void | — |
| minStrength The lowest strength Create account accepts. Default 3 (good: 8+ characters and two of case, number, symbol). | 0 | 1 | 2 | 3 | 4 | 3 |
| onOpenTerms Opens the terms of service. Shows a link under the checkbox when set. | () => void | — |
| onOpenPrivacy Opens the privacy policy. Shows a link under the checkbox when set. | () => void | — |
| onSignIn "Sign in" link in the footer. Hidden when omitted. | () => void | — |
| onBack Shows a back button in the top bar. | () => void | — |
| style Style for the outer container. | StyleProp<ViewStyle> | — |
| testID Identifier for end-to-end tests. | string | — |
Motion and haptics
- The four strength segments fill from the leading edge on the smooth spring and recolor from danger through warning to success as the level changes.
- Each rule's check draws itself in the moment the rule is met.
- Create account gathers into a spinner, then opens into 'Account created' or shakes with 'Try again'; a field error shakes that field.
- Reduced motion: segments change with a short fade, checks appear complete, no shakes.
- Haptic: tap, success and error from the Create account button.
- Haptic: error from a field that fails validation; a rejected request buzzes once from the button only.
- Strength is computed from the password on each keystroke (four regex tests); the meter animates on the UI thread.
Accessibility
- The headline is a header; each field has its label and announces its own errors.
- The strength level is a polite live region ('Weak', 'Fair', 'Good', 'Strong'); each rule reads as one element, for example '8 or more characters, done'. The bar itself is hidden from screen readers.
- The terms checkbox is a real checkbox; skipping it marks it invalid, shows the reason under it and announces it.
- A form-level error appears in a danger banner that is announced; field errors appear under the field.
Notes for AI
- Return the request promise from onCreateAccount. Reject with { field: 'name' | 'email' | 'password', message } for a field error, or an Error for a banner message.
- Navigate in onCreated (usually to verify-screen), not inside onCreateAccount, so the check is visible first.
- minStrength defaults to 3 (good). passwordStrength(password) is exported and returns 0 to 4 with the same rules.
- Terms and privacy links render only when onOpenTerms and onOpenPrivacy are passed; the back button only with onBack.
- Render it as the whole route with the header hidden; it handles safe areas and the keyboard itself.
Related
A complete sign-in screen: email and password, forgot password, an async Sign in button that gathers into a spinner and opens into a check, or shakes together with the password field when the credentials are rejected, and Continue with Apple or Google.
A complete email or SMS code verification screen: OTP cells that shake and clear on a wrong code, a resend button behind a rolling countdown, and a success check that springs in once the code is accepted.
A text field whose label glides up as you focus it, with helper and error text that slide in, a shake and haptic on error, clear and reveal buttons, a character counter and a multiline mode that grows with its text.
Checkboxes whose check draws itself in (an indeterminate dash retracts into it) and radios whose dot pops into the center, inline or as list rows, with CheckboxGroup and RadioGroup helpers.
An inline status banner that slides down from under the edge above and pushes the content down, flings away sideways with the finger, and can collapse on its own behind a draining hairline; includes an offline preset.