Skip to main content
WireKit
Copy for LLM

Toast

Event-driven notifications that appear temporarily to confirm actions or surface warnings. Toasts auto-dismiss after a configurable duration and stack vertically in a fixed corner of the viewport.

Basic Usage

Mount the toast region once per layout (typically in your app shell):

{{-- In your layout file --}}
<x-wirekit::toast-region />

The region listens on window, so anything that dispatches the event reaches it — a Livewire component after the write succeeds, or Alpine's $dispatch for a purely client-side action.

Most toasts report the outcome of something the server did, so that is the shape shown here: the button calls a Livewire action, and the toast is dispatched after the save returns. Nothing in the markup decides what the toast says.

Trigger a toast

Variants

Four semantic variants control color, icon, and ARIA behavior. Click each button to see the toast:

Toast variants

Position

Control where toasts appear on the screen:

<x-wirekit::toast-region position="top-right" />    {{-- default --}}
<x-wirekit::toast-region position="top-left" />
<x-wirekit::toast-region position="top-center" />
<x-wirekit::toast-region position="bottom-right" />
<x-wirekit::toast-region position="bottom-left" />
<x-wirekit::toast-region position="bottom-center" />

Each region below uses a scoped name prop so it only listens on its own channel — avoiding cross-talk with other regions on the same page:

Top-left position
Bottom-right position

Duration

Toasts auto-dismiss after 5 seconds by default. Override per-region or per-toast:

{{-- All toasts in this region dismiss after 3 seconds --}}
<x-wirekit::toast-region :duration="3000" />
// Per-toast override (0 = persistent, must be manually dismissed)
$dispatch('wirekit-toast', {
    title: 'Permanent',
    message: 'This toast stays until dismissed.',
    duration: 0
})

Queue Limit

Limit how many toasts are visible at once. Oldest toasts are removed when the limit is reached:

<x-wirekit::toast-region :max="3" />

Scoped Regions

By default, all toast regions listen on the global wirekit-toast event. When you have multiple regions (e.g. one for system notifications, one for form feedback), use the name prop to scope each region to its own event channel. This prevents duplicate toasts appearing in every region.

{{-- System notifications — listens on 'wirekit-toast-system' --}}
<x-wirekit::toast-region name="system" position="top-right" />

{{-- Form feedback — listens on 'wirekit-toast-form' --}}
<x-wirekit::toast-region name="form" position="bottom-right" />

Dispatch to a specific region by targeting its scoped event name:

// Only appears in the "form" region
$dispatch('wirekit-toast-form', {
    variant: 'success',
    title: 'Saved',
    message: 'Your changes were saved.'
})

// Only appears in the "system" region
$dispatch('wirekit-toast-system', {
    variant: 'warning',
    title: 'Maintenance',
    message: 'Scheduled downtime in 30 minutes.'
})

Regions without a name prop continue to listen on the default wirekit-toast event, so existing code works unchanged.

eventScope — DOM-containment filter (alternative to name)

When you can't (or don't want to) coordinate distinct event names — for example because every region on the page emits the same wirekit-toast event but each region should only handle events from its own portion of the DOM — set eventScope to a CSS selector. The region then ignores any event whose dispatching element doesn't sit inside an ancestor matching the selector:

{{-- Per-section toast surface: only handles events dispatched from inside the wrapper --}}
<div data-wk-section-toast>
    <x-wirekit::toast-region eventScope="[data-wk-section-toast]" position="top-right" />

    {{-- Buttons in this section dispatch the standard event; only THIS region picks it up --}}
    <x-wirekit::button @click="$dispatch('wirekit-toast', { variant: 'success', message: 'Saved' })">
        Save
    </x-wirekit::button>
</div>

name (event-name routing) and eventScope (DOM-containment filtering) are independent and may be combined — set both to require both a matching event name AND a dispatcher inside the scope wrapper. Default null means no containment filter (every dispatched event of the matching name is handled — the existing global-listener behavior).

This is the cleanest pattern for "per-card local toast queues" and similar layouts where the section that emits the toast is the section that should display it.

Pause on Hover

Auto-dismiss pauses when the user hovers over a toast and resumes when they move away. This is built-in — no configuration needed.

Dispatch Payload

The wirekit-toast event accepts:

Property Type Default Description
title string null Bold heading
message string '' Body text
variant string 'info' info | success | warning | danger
duration number Region default Auto-dismiss in ms (0 = persistent)

Width & Layout

Individual toasts have a fixed width of w-80 (20rem / 320px), capped to the viewport width minus 2rem on narrow screens (max-w-[calc(100vw-2rem)]). Position is controlled by the position prop on the toast region — not by CSS classes. Stack direction and spacing are handled automatically.

Props

Prop Type Default Description
position string 'top-right' Where toasts appear. One of: top-left, top-center, top-right, bottom-left, bottom-center, bottom-right
duration number 5000 Default auto-dismiss duration in ms
max number 5 Maximum visible toasts (oldest removed when exceeded)
name string null Scoped name — listens on wirekit-toast-{name} instead of global wirekit-toast
eventScope string null CSS selector — when set, only events whose dispatching element is inside an ancestor matching the selector are handled (DOM-containment filter, complements name's event-name routing)
filled bool false Use full variant background color instead of light tint (like a filled callout)
scope string null Scoped personalization key

Accessibility

  • Info and success toasts use role="status" with aria-live="polite" — announced after the user finishes their current action.
  • Warning and danger toasts use role="alert" with aria-live="assertive" — announced immediately.
  • aria-atomic="true" ensures the full toast is read, not just the changed part.
  • Each toast has a visible dismiss button with aria-label="Dismiss notification".
  • Toasts never steal focus from the page — they are purely informational.
  • Decorative icons are aria-hidden="true".

Keyboard Interaction

This component is purely presentational and does not respond to keyboard input.

Pitfalls

  • Don't use a toast for errors that block progress. Toasts auto-dismiss; errors that the user must acknowledge belong in <x-wirekit::alert-dialog> or an inline <x-wirekit::alert>.
  • Don't show more than 3 toasts simultaneously. Stacking degrades into noise — the component's queue dispatcher already enforces a soft limit, but custom dispatch logic should respect it.

Design Tokens

Toasts use the same tinted-background approach as Alert for visual consistency:

Token Usage
--color-wk-accent Info variant icon + border tint
--color-wk-success Success variant
--color-wk-warning Warning variant
--color-wk-danger Danger variant
--shadow-wk-lg Toast card elevation
--radius-wk-md Card corner radius
--padding-wk-x-md / --padding-wk-y-md Card padding
--font-wk-sans Font family
--transition-wk-duration Enter/leave animation timing

Customization

Override toast styles via personalization:

WireKit::personalize('toast-region', [
    'base' => 'fixed z-[9999] flex flex-col gap-4 p-6',
    'toast' => 'w-96 rounded-xl shadow-2xl',
]);

Was this page helpful?

Thanks — that helps.

Voting requires cookies or local storage. What we store