filament/actions
Filament Actions provides a fluent API for adding interactive buttons, links, and icon buttons to Laravel Filament apps. Define confirmation modals, forms, notifications, redirects, and authorization in one place, then reuse actions across tables, pages, and resources.
Architecture fit. filament/actions is not a standalone product to evaluate in isolation — it is a split-off subpackage of the Filament monorepo (filamentphp/filament, 32k+ stars, MIT). It supplies the action/modal primitive: a PHP-defined Action object rendered through Blade + Alpine.js, dispatched and validated server-side via Livewire. That means the real architecture decision is "do we standardize on Filament's action abstraction as our modal/confirmation pattern?" — not "should we adopt this dependency." Fit is excellent for Livewire-based apps, especially admin panels, internal tools, and CRUD-heavy dashboards. Fit is zero for Inertia/React/Vue front ends and weak for plain Blade apps with only incidental Livewire usage.
Integration feasibility. High, conditional on two things: (1) the app already runs Livewire v3, and (2) the app's Tailwind build scans Filament's vendor view paths — the single most common integration failure, and it presents as "the modal looks unstyled" rather than as an error. Integration surface is small: composer require, then declare actions in a Livewire component (getActions() or Filament's table()->actions([...])), then render the action container in Blade. Server-side authorization, validation, and form schema all travel with the action definition, which is the main productivity lever.
Technical risk.
Key questions.
->authorize(), ->visible() closures — and is that pattern enforced in review?Stack fit.
| Stack | Fit | Note |
|---|---|---|
| Laravel + Livewire + Filament panel | Excellent | Native; zero-friction, inherits design system |
| Laravel + Livewire, no Filament panel | Good | Supported; you must ship Filament's CSS/JS assets and Tailwind config yourself |
| Laravel + Blade + Alpine only | Poor | Requires introducing Livewire first — a separate, larger project |
| Laravel + Inertia / Vue / React | None | Modal logic lives in the JS layer; do not attempt |
| Non-PHP front end | None | Not applicable |
Migration path. Do not run a big-bang refactor. Inventory existing modals and classify them: (a) confirm-only, (b) confirm-with-form, (c) bespoke interactive. Categories (a) and (b) are mechanical to convert and represent the bulk of the payoff. Category (c) stays where it is. Conversion per action is typically a small diff: replace the bespoke Blade partial + Alpine state with an Action::make() definition, move validation into the action's form(), and delete the hand-rolled JS.
Compatibility. Requires Laravel (9+/10+) and Livewire v3; PHP 8.1+ for Filament 3, 8.2+ for Filament 4 — confirm against the pinned major. It has no hard dependency on a Filament panel, but it does depend on Filament's asset pipeline and Tailwind preset, so "no Filament" still means "Filament's front-end stack." Pin Filament and Livewire to matching majors in composer.json; a mismatched minor is the most likely source of confusing runtime errors.
Sequencing.
form(), no bespoke modal markup for new work.Maintenance. Net maintenance is lower for standardized cases: actions are declarative, live in PHP alongside their component, and inherit UI fixes from Filament upgrades instead of from hand-maintained Blade/JS. The retained cost is upgrade cost — a Filament major is a scheduled project, and the action surface is part of it. Budget it explicitly (an estimate in engineer-days per major, refreshed each cycle) rather than discovering it. The counterfactual is worse: hand-rolled modals accumulate per-page JS debt with no upgrade path and no single owner. Also account for the "invisible inheritance" tradeoff — styling and behavior can shift on a minor upgrade, so visual regression coverage on key modals is worth the small setup cost.
Support. Onboarding is fast for anyone who has used Livewire (roughly 1–2 days to productive), and noticeably slower for engineers without Livewire's reactivity model in their heads (closer to a week, and that week is Livewire, not Filament). Debugging splits into two tiers: "action doesn't appear / doesn't fire" is almost always visible() conditions, authorization, or a component not re-rendering — cheap to diagnose. "It's broken inside the modal" can land in Filament or Livewire internals, where stack traces are unhelpful. Mitigation: require a Pest browser test per converted action, and keep a short internal troubleshooting page (styling not applied → check Tailwind content paths; action missing → check authorization/visibility; form not submitting → check field definitions and wire:ignore).
Scaling. Runtime overhead is modest — rendering is server-driven, Alpine handles the client-side state. Two scaling concerns matter more than raw performance:
visible()/label() closures can produce hidden N+1s. Profile before adding DB lookups inside action definitions.Failure modes.
| Failure | User-visible impact | Mitigation |
|---|---|---|
| Tailwind doesn't scan Filament view paths | Unstyled modal ships | Include in build config; add visual smoke test in CI |
| Filament/Livewire version skew | Modal renders, action silently no-ops | Pin majors; run composer test + browser tests on upgrade PRs |
Action registered before $record exists |
Empty or wrong action data | Set actions in mount()/hydrate(); test the lifecycle |
| Long-running action blocks the UI | Perceived hang, double submits | ->defer() / lazy loading; disable action while processing |
| Stacked modals conflict | Overlay/z-index breakage | One modal pattern per page; test the stacked case |
| Authorization only enforced in the UI | Privilege escalation | Enforce in policies on the server; treat visible() as cosmetic |
| Abandonware fear | Unfounded here | Package ships from an active monorepo; verify on each upgrade, not each sprint |
Ramp-up and success metrics. Track four numbers: median engineer-hours to implement a new modal (pre vs. post), modal-related defect count per release, share of new features using the standard action pattern (target >80% within two quarters), and engineer-days consumed by the next Filament major upgrade. Add one quality gate: a WCAG spot-check on the converted modals if accessibility is a contractual obligation. If hours-to-implement doesn't drop and the pattern share doesn't climb by end of the pilot, stop — the cost of the abstraction isn't being earned back.
How can I help you explore Laravel packages today?