| Install | |
|---|---|
composer require islamalsayed/laravel-toasts |
|
| Latest Version: | v1.0.7 |
| PHP: | ^8.0 |
A modern, elegant, and powerful Laravel package for toast notifications and confirmation dialogs with full Livewire support.
All features work perfectly with Arabic text and RTL direction.


composer require islamalsayed/laravel-toasts
# 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
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:
@include('vendor.toasts.toasts') in your <body> tag<head> or head.blade.php<head> or foot.blade.phpAdd 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
After publishing, customize config/toasts.php for more advanced settings.
toasts:injectAutomatically injects toast component references into your layout files.
php artisan toasts:inject
What it does:
@include('vendor.toasts.toasts') after <body> tag in master.blade.php<head> section<head> sectionOutput:
Blade snippet injected into master.blade.php
CSS snippet injected into head.blade.php
JS snippet injected into foot.blade.php
Command Features:
toasts:inject)// 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!');
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!
// 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?');
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();
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
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();
// 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 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>
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' => '❌'
]);
}
}
}
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');
}
}
<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>
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",
});
// 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>
// 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",
});
}
// 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('💾')```
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');
}
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' => '❌'
]);
}
}
public function save()
{
$this->validate();
User::create($this->form);
showToast('success', 'User added!')
->emoji('🎯')
->title('Added')
->pin();
}
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');
}
}
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());
}
}
# Run all tests
composer test
# Run specific test file
vendor/bin/phpunit tests/Feature/ToastFeatureTest.php
# Run with coverage
composer test-coverage
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']);
}
}
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!');
}
}
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']);
}
}
All features work perfectly with Arabic text and RTL direction.

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]
| 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 |
| 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 |
| 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');
use IslamAlsayed\LaravelToasts\Facades\Toast;
Toast::success($message);
Toast::error($message);
Toast::warning($message);
Toast::info($message);
Toast::confirm($message);
| Command | Description |
|---|---|
toasts:inject |
Inject toast references into layout files |
Usage Examples:
# Initial setup - inject toasts into layouts
php artisan toasts:inject
We welcome contributions! Here's how you can help:
git checkout -b feature/amazing-featuregit commit -m 'Add amazing feature'git push origin feature/amazing-feature# Clone the repository
git clone https://github.com/IslamAlsayed/laravel-toasts.git
cd laravel-toasts
# Install dependencies
composer install
# Run tests
composer test
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
This package is open-sourced software licensed under the MIT license.
See CHANGELOG.md for recent changes.
🚀 Built for developers who want elegant, expressive, and flexible notifications in Laravel applications.