islamalsayed/laravel-toasts

Modern, elegant toast notifications and confirmation dialogs for Laravel with full Livewire 3.x support, emoji integration, and RTL compatibility

Installs: 9

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/islamalsayed/laravel-toasts

v1.0.7 2025-11-08 21:19 UTC

This package is auto-updated.

Last update: 2025-12-08 21:31:23 UTC


README

License Laravel Livewire

A modern, elegant, and powerful Laravel package for toast notifications and confirmation dialogs with full Livewire support.

โœจ Features

  • ๐ŸŽจ Multiple toast types: Success โœ…, Error โŒ, Danger โ›”, Warning โš ๏ธ, Info โ„น๏ธ
  • ๐Ÿท๏ธ Two display modes: Standard (with titles) and Message-only (without titles)
  • ๐ŸŽญ Custom icons & emojis with Font Awesome support
  • ๐Ÿ“Œ Pin support for persistent notifications
  • โฑ๏ธ Configurable duration and display positionsุด
  • ๐ŸŒ RTL/LTR support with full Arabic compatibility
  • ๐ŸŽฏ Livewire 3.x integration with event dispatching
  • โšก JavaScript API for client-side notifications
  • ๐ŸŽฌ Smooth animations with customizable timing
  • ๐Ÿ”˜ Action buttons with custom callbacks
  • ๐Ÿ›ก๏ธ Interactive confirmation dialogs
  • ๐Ÿงช Fully tested with PHPUnit
  • ๐Ÿ“ฆ Easy installation with granular asset publishing

๐ŸŒ RTL & Arabic Support

All features work perfectly with Arabic text and RTL direction.

RTL

RTL Example

LTR

LTR Example

๐Ÿ“ฆ Installation

1. Install via Composer

composer require islamalsayed/laravel-toasts

2. Publish Assets

# Publish everything (recommended for first-time setup)
php artisan vendor:publish --tag=toast-all

# Or publish components individually:
php artisan vendor:publish --tag=toast-config    # Configuration file
php artisan vendor:publish --tag=toast-views     # Blade templates
php artisan vendor:publish --tag=toast-css       # CSS styles
php artisan vendor:publish --tag=toast-js        # JavaScript files
php artisan vendor:publish --tag=toast-webfonts  # Font Awesome fonts

3. Inject Toast View

Run the inject command to add the toast component to your master layout:

php artisan toasts:inject

This will automatically inject the following into your layout files:

  • Blade snippet: @include('vendor.toasts.toasts') in your <body> tag
  • CSS assets: FontAwesome and Toasts styles in <head> or head.blade.php
  • JavaScript: Toasts scripts in <head> or foot.blade.php

โš™๏ธ Configuration

Environment Variables

Add these settings to your .env file:

# Animation timing
TOASTS_MOVE=enable                   # Enable/disable toast movement
TOASTS_ENTER_TIME=0.3s               # Entry animation duration
TOASTS_EXIT_TIME=0.3s                # Exit animation duration
TOASTS_VISIBLE_TIME=4s               # How long toast stays visible
TOASTS_START_DELAY_TIME=0.5s         # Delay before showing toast

# Confirmation defaults
TOASTS_CONFIRM_PIN=true              # Keep confirms pinned by default

# Display settings
TOASTS_DEFAULT_DIR=ltr               # Text direction: ltr or rtl
TOASTS_DEFAULT_POSITION=top          # Toast position: top, right
TOASTS_DEFAULT_THEME=info            # Default theme: success, error, warning, info

# Default messages
TOASTS_DEFAULT_MESSAGE=Hello there!
TOASTS_DEFAULT_TITLE=Notification

# Confirmation texts
TOASTS_CONFIRM_TITLE=Please Confirm
TOASTS_CONFIRM_MESSAGE=Do you really want to proceed?
TOASTS_CONFIRM_TEXT=Sure
TOASTS_CANCEL_TEXT=Cancel

Configuration File

After publishing, customize config/toasts.php for more advanced settings.

๏ฟฝ๏ธ Artisan Commands

toasts:inject

Automatically injects toast component references into your layout files.

php artisan toasts:inject

What it does:

  • Adds @include('vendor.toasts.toasts') after <body> tag in master.blade.php
  • Adds CSS links (FontAwesome + Toasts) in <head> section
  • Adds JavaScript module in footer or <head> section
  • Creates proper comments for easy identification

Output:

Blade snippet injected into master.blade.php
CSS snippet injected into head.blade.php
JS snippet injected into foot.blade.php

Command Features:

  • โœ… Smart pattern matching (handles various formatting styles)
  • โœ… Safe operation (only removes toasts-related code)
  • โœ… Informative feedback (clear success/skip messages)
  • โœ… Clean output (removes extra blank lines)
  • โœ… Non-destructive (can be reversed with toasts:inject)

๏ฟฝ๐Ÿš€ Basic Usage

Simple Toasts

// Using helper functions
showToastSuccess('User created successfully!');
showToastError('Failed to delete item');
showToastWarning('Please check your input');
showToastInfo('New update available');

// Generic helper
showToast('success', 'Operation completed!');

Message-Only Toasts (Without Titles)

For cleaner, minimal toasts without type titles, use the message variants:

// Success message without "Success" title
showToastSuccessMessage('User created successfully!');

// Error message without "Error" title
showToastErrorMessage('Failed to delete item');

// Danger message without "Danger" title
showToastDangerMessage('Critical error occurred!');

// Warning message without "Warning" title
showToastWarningMessage('Please check your input');

// Info message without "Info" title
showToastInfoMessage('New update available');

Difference between standard and message variants:

// Standard toast (with title)
showToastSuccess('User created!');
// Displays: [โœ… Success] User created!

// Message-only toast (no title)
showToastSuccessMessage('User created!');
// Displays: [โœ…] User created!

With Session Flash

// Automatic toast from session flash
return redirect()->back()->with('success', 'Data saved!');
return redirect()->route('dashboard')->withError('Access denied');

// All these work automatically:
session()->flash('success', 'Item created!');
session()->flash('error', 'Validation failed!');
session()->flash('warning', 'Action required!');
session()->flash('info', 'Did you know?');

Using Toast Facade

use IslamAlsayed\LaravelToasts\Facades\Toast;

Toast::success('Record saved!');
Toast::error('Something went wrong')->icon('bomb');
Toast::warning('Check your email')->emoji('๐Ÿ“ง');
Toast::info('System maintenance at 10PM')->pin();

โœจ Advanced Usage

Chaining Methods

showToast('success', 'User profile updated!')
    ->title('Success')           // Custom title
    ->emoji('๐ŸŽ‰')               // Add emoji (replaces icon)
    ->icon('user-check')        // Font Awesome icon
    ->pin()                     // Make sticky (won't auto-hide)
    ->duration('5s')            // Custom duration (2s, 500ms, 1m)
    ->position('top')           // Position: top, right
    ->dir('rtl')                // Direction: rtl or ltr
    ->theme('success');         // Theme: success, error, warning, info

With Action Buttons

showToast('info', 'New message received')
    ->title('Notification')
    ->emoji('๐Ÿ“ฌ')
    ->withAction('View', route('messages.show', 1))
    ->withAction('Mark as Read', '/messages/1/read');

Toast::warning('Unsaved changes detected')
    ->withAction('Save Now', '/save')
    ->withAction('Discard', '/discard')
    ->pin();

Confirmation Dialogs

// Simple confirmation
addConfirm('Are you sure you want to delete this?');

// Advanced confirmation
addConfirm('Permanently delete this user?')
    ->title('Confirm Deletion')
    ->emoji('โš ๏ธ')
    ->link(route('users.destroy', $user->id))
    ->onConfirm('Yes, Delete')
    ->onCancel('Cancel')
    ->target('_self');

// Type-specific confirmations
addConfirmSuccess('Save changes?');
addConfirmError('Delete permanently?');
addConfirmWarning('Overwrite existing file?');
addConfirmInfo('Mark all as read?');

๐ŸŽฏ Livewire Integration

Event Dispatching

Livewire components can dispatch toast events from the frontend:

// In your Livewire component
<button wire:click="$dispatch('toast', {
    type: 'success',message: 'Action completed!'
})">
    Click Me
</button>

// With full options
<button wire:click="$dispatch('toast', {
    type: 'warning',
    message: 'Are you sure?',
    title: 'Confirmation',
    emoji: 'โš ๏ธ',
    pin: true,
    duration: '3s'
})">
    Show Toast
</button>

Using HandlesCrudSafely Trait

The package provides a trait for safe CRUD operations with automatic toast notifications:

namespace App\Livewire;

use Livewire\Component;

class Users extends Component
{

    public function destroy($id)
    {
        // Default toast notification
        $user = User::find($id);
        if ($user) {
            $user->delete();
            $this->dispatch('show-toast', [
                'type' => 'success',
                'message' => 'Users deleted successfully.',
                'title' => 'Success',
                'emoji' => 'โœ…'
            ]);
        } else {
            $this->dispatch('show-toast', [
                'type' => 'error',
                'message' => 'Users not found.',
                'title' => 'Error',
                'emoji' => 'โŒ'
            ]);
        }
    }
}

Complete Livewire Example

namespace App\Livewire;

use Livewire\Component;
use App\Models\User;

class UserManager extends Component
{
    public $name;
    public $email;

    public function save()
    {
        $this->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users',
        ]);

        try {
            User::create([
                'name' => $this->name,
                'email' => $this->email,
            ]);

            // Success toast
            showToast('success', 'User created successfully!')
                ->emoji('๐Ÿ‘ค')
                ->title('Success')
                ->withAction('View Users', route('users.index'));

            $this->reset(['name', 'email']);

        } catch (\Exception $e) {
            // Error toast
            showToast('error', 'Failed to create user: ' . $e->getMessage())
                ->emoji('โŒ')
                ->title('Error')
                ->pin();
        }
    }

    public function render()
    {
        return view('livewire.user-manager');
    }
}

Livewire Blade Template

<div>
    <form wire:submit="save">
        <input type="text" wire:model="name" placeholder="Name">
        @error('name') <span class="error">{{ $message }}</span> @enderror

        <input type="email" wire:model="email" placeholder="Email">
        @error('email') <span class="error">{{ $message }}</span> @enderror

        <button type="submit">Save User</button>
    </form>

    {{-- Dispatch toast from frontend --}}
    <button wire:click="$dispatch('show-toast', {
        type: 'info',
        message: 'Form ready for input',
        emoji: 'โ„น๏ธ'
    })">
        Show Info
    </button>
</div>

๐Ÿ–ฅ๏ธ JavaScript Usage

Browser Console

Test toasts directly in the browser console:

// Simple toast
window.showToast({ type: "success", message: "It works!" });

// Advanced toast
window.showToast({
    type: "error",
    message: "Something went wrong",
    title: "Error",
    emoji: "๐Ÿ’ฅ",
    pin: true,
    duration: "5s",
});

// Confirmation dialog
window.showToastConfirm({
    type: "warning",
    message: "Are you sure?",
    onconfirmLink: "/delete/123",
    title: "Confirm",
    emoji: "โš ๏ธ",
    onConfirm: "Yes",
    onCancel: "No",
});

Custom JavaScript Events

// Dispatch from vanilla JavaScript
document.getElementById('myButton').addEventListener('click', function() {
    window.showToast({
        type: 'success',
        message: 'Button clicked!'
        emoji: '๐Ÿ–ฑ๏ธ',
        duration: '2s'
    });
});

// With Livewire Alpine.js
<button @click="window.showToast({ type: 'info', message: 'Alpine works!', emoji: 'โšก' })">
    Click Me
</button>

From External JavaScript Files

// In your app.js or custom script
export function showSuccessToast(message) {
    window.showToast({
        type: "success",
        message: message,
        title: "Success",
        emoji: "โœ…",
        duration: "3s",
    });
}

export function confirmDelete(url) {
    window.showToastConfirm({
        type: "info",
        message: "Are you sure you want to delete this?",
        onconfirmLink: url,
        title: "Confirm Deletion",
        emoji: "๐Ÿ—‘๏ธ",
        onConfirm: "Delete",
        onCancel: "Cancel",
    });
}

Available Emojis:

// Success
->emoji('โœ…') ->emoji('๐ŸŽ‰') ->emoji('๐Ÿ‘') ->emoji('โœ”๏ธ')

// Error
->emoji('โŒ') ->emoji('โ›”') ->emoji('๐Ÿšซ') ->emoji('๐Ÿ’ฅ')

// Warning
->emoji('โš ๏ธ') ->emoji('โšก') ->emoji('๐Ÿ””') ->emoji('๐Ÿ“ข')

// Info
->emoji('โ„น๏ธ') ->emoji('๐Ÿ’ก') ->emoji('๐Ÿ“Œ') ->emoji('๐Ÿ”')

// Delete
->emoji('๐Ÿ—‘๏ธ') ->emoji('๐Ÿšฎ') ->emoji('โŒ')

// Actions
->emoji('๐Ÿ‘๏ธ') ->emoji('โœ๏ธ') ->emoji('๐Ÿ“') ->emoji('๐Ÿ’พ')```

Real-World Examples:

Example 1: After creating a record

public function store(Request $request)
{
    $user = User::create($request->all());

    showToast('success', 'User created successfully!')
        ->title('Success')
        ->emoji('๐Ÿ‘ค')
        ->withAction('View Profile', route('users.show', $user->id));

    return redirect()->route('users.index');
}

Example 2: Before deleting (your current use case)

public function destroy($id)
{
    // Default toast notification
    $user = User::find($id);
    if ($user) {
        $user->delete();
        $this->dispatch('show-toast', [
            'type' => 'success',
            'message' => 'Users deleted successfully.',
            'title' => 'Success',
            'emoji' => 'โœ…'
        ]);
    } else {
        $this->dispatch('show-toast', [
            'type' => 'error',
            'message' => 'Users not found.',
            'title' => 'Error',
            'emoji' => 'โŒ'
        ]);
    }
}

Example 3: Livewire component

public function save()
{
    $this->validate();

    User::create($this->form);

    showToast('success', 'User added!')
        ->emoji('๐ŸŽฏ')
        ->title('Added')
        ->pin();
}

Example 4: Multiple toasts at once

public function import()
{
    $success = 10;
    $failed = 2;

    if ($success > 0) {
        showToast('success', "$success items imported successfully")
            ->emoji('โœ…')
            ->duration(3000);
    }

    if ($failed > 0) {
        showToast('warning', "$failed items failed to import")
            ->emoji('โš ๏ธ')
            ->withAction('View Log', '/import/log');
    }
}

Example 5: Using message-only helpers for cleaner notifications

public function updateProfile(Request $request)
{
    $user = auth()->user();
    $user->update($request->all());

    // Clean message without "Success" title
    showToastSuccessMessage('Profile updated successfully!');

    return redirect()->back();
}

public function validateForm($data)
{
    if (empty($data['email'])) {
        // Clean error without "Error" title
        showToastErrorMessage('Email is required');
        return false;
    }

    if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
        // Clean warning without "Warning" title
        showToastWarningMessage('Please enter a valid email address');
        return false;
    }

    // Clean info without "Info" title
    showToastInfoMessage('Validation passed');
    return true;
}

public function sendNotification()
{
    try {
        // Send notification logic

        // Success with title for important actions
        showToastSuccess('Notification sent to all users!')
            ->emoji('๐Ÿ“ง')
            ->pin();
    } catch (\Exception $e) {
        // Danger message for critical errors
        showToastDangerMessage('Failed to send notification: ' . $e->getMessage());
    }
}

๐Ÿงช Testing

Running Tests

# Run all tests
composer test

# Run specific test file
vendor/bin/phpunit tests/Feature/ToastFeatureTest.php

# Run with coverage
composer test-coverage

Unit Tests Example

namespace IslamAlsayed\LaravelToasts\Tests\Unit;

use IslamAlsayed\LaravelToasts\ToastFactory;
use IslamAlsayed\LaravelToasts\Tests\TestCase;

class ToastFactoryTest extends TestCase
{
    public function test_can_create_success_toast()
    {
        $toast = ToastFactory::success('User created!');

        $this->assertEquals('success', $toast->type);
        $this->assertEquals('User created!', $toast->message);
    }

    public function test_can_chain_methods()
    {
        $toast = ToastFactory::error('Failed!')
            ->title('Error')
            ->emoji('โŒ')
            ->pin()
            ->duration('5s');

        $this->assertEquals('Error', $toast->title);
        $this->assertEquals('โŒ', $toast->emoji);
        $this->assertTrue($toast->pin);
        $this->assertEquals('5s', $toast->duration);
    }

    public function test_can_add_actions()
    {
        $toast = ToastFactory::info('New message')
            ->withAction('View', '/messages')
            ->withAction('Dismiss', '#');

        $this->assertCount(2, $toast->actions);
        $this->assertEquals('View', $toast->actions[0]['label']);
        $this->assertEquals('/messages', $toast->actions[0]['url']);
    }
}

Feature Tests Example

namespace IslamAlsayed\LaravelToasts\Tests\Feature;

use IslamAlsayed\LaravelToasts\Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class ToastFeatureTest extends TestCase
{
    use RefreshDatabase;

    public function test_toast_is_added_to_session()
    {
        showToastSuccess('Test message');

        $toasts = session('toasts');

        $this->assertNotNull($toasts);
        $this->assertCount(1, $toasts);
        $this->assertEquals('success', $toasts[0]->type);
        $this->assertEquals('Test message', $toasts[0]->message);
    }

    public function test_multiple_toasts_can_be_queued()
    {
        showToastSuccess('First');
        showToastError('Second');
        showToastWarning('Third');

        $toasts = session('toasts');

        $this->assertCount(3, $toasts);
    }

    public function test_redirect_with_flash_creates_toast()
    {
        $response = $this->get('/test-redirect');

        $response->assertSessionHas('success', 'Operation completed!');
    }
}

Testing Livewire Integration

namespace Tests\Feature\Livewire;

use App\Livewire\UserManager;
use Livewire\Livewire;
use Tests\TestCase;

class UserManagerTest extends TestCase
{
    public function test_success_toast_on_user_creation()
    {
        Livewire::test(UserManager::class)
            ->set('name', 'John Doe')
            ->set('email', 'john@example.com')
            ->call('save')
            ->assertDispatched('toast');

        $toasts = session('toasts');
        $this->assertNotNull($toasts);
        $this->assertEquals('success', $toasts[0]->type);
    }

    public function test_error_toast_on_validation_failure()
    {
        Livewire::test(UserManager::class)
            ->set('name', '')
            ->set('email', 'invalid-email')
            ->call('save')
            ->assertHasErrors(['name', 'email']);
    }
}

๐ŸŒ RTL & Arabic Support

All features work perfectly with Arabic text and RTL direction.

RTL Example - Confirm RTL Example - Success RTL Example - Error RTL Example - Warning RTL Example - Info

๐Ÿงฉ API Reference

Toast Properties

public $type;        // success, error, info, warning
public $message;     // Toast message text
public $title;       // Optional toast title
public $emoji;       // Emoji next to title
public $icon;        // Font Awesome icon name
public $duration;    // Display duration (e.g., 2s, 500ms, 1m)
public $position;    // Position: top, right
public $pin;         // If true, toast remains until manually closed
public $theme;       // Theme color: success, error, etc.
public $dir;         // Text direction: ltr or rtl
public $confirm;     // Confirm button label
public $cancel;      // Cancel button label
public $actions;     // Array of actions [label + url]

Helper Functions

Standard Toast Helpers (With Titles)

Function Description
showToast($type, $message) Create a generic toast
showToastSuccess($message) Create success toast with title
showToastError($message) Create error toast with title
showToastDanger($message) Create danger toast with title
showToastWarning($message) Create warning toast with title
showToastInfo($message) Create info toast with title

Message-Only Helpers (Without Titles)

Function Description
showToastSuccessMessage($message) Success toast without "Success" title
showToastErrorMessage($message) Error toast without "Error" title
showToastDangerMessage($message) Danger toast without "Danger" title
showToastWarningMessage($message) Warning toast without "Warning" title
showToastInfoMessage($message) Info toast without "Info" title

Confirmation Helpers

Function Description
addConfirm($message) Create confirmation dialog
addConfirmSuccess($message) Create success confirmation
addConfirmError($message) Create error confirmation
addConfirmWarning($message) Create warning confirmation
addConfirmInfo($message) Create info confirmation

Usage Example:

// With title (default)
showToastSuccess('User created successfully!');
// Output: [โœ… Success] User created successfully!

// Without title (message only)
showToastSuccessMessage('User created successfully!');
// Output: [โœ…] User created successfully!

// Confirmation dialog
addConfirmError('Delete this user?')
    ->link(route('users.destroy', $user->id))
    ->onConfirm('Yes, Delete')
    ->onCancel('Cancel');

Facade Methods

use IslamAlsayed\LaravelToasts\Facades\Toast;

Toast::success($message);
Toast::error($message);
Toast::warning($message);
Toast::info($message);
Toast::confirm($message);

Artisan Commands

Command Description
toasts:inject Inject toast references into layout files

Usage Examples:

# Initial setup - inject toasts into layouts
php artisan toasts:inject

๏ฟฝ Future Enhancements

  • Toast queueing system (stacked notifications)
  • Audio alerts on confirmations
  • Persistent toasts across page reloads
  • Built-in animation presets (slide, fade, bounce, zoom)
  • Dark mode support
  • Custom toast templates
  • WebSocket integration for real-time notifications

๐Ÿค Contributing

We welcome contributions! Here's how you can help:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit your changes: git commit -m 'Add amazing feature'
  4. Push to the branch: git push origin feature/amazing-feature
  5. Open a Pull Request

Development Setup

# Clone the repository
git clone https://github.com/IslamAlsayed/laravel-toasts.git
cd laravel-toasts

# Install dependencies
composer install

# Run tests
composer test

Code Style

This project follows PSR-12 coding standards. Please ensure your code adheres to these standards before submitting.

# Check code style
composer phpcs

# Fix code style
composer phpcbf

๐Ÿ“„ License

This package is open-sourced software licensed under the MIT license.

๐Ÿ“ฌ Support & Contact

๐Ÿ™ Acknowledgments

  • Built with โค๏ธ for the Laravel community
  • Inspired by modern notification libraries
  • Font Awesome for the amazing icons

๐Ÿ“ Changelog

See CHANGELOG.md for recent changes.

๐Ÿš€ Built for developers who want elegant, expressive, and flexible notifications in Laravel applications.