Modal Notifications plugin screenshot
Dark mode ready
Multilingual support
Supports v5.x

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.

Tags: Developer Tool Panels
Supported versions:
5.x 4.x
Mustafa Khaled avatar 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 any Notification::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 on Filament\Notifications\Notification in the service provider. It returns a Wezlo\FilamentModalNotifications\ModalNotification — a subclass that overrides send() to push into a dedicated session key (filament.modal-notifications) instead of the default filament.notifications.
  • A custom dehydrate hook dispatches the modalNotificationsSent Livewire 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 at PanelsRenderHook::BODY_END. It listens for modalNotificationsSent, 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

Mustafa Khaled avatar Author: Mustafa Khaled

15 Year Laravel Developer

Plugins
11
Stars
28

From the same author

Workspace Tabs plugin thumbnail

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.

Mustafa Khaled avatar Author: Mustafa Khaled
6 stars
Tag: Panels Tag: Kit More tags: +1
Dark mode ready Multilingual support
Free
Get it now
Search Spotlight plugin thumbnail

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.

Mustafa Khaled avatar Author: Mustafa Khaled
1 star
Tag: Panels
Dark mode ready Multilingual support
Free
Get it now
Export Pro plugin thumbnail

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.

Mustafa Khaled avatar Author: Mustafa Khaled
0 stars
Tag: Action Tag: Developer Tool More tags: +3
Dark mode ready Multilingual support
$99.00
Buy now
Record Freezer plugin thumbnail

Record Freezer

Freeze individual Eloquent records against modification — finalised contracts, audited financial periods, legal holds

Mustafa Khaled avatar Author: Mustafa Khaled
3 stars
Tag: Panels Tag: Developer Tool More tags: +1
No dark mode support No multilingual support
Free
Get it now