SimpleAuth
ReactComponents

SignUpModal

Self-contained sign-up modal component with close handling and built-in registration submission.

Overview

SignUpModal mirrors SignInModal but uses useSignUp for registration and can show an email verification step inside the modal instead of closing immediately. The footer always prompts existing users to sign in (signInHref / onSwitchToSignIn).

Preview

Interactive preview requires JavaScript.

Install

npx @simpleauthjs/react add modal --style minimal

The install snippet uses --style minimal. You can also use --style modern. Style variants compares those two in the live preview. Run npx @simpleauthjs/react add --help for every --style slug the CLI accepts.

Running add modal automatically scaffolds the Google and GitHub auth files when they are missing (same as running add google-auth and add github-auth).

Props

NameTypeRequiredDefaultDescription
openbooleanYesControls visibility.
onClose() => voidYesCalled when the modal should close (backdrop click, close button, or success without pending verification).
onSuccess(result: { user: ExternalUser; needsVerification: boolean }) => voidNoundefinedFires after a successful sign-up.
appNamestringNoundefinedShown in the header next to the SimpleAuth badge. When set, the title becomes Create your {appName} account.
autoSendVerificationbooleanNotrueWhen verification is required, sends the verification email automatically unless set to false.
signInHrefstringNoundefinedFooter “Sign in” link when onSwitchToSignIn is not set.
onSwitchToSignIn() => voidNoundefinedFooter button for sign-in; takes precedence over signInHref.
googleRedirectUrlstringNoundefinedWhen set, renders Continue with Google below the email form.
githubRedirectUrlstringNoundefinedWhen set, renders Continue with GitHub below the email form.

Usage

"use client"

import { useState } from "react"
import { SignUpModal } from "@/components/simpleauth"

export function MarketingHeader() {
  const [open, setOpen] = useState(false)

  return (
    <>
      <button type="button" onClick={() => setOpen(true)}>
        Create account
      </button>
      <SignUpModal
        open={open}
        onClose={() => setOpen(false)}
        appName="Acme"
        googleRedirectUrl="https://myapp.com/dashboard"
        githubRedirectUrl="https://myapp.com/dashboard"
      />
    </>
  )
}

Remove the OAuth buttons

The quickest way to ship email-only modals is to omit both googleRedirectUrl and githubRedirectUrl — the buttons then do not render. To remove OAuth from the generated file entirely, edit components/simpleauth/modals/sign-up-modal.tsx and delete (a) the GoogleButton and GithubButton import lines, (b) the googleRedirectUrl / githubRedirectUrl entries in SignUpModalProps and the component destructure, and (c) the .sa-modal-oauth-below JSX block. You can also delete the unused feature files (for example components/simpleauth/ui/google-button.tsx, components/simpleauth/hooks/use-google-auth.ts, components/simpleauth/styles/google-button.css, and the GitHub equivalents).

Source

components/simpleauth/styles/simpleauth-modal.css
.sa-modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(17, 17, 17, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  z-index: 50;
}

.sa-modal {
  width: 100%;
  max-width: 360px;
  background: #ffffff;
  border: 1px solid #111111;
  color: #111111;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

.sa-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid #111111;
}

.sa-modal-heading {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.sa-modal-brand {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #111111;
}

.sa-modal-brand svg {
  width: 14px;
  height: 14px;
}

.sa-modal-title {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
}

.sa-modal-close {
  border: none;
  background: transparent;
  color: #111111;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
}

.sa-modal-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
}

.sa-modal-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: left;
}

.sa-modal-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.sa-modal-label {
  font-size: 14px;
  color: #111111;
}

.sa-modal-input {
  border: 1px solid #111111;
  padding: 8px 10px;
  background: #ffffff;
  color: #111111;
  font-size: 14px;
  outline: none;
}

.sa-modal-input:focus {
  outline: 2px solid #111111;
  outline-offset: -2px;
}

.sa-modal-error {
  color: #b00020;
  font-size: 13px;
  margin: 0;
}

.sa-modal-button {
  border: 1px solid #111111;
  background: #111111;
  color: #ffffff;
  padding: 8px 12px;
  font-size: 14px;
  cursor: pointer;
}

.sa-modal-button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.sa-modal-oauth-below {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
}

.sa-modal-divider-below {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: #555555;
  text-transform: lowercase;
}

.sa-modal-divider-below::before,
.sa-modal-divider-below::after {
  content: "";
  flex: 1;
  height: 1px;
  background: #111111;
  opacity: 0.2;
}

/* Used by SignUpModal email verification step */
.sa-verify-prompt {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
}

.sa-verify-prompt-title {
  font-size: 16px;
  font-weight: 600;
  margin: 0;
  color: #111111;
}

.sa-verify-prompt-body,
.sa-verify-prompt-hint {
  font-size: 14px;
  margin: 0;
  color: #111111;
  line-height: 1.45;
}

.sa-verify-prompt-hint {
  font-size: 13px;
  color: #444444;
}

.sa-verify-prompt-success {
  font-size: 13px;
  margin: 0;
  color: #0d5c2e;
}

.sa-verify-prompt-error {
  font-size: 13px;
  margin: 0;
  color: #b00020;
}

.sa-verify-prompt-button {
  border: 1px solid #111111;
  background: #ffffff;
  color: #111111;
  padding: 8px 12px;
  font-size: 14px;
  cursor: pointer;
  align-self: flex-start;
}

.sa-verify-prompt-button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.sa-modal-footer {
  margin-top: 12px;
  font-size: 13px;
}

.sa-modal-footer-line {
  margin: 8px 0 0;
}

.sa-modal-footer-muted {
  color: #555555;
}

.sa-modal-link {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: #111111;
  text-decoration: underline;
  font: inherit;
}

.sa-modal-link:hover {
  opacity: 0.85;
}

.sa-modal-footer-plain {
  font-size: 13px;
  color: #555555;
}

Customisation

Owned by you

Files live at components/simpleauth/modals/sign-up-modal.tsx and components/simpleauth/styles/simpleauth-modal.css.

On this page