SignInModal
Self-contained sign-in modal component with close handling and built-in auth submission.
Overview
SignInModal is a self-contained auth modal. It renders its own email/password form, uses useSignIn, and closes on success. The footer always nudges new users toward sign-up (signUpHref / onSwitchToSignUp for navigation). The generated component imports components/simpleauth/styles/simpleauth-modal.css.
Preview
Interactive preview requires JavaScript.
Install
npx @simpleauthjs/react add modal --style minimalThe 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
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
open | boolean | Yes | — | Controls visibility. |
onClose | () => void | Yes | — | Called when the modal should close (backdrop click, close button, or success). |
onSuccess | () => void | No | undefined | Fires after a successful sign-in before the modal closes. |
appName | string | No | undefined | Shown in the header next to the SimpleAuth badge. When set, the title becomes Sign in to {appName}. |
signUpHref | string | No | undefined | Footer “Create one” link when onSwitchToSignUp is not set. |
forgotPasswordHref | string | No | undefined | Footer “Forgot password?” link when onForgotPassword is not set. |
onSwitchToSignUp | () => void | No | undefined | Footer button for sign-up; takes precedence over signUpHref. |
onForgotPassword | () => void | No | undefined | Footer button for forgot password; takes precedence over forgotPasswordHref. |
googleRedirectUrl | string | No | undefined | When set, renders Continue with Google below the email form. |
githubRedirectUrl | string | No | undefined | When set, renders Continue with GitHub below the email form. |
Usage
"use client"
import { useState } from "react"
import { SignInModal } from "@/components/simpleauth"
export function HeaderAuth() {
const [open, setOpen] = useState(false)
return (
<>
<button type="button" onClick={() => setOpen(true)}>
Sign in
</button>
<SignInModal
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-in-modal.tsx and delete (a) the GoogleButton and GithubButton import lines, (b) the googleRedirectUrl / githubRedirectUrl entries in SignInModalProps 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
.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
Update components/simpleauth/modals/sign-in-modal.tsx and components/simpleauth/styles/simpleauth-modal.css to match your brand and interaction patterns.