Toast
The toast shows a brief notification that stacks in a corner and dismisses itself, like "Changes saved" after a form submit. It is created from JavaScript rather than authored markup; for a message that must interrupt and be acknowledged, use a dialog instead.
Usage
Call sp.toast() with a message and an optional configuration object, and everything is created for you: toasts stack with the newest in front, and hovering the stack expands it. The rendered elements carry these classes:
sp.toast("Event has been created");Examples
Types
Use the shorthand methods for a leading status icon, or pass the type option.
<div class="flex flex-wrap justify-center gap-2">
<button class="btn btn-outline" onclick="sp.toast('Event has been created')">
Default
</button>
<button
class="btn btn-outline"
onclick="sp.toast.success('Event has been created')"
>
Success
</button>
<button
class="btn btn-outline"
onclick="sp.toast.info('Be at the area 10 minutes before the event time')"
>
Info
</button>
<button
class="btn btn-outline"
onclick="sp.toast.warning('Event start time cannot be earlier than 8am')"
>
Warning
</button>
<button
class="btn btn-outline"
onclick="sp.toast.error('Event has not been created')"
>
Error
</button>
</div>Description
Add a secondary line of text with the description option.
Type with description
A status icon next to a title and description.
Action
Add a clickable action button; choosing it also dismisses the toast.
Loading and update
sp.toast.loading() shows a spinner and stays put; call update() on the returned instance to swap it to a result state.
const t = sp.toast.loading("Creating post...");
const res = await fetch("/api/posts", { method: "POST", body });
if (res.ok) {
t.update({ title: "Post created", type: "success" });
} else {
t.update({ title: "Failed to create post", type: "error" });
}Promise
Wrap a promise with sp.toast.promise(): it shows a loading toast, then swaps to the success or error state when the promise settles. The messages can be strings or functions of the resolved value.
sp.toast.promise(fetch("/api/posts", { method: "POST", body }), {
loading: "Creating post...",
success: "Post created",
error: (err) => `Failed: ${err.message}`,
});Duration
Control how long the toast stays (milliseconds, default 4000); 0 keeps it until dismissed.
<div class="flex flex-wrap justify-center gap-2">
<button
class="btn btn-outline"
onclick="sp.toast('Gone in 2 seconds', { duration: 2000 })"
>
Short (2s)
</button>
<button
class="btn btn-outline"
onclick="sp.toast('Staying for 10 seconds', { duration: 10000 })"
>
Long (10s)
</button>
<button
class="btn btn-outline"
onclick="sp.toast('I won\'t go away on my own', { duration: 0 })"
>
Persistent
</button>
</div>Position
Place the stack in any corner or centered at the top or bottom; default is bottom-right.
<div class="flex flex-wrap justify-center gap-2">
<button
class="btn btn-outline"
onclick="sp.toast('Top left', { position: 'top-left' })"
>
Top Left
</button>
<button
class="btn btn-outline"
onclick="sp.toast('Top center', { position: 'top-center' })"
>
Top Center
</button>
<button
class="btn btn-outline"
onclick="sp.toast('Top right', { position: 'top-right' })"
>
Top Right
</button>
<button
class="btn btn-outline"
onclick="sp.toast('Bottom left', { position: 'bottom-left' })"
>
Bottom Left
</button>
<button
class="btn btn-outline"
onclick="sp.toast('Bottom center', { position: 'bottom-center' })"
>
Bottom Center
</button>
<button
class="btn btn-outline"
onclick="sp.toast('Bottom right', { position: 'bottom-right' })"
>
Bottom Right
</button>
</div>Non-dismissible
Set dismissible: false to hide the close button; the toast leaves only when its duration expires.
Declarative toasts
Add data-sp-toast to any element to fire it as a toast and remove the element, with a plain string or a JSON config. New elements are picked up as they enter the DOM, so server-rendered redirects can queue flash messages with no JavaScript of their own.
<div data-sp-toast="Changes saved"></div>
<div
data-sp-toast='{"title":"Post created","type":"success","description":"Your post is now live."}'
></div>For example, in Laravel Blade:
@if (session('toast'))
<div data-sp-toast='@json(session("toast"))'></div>
@endifreturn redirect()->back()->with('toast', [
'title' => 'Post created',
'type' => 'success',
]);Toasts queued this way survive being rendered by React, Livewire, HTMX, or anything else that inserts nodes after page load. On Back/Forward navigation, cached flash markup does not re-fire.
Options
Pass options as the second argument to sp.toast().
JavaScript
Events
Lifecycle events fire on each toast element and bubble to document.
Methods
sp.toast() returns a toast instance; the module also exposes global helpers.