jeremykenedy/laravel-toast
Powerful, highly configurable toast notifications for Laravel with 56 animations, 19 per-toast props, RTL support, dark mode, and full CSS/frontend framework parity across Tailwind, Bootstrap, Livewire, Vue, React, and Svelte.
Installation:
composer require jeremykenedy/laravel-toast
Publish the config file (optional but recommended for customization):
php artisan vendor:publish --provider="JeremyKenedy\LaravelToast\ToastServiceProvider" --tag="config"
First Toast:
use JeremyKenedy\LaravelToast\Facades\Toast;
// Basic success toast
Toast::success('Operation completed!');
// With title and duration
Toast::info('New message', 'You have a new notification', 5);
Blade Integration:
Add the toast directive to your layout file (e.g., resources/views/layouts/app.blade.php):
@toast
Upgrading to v3.1.0 (from v3.0.0/v3.0.1):
composer update jeremykenedy/laravel-toast
php artisan view:clear
No required config changes. If you published toast-views, merge the new data-toast-type / data-toast-part attributes into your copies; if you never published views, nothing to do. Rebuild frontend assets (npm run build) only if you import the Vue/React/Svelte components from vendor/.
docs/settings.md and the README at v3.1.0 for the new notification settings feature.config/toast.php for defaults (default_duration, default_position, default_animation, and now colors).TOAST_SETTINGS_ENABLED in .env if you want the new settings UI — it is completely inert until enabled.Display a success toast after a form submission:
public function store(Request $request) {
$validated = $request->validate([...]);
Model::create($validated);
Toast::success('Record saved successfully!');
return back();
}
Give trusted admins a browser-based color/behavior editor:
php artisan toast:update --settings --settings-page --settings-layout=layouts.app
php artisan migrate
Then define who may use it (an undefined gate denies everyone):
Gate::define('manage-toast-settings', fn ($user) => $user->can('manage-site'));
Controller Integration:
// Grouped toasts
Toast::group(['title' => 'Updates']);
Toast::success('Profile updated');
Toast::warning('Some fields are missing');
Toast::endGroup();
// With custom duration
Toast::error('Failed', 'Please try again', 10);
Livewire Component:
use JeremyKenedy\LaravelToast\Facades\Toast;
public function mount() {
Toast::info('Livewire component loaded');
}
public function someAction() {
Toast::success('Action completed');
}
Vue/React Integration: Use the provided directives in your frontend framework:
<template>
<div v-toast-success="showToast">Click me</div>
</template>
<script>
export default {
methods: {
showToast() {
this.$toast.success('Vue toast!');
}
}
}
</script>
The settings feature is opt-in and off by default — no table, no routes, no change to rendered toasts until you turn it on.
Enable + set up the page:
php artisan toast:update --settings --settings-page --settings-layout=layouts.app
php artisan migrate
Flags:
--settings — enable settings and publish the migration once.--settings-page — publish the editable page view and register GET /toast/settings.--settings-layout= — Blade layout the page extends (must exist).--settings-section= — section the layout yields (default content).--settings-middleware= — comma-separated route middleware (default web,auth).--settings-gate= — gate name (default manage-toast-settings).Without a flag, an interactive run asks whether to add the settings page; --no-interaction changes nothing unless a flag is given. The commands never run migrations and never define the gate.
Easiest integration — embed the UI in your own admin page:
{{-- Blade + Tailwind v4 / Bootstrap 5 / Bootstrap 4 views --}}
@toastSettings
{{-- or --}}
@include('toast::settings')
{{-- Livewire --}}
<livewire:toast-settings />
<ToastSettings />
<ToastSettings />
<ToastSettings />
Every UI previews light and dark toasts live and covers all behavior options (position, direction, duration, maximum visible, opacity, enter/exit animations, progress bar placement, plus the icon, border, close, progress, stack, pause, auto dismiss, and flash conversion switches).
Per-type colors without the UI — use the new colors config key:
// config/toast.php
'colors' => [
'success' => [
'light' => ['background' => '#16a34a', 'text' => '#ffffff'],
'dark' => ['background' => '#15803d', 'text' => '#ffffff'],
],
],
Each type (success, error, warning, info) has separate light and dark colors for background, text, border, icon, progress bar, and progress track. Omit a part (or leave it on Default) to keep the CSS framework's own color.
Reading saved settings: values live in the opt-in toast_settings table and are merged over config/toast.php and .env. Anything never saved falls back to config, so the UI is purely additive.
Global Defaults (in config/toast.php):
'default_duration' => 3,
'default_position' => 'top-right',
'default_animation' => 'fade',
Per-Toast Overrides:
Toast::success('Message', null, 5, [
'position' => 'bottom-left',
'animation' => 'slide',
]);
Precedence: saved settings (if enabled and set) → config/toast.php → .env defaults.
| Framework | Usage Pattern | Example |
|---|---|---|
| Blade | @toast directive |
@toast in layout file |
| Blade (settings) | @toastSettings / @include('toast::settings') |
@toastSettings in admin page |
| Livewire | Toast:: facade in component |
Toast::warning('Livewire event'); |
| Livewire (settings) | <livewire:toast-settings /> |
<livewire:toast-settings /> |
| Vue | v-toast-* directives |
<div v-toast-success="showToast"> |
| Vue/React/Svelte (settings) | ToastSettings component |
<ToastSettings /> |
| React | useToast hook |
const { toast } = useToast(); |
| Svelte | toast store |
{#toast 'success', 'Message'} |
web,auth (or stricter) is the right default.@source line from the installation guide).--settings-layout= for production; the standalone page falls back to public CDN copies of Tailwind/Bootstrap.Missing @toast Directive:
@toast is included in your layout file after opening <body> tag.Livewire Component Not Triggering Toasts:
Toastable trait:
use JeremyKenedy\LaravelToast\Traits\Toastable;
class MyComponent extends Component {
use Toastable;
}
Frontend Framework Conflicts:
// Vue example
import { createToastPlugin } from 'laravel-toast';
app.use(createToastPlugin());
Settings Enabled but “Nothing Happens”:
TOAST_SETTINGS_ENABLED=true in .env, that routes are cached-cleared (php artisan route:clear), and that the manage-toast-settings gate is defined and returns true. An undefined gate denies everyone by design.Configured Colors Not Reaching Markup:
data-toast-type and parts with data-toast-part. If you published toast-views, merge those attributes into your copies; otherwise colors can’t be injected.Copied Frontend Components Skip Colors:
applyToastColors from toast-options.js and call it with toast.colors_css (the payload key is an empty string when no color is set).Upgrade Broke an Install-Prompt Subclass:
HasInstallPrompts that overrode/read $font errors after upgrading.FONT (this is the only v3.1.0 internal change). Public API, config keys, view names, published paths, and payload keys are unchanged.Check Toast Queue:
Use Toast::flush() to clear all queued toasts (useful for debugging).
Toast::flush();
Inspect Config: Dump the current config to verify settings:
dd(config('toast'));
Confirm Settings Are Actually On:
dump(env('TOAST_SETTINGS_ENABLED'), config('toast.colors'), Gate::allows('manage-toast-settings'));
Remember that the saved row only overrides config for keys you have saved; unset keys silently fall back.
Inspect the Emitted Color CSS:
Custom colors are delivered as colors_css on each toast payload and injected as a single <style id="toast-colors"> tag. View source or a network/DOM inspector to confirm it is present.
Animation Issues:
If animations fail, ensure your CSS framework (Tailwind/Bootstrap) is properly loaded. Override animations in resources/css/app.css if needed:
@import 'laravel-toast/dist/animations.css';
Custom Animations:
Add animations in resources/css/app.css:
@keyframes custom-slide {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
.toast-custom-slide {
animation: custom-slide 0.5s ease-out;
}
Then reference in config:
'animations' => [
'custom-slide' => 'Custom Slide',
],
Custom Toast Types:
Extend the Toast facade or create a helper:
Toast::extend('custom', function ($message, $title = null, $duration = null, $options = []) {
return Toast::make('info', $message, $title, $duration, [
'class' => 'bg-purple-500',
...$options,
]);
});
Custom Colors Without the UI:
Ship a colors key in config/toast.php (or an environment-specific config) when you want brand colors but not the settings page or table.
Replace the Settings Page View:
Publish with --settings-page using the toast-settings-page tag, then edit the view to fit your admin layout, section, and route middleware.
Dark Mode Support:
Ensure your theme supports dark mode and configure in config/toast.php:
'dark_mode' => true,
'dark_class' => 'dark:bg-gray-800 dark:text-white',
v3.1.0 adds separate light and dark colors per part, so test both modes after saving settings.
Queue Toasts Efficiently: Batch toasts in controllers to reduce DOM updates:
Toast::group(['title' => 'Batch Updates']);
Toast::success('Item 1 updated');
Toast::success('Item 2 updated');
Toast::endGroup();
Lazy-Load Animations: For large applications, load animations dynamically:
// Vue example
const { toast } = useToast();
if (!document.querySelector('.toast-animation')) {
const link = document.createElement('link');
link.href = '/css/laravel-toast-animations.css';
link.rel = 'stylesheet';
document.head.appendChild(link);
}
Keep the Settings UI Out of Hot Paths: load @toastSettings / <livewire:toast-settings /> only on the admin page, not in your global layout, and avoid enabling --settings-page unless you need the full page — the embedded component is lighter.
#rgb or #rrggbb only, and normalized before storage/emission; unknown keys or invalid values are rejected with 422.TOAST_SETTINGS_ENABLED from .env (the saved row is kept and ignored), or run php artisan migrate:rollback --path=<published migration> to drop the table.How can I help you explore Laravel packages today?