atomcoder / laravel-toasty
Pines-inspired toast notifications for Laravel Blade and Livewire.
Requires
- php: ^8.1
- illuminate/contracts: ^10.0|^11.0|^12.0|^13.0
- illuminate/session: ^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
- illuminate/view: ^10.0|^11.0|^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^8.22|^9.0|^10.0
- phpunit/phpunit: ^10.5|^11.0
Suggests
- livewire/livewire: Required if you want to dispatch toasts directly from Livewire 3 or 4 components.
README
Toast notifications for Laravel Blade, Livewire, Alpine, and JavaScript.
Laravel Toasty works with:
- standard Laravel controllers and redirects
- Blade layouts
- Alpine
- Livewire
- plain browser JavaScript
The package uses namespaced APIs so it does not clash with Flux toasts or generic toast() helpers.
See CHANGELOG.md for release history.
What You Get
<x-laravel-toasty::toasts />Blade component@laravelToastyBlade directivelaravel_toasty()helperLaravelToastyfacade alias- Livewire support through the
InteractsWithToaststrait window.LaravelToastyJavaScript API- bundled CSS inside the package, so Tailwind setup is not required
Requirements
- PHP
8.1+ - Laravel
10+ - Alpine.js
3+
Livewire is optional.
Installation
Install with Composer:
composer require atomcoder/laravel-toasty
Publish the config if you want to change defaults:
php artisan vendor:publish --tag=laravel-toasty-config
Publish the views only if you want to override the package markup:
php artisan vendor:publish --tag=laravel-toasty-views
You do not need to:
- install Tailwind for this package
- add vendor Blade paths to Tailwind
content - import a separate package stylesheet
Quick Start
1. Render the toast stack once
Add this near the end of your main layout, usually before </body>:
<x-laravel-toasty::toasts />
Or:
@laravelToasty
2. Make sure Alpine is loaded
If your app already has Alpine, you are done.
If not:
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
3. Trigger a toast
Normal Laravel request:
laravel_toasty()->success('Profile updated');
Livewire immediate toast:
$this->dispatchLaravelToastySuccess('Profile updated');
Browser JavaScript:
<script> window.LaravelToasty.notify('Profile updated'); </script>
How It Works
Laravel Toasty supports two main server-side flows:
Session toast
Use this in controllers, middleware, or normal Laravel request code:
laravel_toasty()->success('Saved');
That stores the toast in the session, and the next page render shows it.
Immediate Livewire toast
Use this inside a Livewire component action:
$this->dispatchLaravelToastySuccess('Saved');
That dispatches a browser event immediately through the current component, so the user sees the toast without leaving the page.
Main APIs
Helper
laravel_toasty()
Facade
LaravelToasty::success('Saved');
Blade
<x-laravel-toasty::toasts /> @laravelToasty
JavaScript
window.LaravelToasty.notify('Saved'); window.LaravelToasty.layout('expanded');
Full Usage Examples
Example 1: Standard controller redirect
Use this when the request ends with a redirect.
<?php namespace App\Http\Controllers; use App\Http\Requests\ProfileRequest; class ProfileController { public function update(ProfileRequest $request) { $request->user()->update($request->validated()); laravel_toasty()->success( 'Profile updated', 'Your account details were saved successfully.' ); return redirect()->route('profile.edit'); } }
Example 2: Controller with custom options
public function destroy(Project $project) { $project->delete(); laravel_toasty()->danger( 'Project deleted', 'This action cannot be undone.', [ 'position' => 'bottom-right', 'duration' => 6000, 'layout' => 'expanded', ] ); return redirect()->route('projects.index'); }
Example 3: Facade usage
<?php namespace App\Http\Controllers; use LaravelToasty; class DashboardController { public function __invoke() { LaravelToasty::info('Welcome back'); return view('dashboard'); } }
Example 4: Livewire with the trait
<?php namespace App\Livewire; use Livewire\Component; use Atomcoder\Toasty\Concerns\InteractsWithToasts; class EditProfile extends Component { use InteractsWithToasts; public string $name = ''; public function save(): void { auth()->user()->update([ 'name' => $this->name, ]); $this->dispatchLaravelToastySuccess( 'Profile updated', 'Your changes were saved immediately.', ['position' => 'top-right'] ); } public function render() { return view('livewire.edit-profile'); } }
Example 5: Livewire redirect
If your Livewire action redirects away, use the normal session helper:
public function createWorkspace() { $workspace = auth()->user()->workspaces()->create([ 'name' => $this->name, ]); laravel_toasty()->success( 'Workspace created', 'You have been taken to your new workspace.' ); return $this->redirect(route('workspaces.show', $workspace)); }
Example 6: More Livewire trait methods
The trait gives you dedicated immediate-dispatch methods:
$this->dispatchLaravelToastyInfo('Draft saved'); $this->dispatchLaravelToastyWarning('Storage almost full'); $this->dispatchLaravelToastyDanger('Delete failed', 'Please try again.'); $this->dispatchLaravelToastyLike('Post liked'); $this->dispatchLaravelToastyBell('Reminder set', 'We will notify you tomorrow.');
Example 7: Blade and Alpine button
<button type="button" x-on:click="window.LaravelToasty.notify('Saved from Alpine', { type: 'success', description: 'The client-side action completed.', position: 'bottom-right' })" > Save </button>
Example 8: Plain JavaScript
<script> window.LaravelToasty.notify('Deployment complete', { type: 'success', description: 'Everything is live.', position: 'top-right', duration: 5000, }); </script>
Example 9: HTML toast
Only use trusted HTML.
laravel_toasty()->html(<<<'HTML' <div style="padding: 1rem;"> <strong>Deployment complete</strong> <div style="margin-top: .5rem; opacity: .8;"> Version 2.0.0 is now live. </div> </div> HTML, [ 'position' => 'bottom-right', 'duration' => 10000, ]);
Example 10: Multiple toasts in one request
laravel_toasty()->success('Project created'); laravel_toasty()->info('Invite your team'); laravel_toasty()->warning('Remember to configure billing');
Example 11: Inspecting and clearing queued session toasts
This only works with the session queue, not the already-mounted browser stack.
$toasts = laravel_toasty()->all(); if (count($toasts) > 5) { laravel_toasty()->clear(); }
Available Methods
These methods are available through laravel_toasty() and LaravelToasty:
flash($message, $options = [])success($message, $description = null, $options = [])info($message, $description = null, $options = [])warning($message, $description = null, $options = [])danger($message, $description = null, $options = [])like($message, $description = null, $options = [])bell($message, $description = null, $options = [])html($html, $options = [])
These methods are only useful for the session-backed queue:
all()clear()
Toast Options
Every toast accepts these options:
| Option | Type | Description |
|---|---|---|
description |
`string | null` |
type |
default, success, info, warning, danger, like, bell |
Visual style and icon |
position |
top-left, top-center, top-right, bottom-left, bottom-center, bottom-right |
Stack location |
duration |
int |
Auto-dismiss time in milliseconds. Use 0 to keep it open |
closeable |
bool |
Whether the close button is shown |
layout |
default, expanded |
Stack layout mode |
html |
`string | null` |
JavaScript API
The package registers:
window.LaravelToasty window.laravelToasty
Available methods:
window.LaravelToasty.notify(message, options = {})window.LaravelToasty.toast(message, options = {})window.LaravelToasty.layout(layout = 'expanded', eventName = null)window.LaravelToasty.setLayout(layout = 'expanded', eventName = null)
Example:
<script> window.LaravelToasty.notify('Warning', { type: 'warning', description: 'Storage is almost full.', duration: 0, closeable: true, }); window.LaravelToasty.layout('expanded'); </script>
Blade Component Props
You can override defaults directly on the component:
<x-laravel-toasty::toasts position="bottom-right" layout="expanded" :duration="7000" :padding-between-toasts="20" :closeable="false" :z-index="120" theme="toasty" />
Useful props:
positionlayoutdurationpadding-between-toastsevent-namelayout-event-namecloseablez-indexthemestyleslegacy-aliases
Configuration
Publish the config:
php artisan vendor:publish --tag=laravel-toasty-config
This creates:
config/laravel_toasty.php
Main config keys:
event_namelayout_event_namesession_keylegacy_aliasespositionlayoutdurationpadding_betweencloseablez_indexthemethemesstyles
Example:
return [ 'event_name' => 'laravel-toasty:notify', 'layout_event_name' => 'laravel-toasty:layout', 'session_key' => 'laravel_toasty.toasts', 'legacy_aliases' => false, 'position' => 'top-center', 'layout' => 'default', 'duration' => 4000, 'padding_between' => 15, 'closeable' => true, 'z_index' => 99, 'theme' => 'pines', 'styles' => [], ];
Themes
Built-in themes:
pinestoastyglass
Change the theme:
'theme' => 'toasty',
Override part of a theme:
'styles' => [ 'max_width' => '30rem', 'base' => [ 'radius' => '1.25rem', ], 'types' => [ 'success' => [ 'background' => 'linear-gradient(135deg, #166534, #14532d)', ], ], ],
You can also pass styles directly to the Blade component for per-page overrides.
Customizing the View
Publish the views:
php artisan vendor:publish --tag=laravel-toasty-views
Published path:
resources/views/vendor/laravel-toasty/components/toasts.blade.php
Important: published vendor views override future package view updates until you remove or update them yourself.
Migration From Older Versions
If you are upgrading from the older generic naming:
| Old | New |
|---|---|
toasty() |
laravel_toasty() |
@toasty |
@laravelToasty |
<x-toasty::toasts /> |
<x-laravel-toasty::toasts /> |
window.Toasty |
window.LaravelToasty |
window.toast(...) |
window.LaravelToasty.notify(...) |
If needed, you can temporarily enable:
'legacy_aliases' => true,
Troubleshooting
Toasts do not show at all
Check:
- Alpine is loaded
- the stack is rendered once in your layout
- your layout includes
<x-laravel-toasty::toasts />
Livewire action runs but no toast appears
If you stay on the same page, use:
$this->dispatchLaravelToastySuccess('Saved');
with the InteractsWithToasts trait on the component.
If you redirect away, use:
laravel_toasty()->success('Saved');
You still see old markup or old errors after updating
Look for stale published views:
rg -n "window\\.LaravelToastyComponent|window\\.ToastyComponent" resources/views vendor
Then clear caches:
php artisan optimize:clear composer clear-cache
all() and clear() do not affect Livewire toasts already visible on screen
That is expected. They only work with the server-side session queue.
Queue jobs or background jobs
Untargeted helper calls are session-backed, so they are meant for the web request lifecycle, not queue workers.
Testing
Run the package tests with:
composer test
Credits
- DevDojo Pines Toast for the original interaction inspiration
License
MIT
