<seva-event-register-modal>
The <seva-event-register-modal> component is a thin portal-based wrapper around <seva-event-register>. It opens in response to a document-level event and contains the full registration flow — sign-in, attendee selection, ticket choice, and confirm — inside a centered modal.
Overview
Section titled “Overview”The modal exists to decouple the registration form from whatever opens it. Common pairings:
- Webflow event detail page:
<seva-event-register-cta>renders an inline “Register” button that dispatchesseva:open-registration; the modal listens and opens. - Custom button anywhere on the site: Your own button dispatches
seva:open-registrationwith aneventSlugin the detail; the modal opens to that event. - Direct linking: Place the modal with the
openattribute and anevent-slugto auto-open on page load (e.g. for an “RSVP now” link from an email).
This is a modal component — auth is read from localStorage by the inner <seva-event-register>, so no glue script is required to propagate tokens. See Inline vs. modal components for details on the distinction.
The modal closes itself automatically when the registration flow advances to a state the modal shouldn’t keep blocking: a successful add-to-cart, a checkout starting, or the user declining the event.
Quick Example
Section titled “Quick Example”The modal alone, opened from a custom button:
<script type="module" src="YOUR_COMPONENTS_URL/seva-event-register-modal.js"></script>
<seva-event-register-modal tenant-slug="my-club" api-url="https://api.seva.tools"></seva-event-register-modal>
<button onclick="document.dispatchEvent(new CustomEvent('seva:open-registration', { detail: { eventSlug: 'annual-gala' } }))"> RSVP for Annual Gala</button>The <seva-event-register-modal> element must be present in the DOM for the event to be received — Lit components don’t auto-mount on event dispatch. The modal is rendered into a portal at document.body, so it can sit anywhere in your markup without affecting layout.
Attributes
Section titled “Attributes”| Attribute | Type | Default | Description |
|---|---|---|---|
event-slug | string | '' | Initial event slug. Can be overridden at open time via the eventSlug field in the seva:open-registration event detail. |
tenant-slug | string | '' | Required. Your organization’s tenant slug. |
api-url | string | 'https://api.seva.tools' | Base URL of the Seva API. |
theme | 'light' | 'dark' | 'light' | Color theme passed through to the inner form. |
auth-token | string | null | null | Pre-supplied bearer token. When set, bypasses the inner form’s localStorage lookup. Rarely needed. |
start-view | EventRegisterView | 'sign-in' | Initial view inside the modal. Default skips 'event-info' because Webflow renders event details on the page already. Can be overridden at open time via the view field in the event detail. |
open | present/absent | absent | If present at mount, the modal auto-opens via queueMicrotask. Useful for deep-link / launched-from-URL flows. The Webflow CTA pattern uses event dispatch instead. |
Events listened for
Section titled “Events listened for”All events are observed on document:
| Event | Detail | Effect |
|---|---|---|
seva:open-registration | { eventSlug?, view? } | Opens the modal. If eventSlug is provided and differs from the current value, updates it. The view field overrides start-view for this open; absent → resets to default. |
seva:add-to-cart | (any) | Closes the modal. The cart drawer takes over. |
seva:open-cart | (any) | Closes the modal so the cart drawer isn’t stacked behind it. |
seva:checkout-started | (any) | Closes the modal — the cart drawer’s checkout flow has begun. |
seva:registration-declined | (any) | Closes the modal after a decline action completes. |
The modal does not dispatch any custom events of its own. The events you’ll observe (seva:add-to-cart, seva:registration-completed, seva:authenticated, etc.) are dispatched by the inner <seva-event-register> form.
Public methods
Section titled “Public methods”The modal extends an internal PortalHost base class, which provides:
| Method | Description |
|---|---|
show() | Open the modal. Idempotent — safe to call when already open. |
hide() | Close the modal. |
In normal use you should not need to call these directly — dispatch seva:open-registration instead, which lets multiple modals on the same page (e.g. across iframes or page-controllers) coordinate via the shared event channel.
Behavior notes
Section titled “Behavior notes”- The modal must be in the DOM at the time the open event fires. Lit components don’t bootstrap themselves on event dispatch; if the element is added to the DOM after a button click, the open won’t happen. Place
<seva-event-register-modal>once, near the end of<body>, and leave it mounted. - The inner form remounts on each open. When the modal opens, it conditionally renders
<seva-event-register>with the currentevent-slugandstart-view. When it closes, the form is destroyed. This keeps state from one registration session from bleeding into the next. start-viewdefaults to'sign-in'rather than the form’s own default of'event-info'. The reason: a Webflow event page already shows the event title, dates, and description above the CTA — duplicating them inside the modal would be redundant. Override via theviewfield inseva:open-registrationif you do want to start at the event-info view.- The backdrop click closes the modal. A close button (×) in the top-right corner does the same. The close button is auto-focused when the modal opens for keyboard accessibility.
auth-tokenattribute is rarely needed. The inner form looks up the token fromlocalStorage(seva-auth-{tenantSlug}) automatically. Only set this attribute when you have a token from outside the normal sign-in flow (e.g. a server-rendered page that mints a token server-side).
Cross-component coordination
Section titled “Cross-component coordination”<seva-event-register-cta>— the recommended companion on event detail pages. The CTA renders the inline “Register” button and dispatchesseva:open-registration.<seva-event-register>— the form that the modal wraps. You don’t embed this directly when using the modal.<seva-cart>/<seva-cart-drawer>— the drawer auto-opens onseva:add-to-cart(the same event that closes this modal), so the modal → drawer handoff is seamless.
Full Example
Section titled “Full Example”A standalone “RSVP” button anywhere on the site, opening the modal directly:
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Events — My Club</title> <script type="module" src="YOUR_COMPONENTS_URL/seva-event-register-modal.js" ></script> <script type="module" src="YOUR_COMPONENTS_URL/seva-cart-drawer.js" ></script> </head> <body> <h1>Upcoming Events</h1>
<ul> <li> Annual Gala — <button onclick="document.dispatchEvent(new CustomEvent('seva:open-registration', { detail: { eventSlug: 'annual-gala' } }))" > RSVP </button> </li> <li> Summer Picnic — <button onclick="document.dispatchEvent(new CustomEvent('seva:open-registration', { detail: { eventSlug: 'summer-picnic' } }))" > RSVP </button> </li> </ul>
<!-- One modal handles all events; eventSlug is set per-open via the dispatch detail. --> <seva-event-register-modal tenant-slug="my-club" api-url="https://api.seva.tools" > </seva-event-register-modal>
<!-- Cart drawer handles checkout after add-to-cart. --> <seva-cart-drawer tenant-slug="my-club" api-url="https://api.seva.tools"> </seva-cart-drawer> </body></html>For the recommended Webflow event-page pattern (CTA + modal), see <seva-event-register-cta>.