Looking to hire Laravel developers? Try LaraJobs

laravel-livewire4-toaster maintained by haxneeraj

Description
Elegant toast notifications for Laravel Livewire 4 + Alpine.js — event-driven, configurable, zero dependencies.
Author
Last update
2026/03/31 20:38 (dev-main)
License
Downloads
1

Comments
comments powered by Disqus

🍞 Livewire4 Toaster

Latest Version on Packagist License: MIT PHP Version

Elegant toast notifications for Laravel Livewire 4 + Alpine.js — event-driven, configurable, zero external dependencies.

Toast Preview Toast Preview Toast Preview Toast Preview

📸 Demo

Laravel Livewire4 Toaster Demo


✨ Features

  • Trait-based API$this->success('Saved!') in any Livewire component
  • Facade & HelperToast::error('Failed!') or toast('success', 'Done') from controllers
  • Event-driven — Livewire 4 dispatch() → Alpine x-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
  • Accessiblerole="status", aria-live="polite"
  • Redirect support — flash toasts to session, inject on next page load
  • JavaScript APIwindow.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 InjectToasts middleware (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:

  1. Collects pending toasts from ToastManager and session flash
  2. Injects a <script> tag before </body> that dispatches window events
  3. 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:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing)
  5. 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