Auth Forms
Workspace SSO gate
Email first, then SSO or password
Email first, then SSO or password
Create an email-first sign-in card with Tailwind CSS, max-w-sm on a neutral background. Start with a logo badge, a "Sign in to Northwind" heading, and a line explaining that the work email decides the sign-in method. The form holds an email field with a hidden inline error line, a hidden identity row that shows the confirmed address in a grey pill with a "Change" button, a hidden password field, a full-width dark Continue button, and a hidden note about single sign-on. Finish with a "Create an account" link. Then add JavaScript for the two-step flow: on Continue, validate the address and reveal the error if it is malformed; otherwise lock the email into the identity pill and look up its domain in a small map of SSO-enabled companies — matched domains relabel the button "Continue with Okta" (or whichever provider) and reveal the SSO note, unmatched domains reveal the password field and relabel the button "Sign in". "Change" restores the first step, and the button label always reflects the current step. <div class="flex min-h-screen items-center justify-center bg-neutral-100 p-6">
<div class="w-full max-w-sm rounded-2xl border border-neutral-200 bg-white p-8 shadow-sm">
<div class="mb-6 h-9 w-9 rounded-lg bg-neutral-900"></div>
<h1 class="text-xl font-semibold text-neutral-900">Sign in to Northwind</h1>
<p class="mt-1 text-sm text-neutral-500">Use your work email — we will send you to the right sign-in method.</p>
<form id="gate" class="mt-6 space-y-3">
<div id="emailRow">
<input id="email" type="email" placeholder="[email protected]"
class="w-full rounded-xl border border-neutral-200 px-3.5 py-2.5 text-sm outline-none focus:border-neutral-900 focus:ring-4 focus:ring-neutral-900/10" />
<p id="error" class="mt-1.5 hidden text-xs text-red-600">Enter a valid work email address.</p>
</div>
<div id="identity" class="hidden items-center justify-between gap-3 rounded-xl border border-neutral-200 bg-neutral-50 px-3.5 py-2.5">
<span id="identityEmail" class="truncate text-sm text-neutral-700">[email protected]</span>
<button type="button" id="change" class="shrink-0 text-xs font-medium text-neutral-900 hover:underline">Change</button>
</div>
<div id="passwordRow" class="hidden">
<input id="password" type="password" placeholder="Password"
class="w-full rounded-xl border border-neutral-200 px-3.5 py-2.5 text-sm outline-none focus:border-neutral-900 focus:ring-4 focus:ring-neutral-900/10" />
</div>
<button id="submit" type="submit" class="w-full rounded-xl bg-neutral-900 py-2.5 text-sm font-medium text-white transition hover:bg-neutral-800">Continue</button>
<p id="ssoNote" class="hidden text-center text-xs text-neutral-500">Your organisation requires single sign-on.</p>
</form>
<p class="mt-6 text-center text-sm text-neutral-500">
New here? <a href="#" class="font-medium text-neutral-900 hover:underline">Create an account</a>
</p>
</div>
</div> // Domains that are wired to an identity provider. Everything else gets a password.
var SSO = {
"northwind.co": "Okta",
"acme.com": "Microsoft Entra ID",
"globex.io": "Google Workspace"
};
var form = document.getElementById("gate");
var emailRow = document.getElementById("emailRow");
var email = document.getElementById("email");
var error = document.getElementById("error");
var identity = document.getElementById("identity");
var identityEmail = document.getElementById("identityEmail");
var change = document.getElementById("change");
var passwordRow = document.getElementById("passwordRow");
var password = document.getElementById("password");
var submit = document.getElementById("submit");
var ssoNote = document.getElementById("ssoNote");
var step = "email";
function reset() {
step = "email";
emailRow.classList.remove("hidden");
identity.classList.add("hidden");
identity.classList.remove("flex");
passwordRow.classList.add("hidden");
ssoNote.classList.add("hidden");
submit.textContent = "Continue";
email.focus();
}
form.addEventListener("submit", function (e) {
e.preventDefault();
if (step === "method") return; // Real apps hand off to the provider here.
var value = email.value.trim().toLowerCase();
var valid = /^[^@\s]+@[^@\s]+\.[^@\s]{2,}$/.test(value);
error.classList.toggle("hidden", valid);
if (!valid) return;
step = "method";
emailRow.classList.add("hidden");
identityEmail.textContent = value;
identity.classList.remove("hidden");
identity.classList.add("flex");
var provider = SSO[value.split("@")[1]];
if (provider) {
submit.textContent = "Continue with " + provider;
ssoNote.classList.remove("hidden");
return;
}
passwordRow.classList.remove("hidden");
submit.textContent = "Sign in";
password.focus();
});
change.addEventListener("click", reset);