Overlay Events
Every WireKit overlay component is event-controlled — you open it, close it, or scope it via $dispatch from Alpine OR $this->dispatch(...) from a Livewire component. There's no programmatic JS API to import; the event vocabulary IS the API.
This page is the canonical reference for every overlay event the components listen for, including the payload shape and Livewire-side dispatch examples. Each component's own docs page links here for the cross-reference.
Event matrix
| Component | Event name | Payload shape | Notes |
|---|---|---|---|
<x-wirekit::modal> |
wirekit-modal-show / wirekit-modal-close |
{ name } |
Dismissible by default — backdrop click + ESC both close. |
<x-wirekit::drawer> |
wirekit-drawer-show / wirekit-drawer-close |
{ name } |
Same shape as modal. |
<x-wirekit::alert-dialog> |
wirekit-alert-dialog-show / wirekit-alert-dialog-close |
{ name } |
Non-dismissible by default (safety); ESC always closes; backdrop stays inert without explicit dismissible="true". |
<x-wirekit::command-palette> |
wirekit-command-palette-show / wirekit-command-palette-close |
optional { name }, and { query } on show |
Without a name it reaches every palette on the page except one with named-only; with one, only the palette whose name prop matches. A query opens the palette with that text in its field, see Opening with text. Escape closes it too, and so does choosing an item, after the item's own click handler has run. |
<x-wirekit::tour> |
wirekit-tour-start-<name> (name suffixed into the event name) |
— (no detail) | The tour's name prop is appended to the event with a hyphen separator. Example: <x-wirekit::tour name="onboarding"> listens for wirekit-tour-start-onboarding. |
<x-wirekit::toast-region> |
wirekit-toast (global) OR wirekit-toast-<name> (scoped) |
{ title, message, variant, duration? } |
Different payload from the show/close family — toasts carry their own content. |
<x-wirekit::lightbox> |
wirekit-lightbox-open |
{ name, index } |
Opens the named lightbox at a given item. It was missing from this table while the page called itself the canonical reference for every overlay event. |
<x-wirekit::command-palette> |
wirekit-command-palette-query |
{ query } |
Dispatched BY the palette, not listened for. It fires from the component root rather than the input, because the input teleports to <body> and an event fired there never passes the root. |
<x-wirekit::command-palette> |
wirekit:command-palette-state |
{ state, name? } |
Addressed like the palette's show and close events: every palette without a name, only the named one with it. state is loading, error or idle, and says where your remote search stands: the palette shows its loading or error slot and holds back the empty state meanwhile. Any other value counts as idle. A remote search shows it at work. |
<x-wirekit::modal> |
wirekit:modal-dismissed |
{ name, via } |
Dispatched BY the modal, on the window, when the reader dismisses it: via is backdrop, escape or close-button. Never for a close the page asked for, so a cleanup it triggers runs once. |
<x-wirekit::drawer> |
wirekit:drawer-dismissed |
{ name, via } |
Dispatched BY the drawer, the same as the modal's. |
Shape detail
Most overlays take { name: 'unique-id' } where name matches the component's name="..." prop. Multiple overlays on the same page each listen for their own name; events targeted at a different name are ignored.
Command palette takes the show/close verbs of the family, and its payload is optional. Dispatched without one, $dispatch('wirekit-command-palette-show') opens every palette on the page and the close event closes every one, which is all a page with a single palette needs. A page with two gives each a name prop and puts the same name in the event, $dispatch('wirekit-command-palette-show', { name: 'search' }), and only that palette answers. The keyboard shortcut is not addressed by name, so set hotkey="" on all but one. A palette that must not answer the unnamed event at all, such as a site search beside demos, takes named-only. See Two palettes on one page.
Tour is the odd one out — instead of a payload, the tour's name is part of the event NAME itself. $dispatch('wirekit-tour-start-onboarding') starts the tour named onboarding; no payload object needed. This shape is historical; it's documented but kept stable for back-compat.
Toast is also irregular — instead of { name }, the payload carries the toast's CONTENT: { title, message, variant, duration? }. The variant value mirrors the canonical 4-state semantic enum (info / success / warning / danger). The scoping mechanism (which <x-wirekit:: instance picks up the event) is event-NAME-based: regions with name="..." listen on wirekit-toast-<name>, regions without a name listen on the global wirekit-toast.
Examples — opening from Alpine (client-side)
The contract in one live block: a button that dispatches, a modal that listens, and a readout of what actually crossed the window. Open and close it and watch the two names arrive in order.
Last overlay event:
Two things the block is there to show rather than assert. The name in the payload is what
picks this modal out of however many are on the page — dispatch a different one and nothing
opens. And every close route reports the same event: there is no separate "dismissed by
backdrop" signal to listen for.
Trigger a modal from a custom button outside the dialog markup:
<button x-on:click="$dispatch('wirekit-modal-show', { name: 'settings' })">
Open settings
</button>
<x-wirekit::modal name="settings">
<x-wirekit::modal.header>Settings</x-wirekit::modal.header>
<x-wirekit::modal.body>
...
</x-wirekit::modal.body>
</x-wirekit::modal>
Close from inside the modal (Cancel button):
<button x-on:click="$dispatch('wirekit-modal-close', { name: 'settings' })">
Cancel
</button>
Open a tour by name:
<button x-on:click="$dispatch('wirekit-tour-start-onboarding')">
Start tour
</button>
Show a toast — global region (single <x-wirekit:: on the page):
<button x-on:click="$dispatch('wirekit-toast', {
title: 'Saved',
message: 'Your changes are live.',
variant: 'success',
duration: 4000
})">
Save
</button>
Show a toast — scoped region (when multiple regions exist with different name="..." props):
<x-wirekit::toast-region name="critical" />
<x-wirekit::toast-region name="info" />
<button x-on:click="$dispatch('wirekit-toast-critical', {
title: 'Connection lost',
message: 'Retrying in 5s...',
variant: 'danger'
})">
Simulate connection loss
</button>
Examples — dispatching from Livewire (server-side)
Every Alpine $dispatch call has a 1:1 Livewire equivalent via $this->dispatch(...). Same event name; payload becomes named arguments.
Open a modal from a Livewire method:
public function openSettings(): void
{
$this->dispatch('wirekit-modal-show', name: 'settings');
}
Show a toast as a flash after a server-side action:
public function save(): void
{
// ... persist state ...
$this->dispatch('wirekit-toast',
title: 'Saved',
message: 'Your changes are live.',
variant: 'success',
duration: 4000,
);
}
Close an alert-dialog after a destructive confirmation runs:
public function deleteProject(): void
{
Project::find($this->projectId)->delete();
$this->dispatch('wirekit-alert-dialog-close', name: 'delete-project');
}
Conventions + footguns
The event vocabulary has a few historical irregularities documented here so AI tooling and LLM-driven scaffolding produce correct code on the first try.
- The overlay events on this page use hyphens throughout — and they are the exception.
$dispatch('wirekit:modal-show', …)silently does nothing; the shape these components listen for is$dispatch('wirekit-modal-show', …). This does not generalize. The library's convention iswirekit:<component>-<happening>— a colon after the namespace — and Events documents it as such:wirekit:tab-changed,wirekit:reveal,wirekit:inline-edit-confirmed,wirekit:reading-progress:milestone. The overlays predate that convention and keep the all-hyphen form for back-compat, so the rule to carry is "look the event up", not "WireKit does not use colons". <x-wirekit::suffixes the name into the event itself, not the payload. Dispatchingtour> wirekit-tour-start-${this.rather thanname} wirekit-tour-startwith a{ name }payload. This was an early-design choice that didn't generalize to the show/close pattern; subsequent overlays standardized on the{ name }payload shape.<x-wirekit::usestoast-region> variant, notintent. The toast payload key isvariant: 'info' | 'success' | 'warning' | 'danger'— same value set as badge / alert / callout, but the prop name diverges. See Prop Naming Conventions for theintent/surface/variant/tonefamily split and the alias matrix.- Show events are fire-and-forget — the dispatcher gets no return value. If you need to act AFTER the overlay opens (e.g. focus a specific input inside the modal once it's mounted), listen for the overlay's own lifecycle event from Alpine inside the panel scope rather than chaining off the dispatch.
Standardization roadmap
A v3.0.0 candidate is to unify the event surface:
- Standard verb scheme:
-show/-closeeverywhere (toast becomeswirekit-toast-show; tour becomeswirekit-tour-showwith{ name }payload). - Standard payload shape:
{ name, ...extras }everywhere. Toast carries{ name, title, message, intent, duration? }—variantmigrates tointentfor cross-component consistency.
This is intentionally NOT shipping in v2.x — back-compat fence. Until then, the matrix above is the contract, and the event names in it keep working unchanged for the whole of v2.