haxneeraj / laravel-livewire4-toaster
Elegant toast notifications for Laravel Livewire 4 + Alpine.js โ event-driven, configurable, zero dependencies.
Package info
github.com/haxneeraj/laravel-livewire4-toaster
pkg:composer/haxneeraj/laravel-livewire4-toaster
Requires
- php: ^8.1
- illuminate/contracts: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- livewire/livewire: ^3.0|^4.0
- orchestra/testbench: ^8.0|^9.0|^10.0
- phpunit/phpunit: ^10.0|^11.0
Suggests
- livewire/livewire: Required for Livewire component integration (^3.0|^4.0)
README
Elegant toast notifications for Laravel Livewire 4 + Alpine.js โ event-driven, configurable, zero external dependencies.
๐ธ Demo
โจ Features
- Trait-based API โ
$this->success('Saved!')in any Livewire component - Facade & Helper โ
Toast::error('Failed!')ortoast('success', 'Done')from controllers - Event-driven โ Livewire 4
dispatch()โ Alpinex-on:toast.window - Auto-dismiss with animated progress bar & pause-on-hover
- Queue mode โ show one toast at a time with automatic queue
- Duplicate handling โ suppress or replace identical toasts
- Configurable positions โ top-right, top-left, bottom-right, bottom-left, top-center, bottom-center
- Dark mode ready with Tailwind CSS
- Accessible โ
role="status",aria-live="polite" - Redirect support โ flash toasts to session, inject on next page load
- JavaScript API โ
window.Toast.success('Hello!')for frontend-only toasts - Publishable config & views โ full control when you need it
- Zero external dependencies โ no toastr.js, no notyf, just Alpine.js
๐ฆ Installation
1. Install via Composer
composer require haxneeraj/laravel-livewire4-toaster
The package auto-discovers its service provider and facade.
2. Publish Config (Optional)
php artisan vendor:publish --tag=toaster-config
This creates config/toaster.php where you can customize everything.
3. Add the Toast Hub to Your Layout
Place the toast-hub component in your main layout file, typically before </body>:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My App</title> @vite(['resources/css/app.css', 'resources/js/app.js']) @livewireStyles </head> <body> {{ $slot }} {{-- Toast notification container --}} <x-livewire-toaster::toast-hub /> @livewireScripts </body> </html>
That's it! You're ready to toast. ๐
๐ Usage
In Livewire Components (Toastable Trait)
The Toastable trait is the primary API for Livewire components:
<?php namespace App\Livewire; use Haxneeraj\LivewireToaster\Traits\Toastable; use Livewire\Component; class ProfileForm extends Component { use Toastable; public string $name = ''; public function save() { // ... validate and save ... $this->success('Profile updated successfully!', 'Saved'); } public function delete() { // ... delete logic ... $this->error('Profile has been deleted.', 'Deleted'); } public function archive() { $this->warning('Profile archived. You can restore it within 30 days.', 'Archived', [ 'duration' => 5000, ]); } public function notify() { $this->info('You have 3 unread messages.'); } public function customToast() { $this->toast('success', 'Custom positioned toast!', null, [ 'position' => 'bottom-left', 'duration' => 0, // sticky โ manual dismiss only ]); } public function render() { return view('livewire.profile-form'); } }
In Controllers (Toast Facade)
Use the Toast facade for controller-based workflows:
<?php namespace App\Http\Controllers; use Haxneeraj\LivewireToaster\Facades\Toast; use App\Http\Requests\UserRequest; class UserController extends Controller { public function store(UserRequest $request) { // ... create user ... Toast::success('User created successfully!', 'Welcome'); return redirect()->route('users.index'); } public function destroy(User $user) { $user->delete(); Toast::error('User has been removed.', 'Deleted'); return redirect()->route('users.index'); } }
Note: When using the facade with redirects, register the
InjectToastsmiddleware (see Middleware Setup).
Global Helper Function
// Quick toast toast('success', 'Item saved!'); // Get the manager and chain toast()->success('First toast')->error('Second toast'); // With options toast('warning', 'Low disk space!', 'Warning', ['duration' => 10000]);
From JavaScript
Include resources/js/toast.js in your build, or use the global window.Toast object (available when the hub is loaded):
// These work anywhere in your JS Toast.success('Saved!'); Toast.error('Something went wrong.', 'Error'); Toast.info('FYI...', null, { duration: 5000 }); Toast.warning('Careful!', 'Warning'); Toast.show('success', 'Custom type toast');
Or dispatch a raw event:
window.dispatchEvent(new CustomEvent('toast', { detail: { type: 'success', message: 'Hello from JS!', title: 'Custom Event', duration: 3000, } }));
In Alpine.js
<button type="button" x-data x-on:click="$dispatch('toast', { type: 'success', message: 'Button clicked!', title: 'Action' })" > Click me </button>
โ๏ธ Configuration
Publish the config file:
php artisan vendor:publish --tag=toaster-config
Configuration Reference
| Key | Type | Default | Description |
|---|---|---|---|
position |
string |
"top-right" |
Toast position. Options: top-right, top-left, bottom-right, bottom-left, top-center, bottom-center |
duration |
int |
3000 |
Auto-dismiss time in ms. 0 = sticky (manual dismiss only) |
closable |
bool |
true |
Show close (ร) button |
close_on_click |
bool |
true |
Click anywhere on toast to dismiss |
pause_on_hover |
bool |
true |
Pause auto-dismiss when hovering |
max_toasts |
int |
5 |
Max visible toasts. 0 = unlimited |
queue |
bool |
false |
Queue mode: show one at a time |
suppress_duplicates |
bool |
false |
Ignore duplicate type+message |
replace_duplicates |
bool |
false |
Replace existing duplicate |
show_icon |
bool |
true |
Show type-specific icon |
show_progress_bar |
bool |
true |
Show animated progress bar |
event_name |
string |
"toast" |
Browser event name |
styles |
array |
see below | Per-type Tailwind CSS classes |
Style Configuration
Each toast type has customizable Tailwind classes:
'styles' => [ 'success' => [ 'bg' => 'bg-emerald-50 dark:bg-emerald-950/80', 'border' => 'border-emerald-200 dark:border-emerald-800', 'text' => 'text-emerald-800 dark:text-emerald-200', 'icon_color' => 'text-emerald-500 dark:text-emerald-400', 'progress_bg' => 'bg-emerald-500', ], // ... error, warning, info ],
๐ง Middleware Setup
To use the Toast facade or toast() helper in controllers (especially with redirects), register the InjectToasts middleware.
Laravel 11+ (bootstrap/app.php)
use Haxneeraj\LivewireToaster\Http\Middleware\InjectToasts; return Application::configure(basePath: dirname(__DIR__)) ->withMiddleware(function (Middleware $middleware) { $middleware->web(append: [ InjectToasts::class, ]); }) ->create();
Laravel 10 (app/Http/Kernel.php)
protected $middlewareGroups = [ 'web' => [ // ... other middleware ... \Haxneeraj\LivewireToaster\Http\Middleware\InjectToasts::class, ], ];
The middleware:
- Collects pending toasts from
ToastManagerand session flash - Injects a
<script>tag before</body>that dispatcheswindowevents - The Alpine toast-hub catches these events and renders the toasts
๐จ Customizing Views
Publish the views to fully customize the toast markup:
php artisan vendor:publish --tag=toaster-views
This copies the Blade component to resources/views/vendor/livewire-toaster/.
Tailwind CSS Purge
Add the package views to your Tailwind content paths:
// tailwind.config.js module.exports = { content: [ './resources/views/**/*.blade.php', './vendor/haxneeraj/livewire4-toaster/resources/views/**/*.blade.php', // ... ], };
๐งช Testing
Running Tests
composer install vendor/bin/phpunit
Testing Your Toasts
When testing Livewire components that use the Toastable trait:
use Livewire\Livewire; public function test_profile_save_shows_success_toast() { Livewire::test(ProfileForm::class) ->set('name', 'John') ->call('save') ->assertDispatched('toast'); }
When testing controllers that use the facade:
use Haxneeraj\LivewireToaster\Facades\Toast; use Haxneeraj\LivewireToaster\ToastManager; public function test_user_creation_flashes_toast() { $this->post('/users', ['name' => 'John', 'email' => 'john@example.com']); $manager = app(ToastManager::class); // Toasts are flushed by middleware, so check session for redirect tests $this->assertNotNull(session('livewire_toaster')); }
๐ API Reference
Toastable Trait Methods
| Method | Signature | Description |
|---|---|---|
success() |
success(string $message, ?string $title = null, array $options = []) |
Green success toast |
error() |
error(string $message, ?string $title = null, array $options = []) |
Red error toast |
info() |
info(string $message, ?string $title = null, array $options = []) |
Blue info toast |
warning() |
warning(string $message, ?string $title = null, array $options = []) |
Amber warning toast |
toast() |
toast(string $type, string $message, ?string $title = null, array $options = []) |
Generic toast |
Toast Facade / Manager Methods
Same methods as above, plus:
| Method | Description |
|---|---|
toArray() |
Get all pending toasts |
flush() |
Get and clear pending toasts |
flashToSession() |
Flash toasts to session (for redirects) |
hasPending() |
Check if toasts are queued |
count() |
Count pending toasts |
Per-Toast Options
Pass as the $options array:
$this->success('Done!', 'OK', [ 'duration' => 5000, // Override duration (ms) 'position' => 'top-left', // Override position ]);
๐ Package Structure
livewire4-toaster/
โโโ config/
โ โโโ toaster.php # Published config
โโโ resources/
โ โโโ js/
โ โ โโโ toast.js # JS helper (window.Toast)
โ โโโ views/
โ โโโ components/
โ โโโ toast-hub.blade.php # Alpine.js toast container
โโโ src/
โ โโโ Facades/
โ โ โโโ Toast.php # Laravel facade
โ โโโ Http/
โ โ โโโ Middleware/
โ โ โโโ InjectToasts.php # Middleware for controller support
โ โโโ Traits/
โ โ โโโ Toastable.php # Livewire trait
โ โโโ ToastManager.php # Core toast collector
โ โโโ ToasterServiceProvider.php # Service provider
โ โโโ helpers.php # Global toast() helper
โโโ tests/
โ โโโ Unit/
โ โ โโโ InjectToastsMiddlewareTest.php
โ โ โโโ ServiceProviderTest.php
โ โ โโโ ToastManagerTest.php
โ โโโ TestCase.php
โโโ CHANGELOG.md
โโโ LICENSE
โโโ README.md
โโโ composer.json
โโโ phpunit.xml
๐ค Contributing
Contributions are welcome! Please:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing) - Open a Pull Request
Please ensure tests pass (vendor/bin/phpunit) and follow PSR-12 coding standards.
๐ License
The MIT License (MIT). See LICENSE for details.
๐ Credits
- Neeraj Saini (HaxNeeraj) โ Creator & Maintainer
- Built for the TALL Stack community
