Modal Notifications
Render any Filament notification as a blocking modal by chaining one method: ->asModal(). Multiple modal notifications fired in the same request are queued one at a time — the user dismisses one and the next slides in, no stacking.
Author:
Mustafa Khaled
Documentation
Render any Filament notification as a blocking modal by chaining one method: ->asModal(). Multiple modal notifications fired in the same request are queued one at a time — the user dismisses one and the next slides in, no stacking.
Everything else you already know about Filament notifications (title, body, icon, color, actions, danger()/success()/warning()/info()) carries over unchanged.
#Requirements
- PHP 8.2+
- Laravel 11+ / 13
- Filament 4 or 5
#Features
- One-line opt-in — chain
->asModal()onto anyNotification::make()call. No new classes to learn. - Queued — multiple modal notifications show one at a time, dismissal advances to the next.
- Auto-added Close button — if the developer didn't declare actions, the modal gets a "Close" button in its footer so it's always dismissible.
- Respects your actions — if you declare
->actions([...]), those render in the footer instead. - Conditional —
->asModal($isCritical)is a no-op when the condition is false, so the notification sends as a regular toast. - Independent of the toast tray — modal notifications never briefly flash as toasts; they use a dedicated session key and Livewire event.
- Plugin-level defaults — set the default modal width, closable behavior, and close button label per panel.
#Installation
composer require wezlo/filament-modal-notifications
Register the plugin on your panel so the Livewire component mounts at the page footer:
use Wezlo\FilamentModalNotifications\FilamentModalNotificationsPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
FilamentModalNotificationsPlugin::make(),
]);
}
Optionally publish the config:
php artisan vendor:publish --tag=filament-modal-notifications-config
#Quick Start
use Filament\Notifications\Notification;
Notification::make()
->title('Changes not saved')
->body('Your unsaved edits will be lost if you leave this page.')
->danger()
->asModal()
->send();
That's it. On the next Livewire cycle, a modal opens with the title, body, and a default Close button. Regular toasts still work exactly as before — only notifications with ->asModal() go through the modal pipeline.
#Usage
#With custom actions
The notification's actions render in the modal footer:
use Filament\Actions\Action;
use Filament\Notifications\Notification;
Notification::make()
->title('Delete this order?')
->body('This cannot be undone.')
->warning()
->actions([
Action::make('cancel')->label('Cancel')->color('gray')->close(),
Action::make('delete')->label('Delete')->color('danger')
->action(fn () => $this->record->delete())
->close(),
])
->asModal()
->send();
When any action's ->close() is invoked (or the user clicks X / Esc / clicks outside if closable), the queue advances to the next pending modal notification.
#Conditional modal
->asModal(false) leaves the notification as a normal toast:
Notification::make()
->title($wasCritical ? 'Error' : 'Saved')
->asModal($wasCritical)
->send();
#Queued — multiple in one request
Notification::make()->title('Step 1 complete')->asModal()->send();
Notification::make()->title('Step 2 complete')->asModal()->send();
Notification::make()->title('Step 3 complete')->asModal()->send();
The user sees one modal at a time in FIFO order. Each dismissal advances to the next. When the queue is empty the modal closes.
#Panel-level defaults
use Filament\Support\Enums\Width;
use Wezlo\FilamentModalNotifications\FilamentModalNotificationsPlugin;
->plugins([
FilamentModalNotificationsPlugin::make()
->defaultWidth(Width::Large)
->defaultClosable(false) // block Esc / click-away / X — require an explicit action
->defaultCloseButtonLabel('Dismiss'),
])
| Method | Type | Default | Description |
|---|---|---|---|
defaultWidth(Width|string) |
enum/string | md |
Modal width (sm, md, lg, xl, 2xl, …, screen) |
defaultClosable(bool) |
bool | true |
Whether the modal can be dismissed via X, Esc, or click-away |
defaultCloseButtonLabel(string) |
string | Close |
Label for the auto-added Close action |
#Default Config File
// config/filament-modal-notifications.php
return [
'default_width' => 'md',
'default_closable' => true,
'default_close_label' => 'Close',
];
#How It Works
->asModal()is a macro registered onFilament\Notifications\Notificationin the service provider. It returns aWezlo\FilamentModalNotifications\ModalNotification— a subclass that overridessend()to push into a dedicated session key (filament.modal-notifications) instead of the defaultfilament.notifications.- A custom dehydrate hook dispatches the
modalNotificationsSentLivewire event when the modal session key has pending notifications (same pattern Filament uses for its toast tray). - A Livewire component (
Wezlo\FilamentModalNotifications\Livewire\ModalNotifications) mounts atPanelsRenderHook::BODY_END. It listens formodalNotificationsSent, drains the session key into an in-component queue, and renders the first pending notification through<x-filament::modal>. When the user dismisses the modal (X, Esc, click-away, or any action chained with->close()), the component advances to the next queued notification. - No toast flash — because modal notifications use a separate session key, the default toast tray never sees them.
#License
MIT
The author
From the same author
Workspace Tabs
Browser-like tabs for Filament panels. Open multiple pages in tabs without losing context, drag to reorder, pin frequently accessed pages, and right-click for quick actions.
Author:
Mustafa Khaled
Search Spotlight
A full-screen Spotlight / command-palette search overlay for Filament panels. Opens on ⌘K (configurable), aggregates results from multiple categories (records, resources, pages, actions, plus recent/pinned from localStorage), and composes Filament's built-in `GlobalSearchProvider` — every resource that already implements `getGloballySearchableAttributes()` shows up automatically.
Author:
Mustafa Khaled
Export Pro
A comprehensive, model-agnostic export engine for Filament. Handles large datasets with background processing and real-time progress tracking, maintains full export history with audit trails, supports scheduled/recurring exports with delivery, and gives admins visibility into who exported what and when.
Author:
Mustafa Khaled
Record Freezer
Freeze individual Eloquent records against modification — finalised contracts, audited financial periods, legal holds
Author:
Mustafa Khaled
Featured Plugins
A selection of plugins curated by the Filament team
Custom Dashboards
Let your users build and share their own dashboards with a drag-and-drop interface. Define your data sources in PHP and let them do the rest.
Filament
Data Lens
Advanced Data Visualization for Laravel Filament - a premium reporting solution enabling custom column creation, sophisticated filtering, and enterprise-grade data insights within admin panels.
Padmission
Spotlight Pro
Browse your Filament Panel with ease. Filament Spotlight Pro adds a Spotlight/Raycast like Command Palette to your Filament Panel.
Dennis Koch