Skip to content

SignUpForm

Terminal window
npx stylesheet-ui add sign-up-form otp-input

Sign-up is usually two steps: create the account, then verify the emailed code with OtpInput.

import { useState } from "react";
import { SignUpForm } from "@/components/ui/sign-up-form";
import { OtpInput } from "@/components/ui/otp-input";
export default function SignUpScreen() {
const [pending, setPending] = useState(false);
const [code, setCode] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string>();
const onSubmit = async ({ emailAddress, password }) => {
setLoading(true);
try {
await createAccount(emailAddress, password); // your auth provider
await sendVerificationCode(); // your auth provider
setPending(true);
} catch (e) {
setError("Couldn't sign up.");
} finally {
setLoading(false);
}
};
const verify = async (value: string) => {
await confirmVerificationCode(value); // your auth provider
};
if (pending) return <OtpInput value={code} onChange={setCode} onComplete={verify} error={error} autoFocus />;
return <SignUpForm onSubmit={onSubmit} loading={loading} error={error} />;
}

By default the form collects email + password. Opt-in props add more, and each value reaches onSubmit only when its prop is set:

  • nameFields — First/Last name inputs, side by side → firstName, lastName.
  • usernameField — a username input → username.
  • phoneField — a phone input with a phone-pad keyboard → phoneNumber.
  • requireConfirm — a confirm-password field; blocks submit until it matches.
  • requireTerms — a terms-acceptance checkbox that gates submit → acceptedTerms.
<SignUpForm
nameFields
usernameField
phoneField
requireConfirm
requireTerms
onSubmit={(values) => {
// values: emailAddress, password, firstName, lastName,
// username, phoneNumber, acceptedTerms
}}
/>

With requireTerms, the checkbox label reads “I agree to the Terms of Service and Privacy Policy”, with both names as tappable links. Choose how they open:

  • termsUrl / privacyUrl — open the page in an in-app browser via expo-web-browser. add sign-up-form prompts you to install it.
  • onTermsPress / onPrivacyPress — handle the tap yourself, e.g. navigate to an in-app route. A handler takes precedence over its URL.
  • termsLabel — replace the whole label with your own node (then termsUrl/onTermsPress are ignored).
<SignUpForm
requireTerms
termsUrl="https://yourapp.com/terms"
privacyUrl="https://yourapp.com/privacy"
onSubmit={(values) => createAccount(values)}
/>

Need a field that isn’t built in? The form is yours — add inputs and include them in the onSubmit payload.