LoginForm
<allegro-login-form> is a web component that authenticates readers via a magic
login link sent to their email, a six-digit one-time code, or via Google, Apple,
or Facebook OAuth. The email-based method is chosen with the
login-method attribute — magic link by default. The email input
and submit button always stack vertically; social login buttons stack on mobile
and sit side by side on wider screens (≥40em).
Set login-method="magic-link-otp" to send a single email containing both a
magic link and a six-digit code. The form has one submit button, just like the
single-method layouts; submitting it emails the reader both options and shows
the code-entry screen. Clicking the link in the email authenticates directly
(the form polls for that in the background), or the reader can type the code
instead — whichever they do first signs them in.
Usage
<allegro-login-form></allegro-login-form>
Customise the text labels via HTML attributes:
<allegro-login-form
form-label-text="Your email"
show-form-label="false"
placeholder-text="Your email"
button-text="Get my link"
publisher-name="Example News"
continue-text="Keep Reading"
hide-third-party="true"
></allegro-login-form>
Send a magic link and a one-time code together from a single form:
<allegro-login-form
login-method="magic-link-otp"
button-text="Sign in securely"
></allegro-login-form>
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
show-form-label | boolean | true | Whether to show the email field's label. When false, the label is still rendered for screen readers but visually hidden. |
form-label-text | text | Email Address | Label text for the email input field. |
placeholder-text | text | Enter your email | Placeholder shown inside the email input. |
button-text | text | Sign in | Label for the submit button in every login method. |
login-method | select | magic-link | Authentication method: magic-link (emails a login link), otp (emails a 6-digit code), or magic-link-otp (emails both a link and a code). |
hide-third-party | boolean | false | Set to true to hide all social login buttons (Google, Apple, Facebook). |
publisher-name | text | (empty) | Publisher name shown in the success state, e.g. "Welcome back to Example News!" |
continue-text | text | (empty) | Override the continue button label in the success state. |
learn-more-url | text | (empty) | URL to navigate to when the continue button is clicked in success state. |
show-last-used | boolean | false | Set to true to show a "Last used" badge on the login method (social provider or email) the reader most recently used to sign in. Recorded per-browser in localStorage. See Last used badge. |
tracking-data | text | (empty) | JSON object of custom data merged into every tracked event, e.g. "{'campaign': 'header'}". |
Last used badge
Set show-last-used to display a small "Last used" badge over the login method
the reader most recently used, helping returning readers pick the same method
again:
<allegro-login-form show-last-used></allegro-login-form>
The last-used method is recorded in the browser's localStorage (key
allegro:login-form:last-used) at the moment the reader initiates a login —
clicking a social provider button or submitting the email form. Recording only
happens when show-last-used is set, and the badge appears on the reader's next
visit. Because it is stored per browser, the badge does not follow the reader
across devices. If the last-used social provider is later disabled for the
tenant, no badge is shown.
Style the badge with the last-used-badge shadow part and the
--loginForm--last-used--* CSS variables listed below.
States
The component moves through several states as the chosen sign-in flow advances.
link-sent appears for the magic-link method, and code-entry for the
one-time-code method (login-method="otp") and for the combined
login-method="magic-link-otp" method — submitting the combined form always
sends the single email and moves straight to code-entry, since the reader can
either type the code there or click the link in the email. The expired state
adapts its wording to match whichever method was last used.
| State | Trigger | Description |
|---|---|---|
email | Initial render (unauthenticated, no token in URL) | Email input + social login buttons. |
loading | Initial render when allegro_token is present in the URL | Spinner shown while the SDK validates the token. |
link-sent | allegro:login-form:magic-link:sent fires (magic-link method) | "Check your email inbox" with a resend option. |
code-entry | A one-time code was requested successfully (otp or magic-link-otp method) | Six code-input boxes where the reader types the code. |
success | Initial render (already authenticated), or a magic link / one-time code is validated successfully | Checkmark + "Welcome back" with a continue button. |
expired | allegro:magic-link:failed fires, or an entered one-time code has expired or been locked | "Your link has expired" with a send-new-link button. |
If the user is already signed in when the component renders, it skips straight
to the success state.
Events
Dispatched by this component
| Name | Bubbles | Detail | Description |
|---|---|---|---|
allegro:login-form:magic-link:sent | yes | { email: string, data?: Record<string, unknown> } | Fired after a magic link is successfully sent. Triggers the link-sent state. |
allegro:login-form:authenticated | yes | (none) | Fired on every auth flow (magic link, one-time code, and social), before any flow-specific event. |
allegro:login-form:magic-link:authenticated | yes | (none) | Fired after a magic link is validated successfully. Follows allegro:login-form:authenticated. |
allegro:login-form:third-party:authenticated | yes | { provider: string, session_id: string, token: string } | Fired after a successful Google or Apple login. Follows allegro:login-form:authenticated. provider is the provider name (e.g. google). |
allegro:login-form:continue | yes | (none) | Fired when the user clicks the continue button in the success state. |
Listened to by this component (on window)
| Name | Detail | Description |
|---|---|---|
allegro:magic-link:authenticated | (none) | Dispatched by the SDK after a magic link is validated successfully. Transitions to the success state. |
allegro:magic-link:failed | { error: string } | Dispatched by the SDK when magic link validation fails (e.g. expired token). Transitions to the expired state. |
Slots
| Slot name | Appears in state | Description |
|---|---|---|
header | email | Rendered above the email input. Use for a title or description. Hidden once the form transitions to another state. |
footer | email | Rendered below the email input (and social buttons when present). Use for supplementary links. Hidden once the form transitions to another state. |
after-form | email | Rendered between the email input and the social login buttons. Use for supplementary inputs such as newsletter opt-in checkboxes. Values from named inputs inside this slot are included in the magic link request data. |
success | success | Replaces the entire success state UI (icon, heading, body, and continue button). When omitted, the default success UI is shown as fallback content. |
after-continue | success | Rendered directly below the continue button in the default success UI. Ignored when the success slot is provided. |
<allegro-login-form publisher-name="Example News">
<div slot="header">
<h2>Sign in to continue</h2>
<p>Access your account below.</p>
</div>
<p slot="footer">
<a href="/register">Don't have an account? Sign up</a>
</p>
</allegro-login-form>
To override the entire success state:
<allegro-login-form publisher-name="Example News">
<div slot="success">
<h2>You're in!</h2>
<p>Redirecting you now…</p>
</div>
</allegro-login-form>
Shadow Parts
For styling beyond what the CSS variables make available, elements can be
targeted directly with the CSS
::part() selector.
allegro-login-form::part(email-field-input) {
margin-bottom: 2rem;
}
| Part | Appears in state | Description |
|---|---|---|
email-form | email | The email input + submit button <form>. |
email-field | email | Wrapper around the email label and input. |
email-field-label | email | The email input's <label> element. |
email-field-input | email | The email <input> element. |
email-form-submit | email | The email submit button. |
social-divider | email | The "OR" divider between the email form and social buttons. |
social-row | email | Wrapper around the social provider buttons. |
social-btn | email | Every social provider button. Combined with a provider-specific part, e.g. social-btn social-btn-google. |
last-used-badge | email | The "Last used" badge. Only rendered when show-last-used is set. See Last used badge. |
link-sent | link-sent | Wrapper around the link-sent state UI. |
link-sent-icon | link-sent | The icon. |
link-sent-heading | link-sent | The heading. |
link-sent-body | link-sent | The body text. |
link-sent-resend | link-sent | The resend button. |
code-entry | code-entry | Wrapper around the code-entry elements. |
code-entry-icon | code-entry | The icon. |
code-entry-heading | code-entry | The heading. |
code-entry-body | code-entry | The body text. |
code-entry-input | code-entry | The six-digit code input box. |
code-entry-submit | code-entry | The verify button. |
code-entry-resend | code-entry | The resend button. |
success | success | Wrapper around the success elements. Not rendered when the success slot is provided. |
success-icon | success | The icon. |
success-heading | success | The heading. |
success-body | success | The body text. |
success-continue-button | success | The continue button. |
expired-heading | expired | The heading. |
expired-body | expired | The body text. |
expired-btn | expired | The send-new-link / send-new-code button. |
Tracked Events
The component records the following analytics events via the Allegro SDK.
| Event | When | Data |
|---|---|---|
magic_link_requested | A magic link is requested — on the initial submit, or when resent from the link-sent state. | { created: boolean } |
otp_requested | A one-time code is requested — on the initial submit, or when resent from a code-entry state. | { created: boolean } |
otp_validated | A submitted one-time code is accepted and the device is authenticated. | (none) |
login | Authentication completes through a social / SSO provider. | { provider: string } |
created is true when a new audience member was created for the email
address, and false when an existing member was matched.
Magic link validation is tracked separately as magic_link_validated by the
SDK when the link is opened, since that happens on the page the link points to
rather than within the form.
CSS Variables
All visual properties are exposed as CSS custom properties so the component can be themed from the host page without piercing the shadow DOM.
allegro-login-form {
--loginForm--input--background: #fff;
--loginForm--submit--background: #1a1a1a;
}
General
| Variable | Default | Description |
|---|---|---|
--loginForm--base-font-size | 1rem | Base unit all internal sizing is derived from. Defaults to the document's rem. See the note below. |
--loginForm--color | black | Base text colour for the component. |
--loginForm--font-family | system-ui, sans-serif | Font family applied to the entire component. |
Internally the form scales every dimension — padding, font sizes, spacing — from
--loginForm--base-font-size, which defaults to the page's rem. If the host
page sets a root font-size other than the usual 16px (for example a 10px
root), the form renders too small or too large. Pin the base to a fixed value so
the form sizes consistently regardless of the host page:
allegro-login-form {
--loginForm--base-font-size: 16px;
}
Form Layout
| Variable | Default | Description |
|---|---|---|
--loginForm--form--gap | 0.8rem | Gap between the field and submit button. |
--loginForm--label--margin | 0 0 0.4rem | Margin around the email field's label. |
Input
| Variable | Default | Description |
|---|---|---|
--loginForm--input--background | #fff | Input background colour. |
--loginForm--input--border | 1px solid #ccc | Input border shorthand. |
--loginForm--input--border-radius | 0.375rem | Corner radius applied to the input. |
--loginForm--input--font-size | 1rem | Input text size. |
--loginForm--input--padding | 0.75rem 1rem | Input padding shorthand. |
--loginForm--input--focus-border-color | #555 | Border colour when the input is focused. |
Submit button
| Variable | Default | Description |
|---|---|---|
--loginForm--submit--background | #000 | Button background colour. |
--loginForm--submit--color | #fff | Button text colour. |
--loginForm--submit--border-radius | 0.375rem | Corner radius applied to the button. |
--loginForm--submit--font-size | 0.875rem | Button text size. |
--loginForm--submit--font-weight | 700 | Button font weight. |
--loginForm--submit--letter-spacing | 0 | Button letter spacing. |
--loginForm--submit--font-family | inherit | Button font family. Inherits the surrounding font by default. |
--loginForm--submit--padding | 0.75rem 1.25rem | Button padding shorthand. |
--loginForm--submit--text-transform | uppercase | CSS text-transform applied to button label. |
Divider
| Variable | Default | Description |
|---|---|---|
--loginForm--divider--color | #333 | Text and line colour for the "OR" divider. |
--loginForm--divider--line-color | currentColor | Override only the line colour independently. |
--loginForm--divider--margin | 1rem 0 | Vertical spacing around the divider. |
Social buttons
| Variable | Default | Description |
|---|---|---|
--loginForm--social--background | #fff | Social button background colour. |
--loginForm--social--hover-background | #f9fafb | Social button background on hover. |
--loginForm--social--border | 1px solid #d1d5db | Social button border shorthand. |
--loginForm--social--border-radius | 0.5rem | Social button corner radius. |
--loginForm--social--color | #111 | Social button text colour. |
--loginForm--social--font-family | inherit | Social button font family. Inherits the surrounding font by default. |
--loginForm--social--font-size | 1rem | Social button text size. |
--loginForm--social--line-height | 1.25 | Social button line height. |
--loginForm--social--height | 42px | Minimum button height below the 640px breakpoint (stacked). |
--loginForm--social--height-desktop | 48px | Minimum button height at 640px and above (side-by-side). |
--loginForm--social--padding | 0.5rem 1rem | Social button padding shorthand. |
--loginForm--social--gap | 0.5rem | Gap between social buttons when stacked; same value applies in the side-by-side layout. |
Last used badge
Only rendered when the show-last-used attribute is set. Also exposed as the
last-used-badge shadow part for full style overrides.
| Variable | Default | Description |
|---|---|---|
--loginForm--last-used--background | #dbeafe | Badge background colour. |
--loginForm--last-used--color | #2563eb | Badge text colour. |
--loginForm--last-used--border | 1px solid #bfdbfe | Badge border shorthand. |
--loginForm--last-used--shadow | 0 1px 2px rgba(0, 0, 0, 0.15) | Badge drop shadow (box-shadow). |
--loginForm--last-used--border-radius | 999px | Badge corner radius. |
--loginForm--last-used--font-family | inherit | Badge font family. |
--loginForm--last-used--font-size | 0.6875rem | Badge text size. |
--loginForm--last-used--font-weight | 500 | Badge font weight. |
--loginForm--last-used--padding | 0.125rem 0.5rem | Badge padding shorthand. |
--loginForm--last-used--offset-x | -0.5rem | Horizontal offset of the badge from the button's right edge. |
--loginForm--last-used--offset-y | -0.5rem | Vertical offset of the badge from the button's top edge. |
Loading spinner
| Variable | Default | Description |
|---|---|---|
--loginForm--loading--track-color | currentColor | Spinner colour. Inherits the component text colour by default. |
State screens (link-sent, success, expired)
| Variable | Default | Description |
|---|---|---|
--loginForm--state-icon--background | #111 | Background colour of the circular state icon. |
--loginForm--state-heading--color | #111 | Heading text colour. |
--loginForm--state-heading--font-size | 1.25rem | Heading font size. |
--loginForm--state-heading--font-weight | 700 | Heading font weight. |
--loginForm--state-body--color | #555 | Body and disclaimer text colour. |
--loginForm--state-body--font-size | 0.9375rem | Body text size. |
--loginForm--resend--color | #555 | Resend link text colour. |
--loginForm--resend--hover-color | #111 | Resend link text colour on hover. |
--loginForm--resend--font-size | 0.875rem | Resend link font size. |
--loginForm--resend-error--color | #b91c1c | Text colour for the inline error shown below the resend/send-new-link button. |
Error message
| Variable | Default | Description |
|---|---|---|
--loginForm--error--background | #fef2f2 | Error container background colour. |
--loginForm--error--border | 1px solid #fecaca | Error container border shorthand. |
--loginForm--error--accent-color | #dc2626 | Left accent border colour. |
--loginForm--error--border-radius | 0.375rem | Error container corner radius. |
--loginForm--error--color | #b91c1c | Error message text colour. |
--loginForm--error--icon-color | currentColor | Error icon colour (inherits text colour by default). |
--loginForm--error--padding | 0.625rem 0.875rem | Error container padding. |
Example: Dark Background
When placing the component on a dark or coloured background, override the divider and social button colours so they read clearly:
allegro-login-form {
--loginForm--divider--color: rgba(255, 255, 255, 0.7);
--loginForm--social--background: transparent;
--loginForm--social--border: 1px solid rgba(255, 255, 255, 0.4);
--loginForm--social--color: #fff;
--loginForm--social--hover-background: rgba(255, 255, 255, 0.08);
}