Filament: Unsaved changes as a modal instead of the browser dialog
When you edit a form in a Filament panel and try to leave without saving, Filament’s unsavedChangesAlerts() feature kicks in—and the browser often shows the classic window.confirm dialog. It works, but it feels disconnected from the rest of the UI: no shared dark mode, no brand colours, none of the panel’s visual language.
I built filament-unsaved-changes-modal to address that: the same dirty-state rules as Filament, but the confirmation is a Filament modal with “Stay” and “Leave” actions (copy is customizable via translations).
What changes for users
In-panel navigation (links in the body, same origin): you get a Filament modal instead of the browser popup.
Closing the tab or reloading the page: the native browser prompt still applies. That is intentional; a panel modal cannot reliably replace those flows.
The plugin supports Filament SPA (livewire:navigate) and standard full-page navigation.
Installation
Install via Composer (PHP 8.2+, Filament ^5.3.5—see the CVE note in the README):
composer require azgasim/filament-unsaved-changes-modalPanel setup
You need unsavedChangesAlerts() and the plugin together—the package only replaces the confirmation UI, not Filament’s unsaved-change detection.
use AzGasim\FilamentUnsavedChangesModal\FilamentUnsavedChangesModalPlugin;
return $panel
// … your existing configuration …
->unsavedChangesAlerts()
->plugin(FilamentUnsavedChangesModalPlugin::make());You can also register FilamentUnsavedChangesModalPlugin::make() inside ->plugins([...]) alongside your other plugins.
Customization without forking the package
Width, icon, colours for the modal and buttons: methods such as
modalWidth(),modalIcon(),modalIconColor(),stayButtonColor(), andleaveButtonColor()—allowed values follow Filament conventions (width strings like theWidthenum, colours are your panel colour keys).Copy (heading, description, button labels): translations only—publish with the
filament-unsaved-changes-modal-translationstag. The package ships English and German out of the box.Blade markup when you really need it: publish views (
filament-unsaved-changes-modal-views). If you change the modal DOMid, keep it in sync with the plugin constant and the script hook (documented in the README).
To skip the prompt for specific links, add data-skip-unsaved-changes-modal on the <a> or any ancestor element.
Links
Filament: https://filamentphp.com/plugins/aziz-gasim-unsaved-changes-modal
Packagist: packagist.org/packages/azgasim/filament-unsaved-changes-modal
Issues and feedback are welcome on GitHub—if this saves you a few awkward browser dialogs in production, I’d love to hear it.