Sign up screen

ProReact Native · Expo

A 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.

View as Markdown
Try it on your phone
Scan to open this demo in your phone's browser and use it with your fingers.

Installation

$ npx shadcn@latest add @goodui-native-pro/sign-up-screen

Then 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

Use it for
  • 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.
Reach for something else
  • 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

PropTypeDefault
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 | 43
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.