Designer view
Login Form
The canonical credentials surface — a `<form>` with an identifier field (email or username), a password field with a visibility toggle, a primary submit button, and secondary affordances (forgot-password link, sign-up link). Composes TextInput twice, Button, and Link. Single-page variant is canonical; split-page ("email first, password on next screen") is documented as a decision rather than a separate pattern.
Composition
-
Text Input identifier field (email or username) Use `type="email"` with `autocomplete="email"` for the contemporary canonical login. For dual identifier flows (email or username accepted), use `type="text"` with `autocomplete="username"` and accept any string. Initial focus lands here unless the page is loaded with the field pre-filled by autofill.
-
Text Input password field Use `type="password"` with `autocomplete="current-password"` for the login flow specifically (signup uses `new-password`). The trailing-icon slot hosts the visibility toggle as a real `<button type="button">` — never the password input itself with `type` flipping. The `required` attribute pairs with a visible required indicator.
-
Button primary action (submit) Use `variant="primary"` and `type="submit"`. The button label names the action ("Sign in", "Log in") — never generic "Submit" or "OK". The button must be inside the `<form>` so Enter on either field submits.
-
Link forgot-password recovery Use `variant="inline"` placed near the password field (above it or to the right). Routes to the password-recovery flow. Distinguished from the sign-up link by position and by the verb of its text ("Forgot your password?").
-
Link alternate-flow link (sign up / register) Use `variant="inline"` placed near the submit button (typically below it). Routes to the registration flow when the user has no account. Optional — omit if the product has no public sign-up (B2B SaaS with admin-provisioned accounts).
When to use
- Use
- For account-based products where the user authenticates with a credential the system can verify. The canonical entry point when the auth model is "the user has previously created an account and is now returning". Single-page variant for the common case; split-page for products with passwordless or federated-identity flows where the email determines the next step.
- Avoid
- For unauthenticated browsing — gate only what genuinely requires identity. For machine-to-machine auth — that is API keys, not a login form. For one-off email-magic-link flows — that pattern (single email field plus Send button) is a distinct passwordless-login pattern. For role-elevated re-authentication ("confirm your password to delete account") use a `Confirmation Flow` with a password TextInput inside, not a full Login Form.
Canonical decisions
-
Single-page (email + password together) or split-page (email first, password on next screen)?
Single-page is the canonical default; split-page is a product decision tied to passwordless / federated flows.
Single-page is faster for users with stored credentials in a password manager (one form, one autofill, one submit). Split-page only pays off when the email determines the flow (federated-SSO redirect, passwordless magic-link, MFA-only-account). Google, Microsoft, Apple use split-page because email selects the auth provider; most other products do not have that fork. Default to single-page; split when the email-routes-to-different-flow constraint is real.
-
Show "wrong email" and "wrong password" as separate errors, or as a single combined error?
Single combined error — "Wrong email or password" — for production; never disclose which one was wrong.
Specific errors leak account-existence information. An attacker enumerating addresses can probe the form: a "wrong password" response confirms the email is registered; a "wrong email" response confirms it is not. The combined message removes the enumeration oracle. Pair with rate-limiting and CAPTCHA-on-failure for the complete defence; the message text alone is necessary not sufficient. OWASP ASVS 2.1, NIST SP 800-63B, and the Auth0 / Okta security guides all converge on this rule.
-
Should the password field have a visibility toggle?
Yes — recommended for all login forms.
The visibility toggle reduces typo-driven failed-login attempts (especially on mobile, where touch keyboards hide the typed character after a brief reveal). The security objection — "shoulder-surfing in public spaces" — is mitigated by the toggle defaulting to hidden and requiring an explicit press. The accessibility benefit to users with motor or vision differences is large. NIST SP 800-63B explicitly recommends allowing password reveal. The toggle button is a real `<button>` with an accessible label that updates ("Show password" / "Hide password").
-
Where does initial focus land?
The first empty field — usually the email input, unless browser autofill has populated it, in which case focus the password.
Auto-focusing the page on load forces a scroll on mobile (the on-screen keyboard pops up immediately and shifts the layout). The trade is between "fast for keyboard users" and "jarring for mobile users". Canonical resolution: do focus the email field on `DOMContentLoaded` for desktop (`@media (hover: hover) and (pointer: fine)`) and skip the autofocus on touch devices. Or simpler: do not auto-focus at all and rely on the user's tap or Tab. The "no autofocus" rule is the more conservative canon; document both choices.
-
What `autocomplete` tokens go on each field?
Email field: `autocomplete="email"` (or `username` if the identifier is not strictly an email). Password field: `autocomplete="current-password"`. Sign-up flows use `new-password` instead.
The autocomplete tokens are how browsers and password managers recognise the form. `current-password` tells the manager "this is the field where the existing stored password should fill in"; `new-password` tells it "this is a registration form, suggest a strong new password". Mixing them — using `new-password` on a login form — breaks autofill and forces the user to type the password manually every time. The HTML spec lists the full token set; getting these right is the difference between a form that works with 1Password and one that does not.
-
Is the email field required?
Yes — both fields are required. Pair the visible required indicator with the `required` HTML attribute on each input.
Browser-native validation surfaces the empty-required message at the right moment (form submit). Server-side validation must still run; client-side `required` is for UX, not security. The visible indicator (asterisk or "(required)") tells users before they try to submit; the attribute tells the browser and assistive tech.
Notes
This is the second canonical pattern after Confirmation Flow. Triangulated against APG (textbox + button patterns), HTML spec on `autocomplete`, NIST SP 800-63B (password guidance + reveal- is-allowed), OWASP ASVS 2.1 (authentication), Polaris Account pattern, Material 3 Sign-in Form, and the auth0 / Okta / WorkOS engineering blogs on enumeration-resistant login forms. Library APIs and security guidance evolve; re-validate against current docs and threat-modelling discipline before citing in production reviews. Sign-up Form, Password Recovery Flow, and Magic-Link Login are sibling patterns deferred to follow-up work.