From a9d00218c7030adcb968170c03eff387f20b133c Mon Sep 17 00:00:00 2001 From: Leandro Ferreira Date: Fri, 7 Nov 2025 16:07:50 -0300 Subject: [PATCH 1/9] Add core.blade.php for Filament Actions documentation --- .ai/filament-actions/3/core.blade.php | 406 ++++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 .ai/filament-actions/3/core.blade.php diff --git a/.ai/filament-actions/3/core.blade.php b/.ai/filament-actions/3/core.blade.php new file mode 100644 index 00000000..d90e30ea --- /dev/null +++ b/.ai/filament-actions/3/core.blade.php @@ -0,0 +1,406 @@ +## Filament Actions 3 + +### What is an Action? + +In Filament, actions also handle "doing" something in your app. However, they are a bit different from traditional +actions. +They are designed to be used in the context of a user interface. For instance, you might have a button to delete a +client record, which opens a modal to confirm your decision. +When the user clicks the "Delete" button in the modal, the client is deleted. This whole workflow is an "action". + +@verbatim + + use Filament\Actions\Action; + + Action::make('delete') + ->requiresConfirmation() + ->action(fn () => $this->client->delete()) + +@endverbatim + +### Types of Actions (Different Classes) + +Each context uses a specific class: + +1. `Filament\Actions\Action` - Custom Livewire components and panel pages +- Supports full modals +- Can open URLs or execute logic + +2. `Filament\Tables\Actions\Action` - Table actions (rows/header) +- Supports modals +- Can be added to specific columns + +3. `Filament\Tables\Actions\BulkAction` - Bulk actions +- Executed on multiple selected records + +4. `Filament\Forms\Components\Actions\Action` - Actions in form components + +5. `Filament\Infolists\Components\Actions\Action` - Actions in infolists + +6. `Filament\Notifications\Actions\Action` - Actions in notifications +- Does not support modals (only URL or Livewire events) + +7. `Filament\GlobalSearch\Actions\Action` - Actions in global search results +- Does not support modals (only URL or Livewire events) + +### Prebuilt Actions + +Filament provides prebuilt actions for common Eloquent operations: + +- CreateAction - Create new records +- EditAction - Edit existing records +- ViewAction - View records (read-only) +- DeleteAction - Delete records +- ReplicateAction - Duplicate records +- ForceDeleteAction - Permanently delete (soft deletes) +- RestoreAction - Restore deleted records (soft deletes) +- ImportAction - Import data +- ExportAction - Export data + +These actions come with sensible default configurations and can be customized as needed. + +### Examples +@verbatim + + use Filament\Actions\Action; + + // Button (default) - with background + Action::make('edit')->button() + + // Link - no background, link appearance + Action::make('edit')->link() + + // Icon Button - icon only + Action::make('edit') + ->icon('heroicon-m-pencil-square') + ->iconButton() + + // Responsive - icon button on mobile, button with label on desktop + Action::make('edit') + ->icon('heroicon-m-pencil-square') + ->button() + ->labeledFrom('md') // Label from md breakpoint + +@endverbatim + +### Authorization and Visibility + +Filament actions support conditional visibility and disabling based on authorization or other conditions. + +@verbatim + + // Show/hide conditionally + Action::make('edit') + ->visible(auth()->user()->can('update', $this->post)) + ->hidden(! auth()->user()->can('update', $this->post)) + + // Disable (keeps visible but inactive) + Action::make('delete') + ->disabled(! auth()->user()->can('delete', $this->post)) + +@endverbatim + +### Confirmation Modal + +Filament actions can require confirmation before executing: + +@verbatim + + use App\Models\Post; + use Filament\Actions\Action; + + Action::make('delete') + ->action(fn (Post $record) => $record->delete()) + ->requiresConfirmation() + ->modalHeading('Delete post') + ->modalDescription('Are you sure? This cannot be undone.') + ->modalSubmitActionLabel('Yes, delete it') + ->modalIcon('heroicon-o-trash') + ->modalIconColor('danger') + +@endverbatim + +### Modal with Form + +Filament actions can open modals with forms to collect user input: + +@verbatim + + use App\Models\Post; + use App\Models\User; + use Filament\Actions\Action; + use Filament\Forms\Components\Select; + + Action::make('updateAuthor') + ->form([ + Select::make('authorId') + ->label('Author') + ->options(User::query()->pluck('name', 'id')) + ->required(), + ]) + ->action(function (array $data, Post $record): void { + $record->author()->associate($data['authorId']); + $record->save(); + }) + +@endverbatim + +### Wizard in Modal + +You can create multi-step wizards within action modals: + +@verbatim + + use Filament\Actions\Action; + use Filament\Forms\Components\Wizard\Step; + + Actions\Action::make('create') + ->steps([ + Step::make('Step1') + ->schema([ + // ... + ]), + Step::make('Step2') + ->schema([ + // ... + ]), + ]) + +@endverbatim + +### Custom Modal Content + +Filament actions allow for custom content in modals: + +@verbatim + + use Filament\Actions\Action; + + Action::make('advance') + ->modalContent(view('filament.pages.actions.advance')) + ->modalContentFooter(view('filament.pages.actions.footer')) + +@endverbatim + +### Modal Actions + +Filament actions support customizing modal actions: + +@verbatim + + use Filament\Actions\Action; + use Filament\Actions\StaticAction; + + Action::make('help') + ->modal() + ->modalDescription('...') + ->modalCancelAction(fn (StaticAction $action) => $action->label('Close')) + ->modalSubmitAction(false), // Remove submit button + +@endverbatim + +@verbatim + + use Filament\Actions\Action; + + // Extra footer actions + Action::make('create') + ->form([ + // ... + ]) + ->extraModalFooterActions(fn (Action $action): array => [ + $action->makeModalSubmitAction('createAnother', arguments: ['another' => true]), + ]) + ->action(function (array $data, array $arguments): void { + + // Create record + + if ($arguments['another'] ?? false) { + // Reset form without closing modal + } + }), + +@endverbatim + +### Chaining Actions + +Filament actions can chain multiple actions together, allowing one action to trigger another. + +@verbatim + + use Filament\Actions\Action; + + Action::make('first') + ->requiresConfirmation() + ->action(function () {}) + ->extraModalFooterActions([ + Action::make('second') + ->requiresConfirmation() + ->action(function () {}), + ]), + +@endverbatim + +You can use `->cancelParentActions('first')` on the second action to close the first action's modal when the second action is triggered. + +### Using Actions in Livewire Components + +Filament actions can be integrated into custom Livewire components. Here's how to set up and use actions within a Livewire component: + +@verbatim + + use App\Models\Post; + use Filament\Actions\Action; + use Filament\Actions\Concerns\InteractsWithActions; + use Filament\Actions\Contracts\HasActions; + use Filament\Forms\Concerns\InteractsWithForms; + use Filament\Forms\Contracts\HasForms; + use Livewire\Component; + + class ManagePost extends Component implements HasActions, HasForms + { + use InteractsWithActions; + use InteractsWithForms; + + public Post $post; + + // The method name must be: {actionName} or {actionName}Action + public function deleteAction(): Action + { + return Action::make('delete') + ->requiresConfirmation() + ->action(fn () => $this->post->delete()); + } + + public function render() + { + return view('livewire.manage-post'); + } + } + +@endverbatim + +**Important**: The method must share the exact same name as the action, or the name followed by `Action`. + +Now, to render the action in your Livewire component's Blade view: + +@verbatim + +
+ {{-- Render action --}} + {{ $this->deleteAction }} + + {{-- Required for modals (once per component) --}} + +
+
+@endverbatim + +You also need `` which injects the HTML required to render action modals. +This only needs to be included within the Livewire component once, regardless of how many actions you have for that component. + + +### Passing Arguments + +You can pass arguments to actions when rendering them: + +@verbatim + +
+ @foreach ($posts as $post) +

{{ $post->title }}

+ + {{ ($this->deleteAction)(['post' => $post->id]) }} + @endforeach + + +
+
+@endverbatim + +@verbatim + + Action::make('delete') + ->action(function (array $arguments) { + $post = Post::find($arguments['post']); + + $post?->delete(); + }); + +@endverbatim + +### Visibility in Livewire + +@verbatim + +
+ {{-- Check if action is visible before rendering --}} + @if ($this->deleteAction->isVisible()) + {{ $this->deleteAction }} + @endif + + {{-- With arguments --}} + @if (($this->deleteAction)(['post' => $post->id])->isVisible()) + {{ ($this->deleteAction)(['post' => $post->id]) }} + @endif +
+
+@endverbatim + +### Grouping Actions + +You can group multiple actions together for better organization and presentation. + +@verbatim + +
+ + + +
+
+@endverbatim + +### Triggering Programmatically + +You can trigger actions programmatically using Livewire's `$wire` or `wire:click` directives. + +@verbatim + + + +@endverbatim + +@verbatim + + $wire.mountAction('test', { id: 12345 }) + +@endverbatim + +### Testing Actions + +Filament uses Pest for testing. However, you can easily adapt this to PHPUnit. + +@verbatim + + use function Pest\Livewire\livewire; + + it('can send invoices', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->callAction('send'); + + expect($invoice->refresh()) + ->isSent()->toBeTrue(); + }); + +@endverbatim \ No newline at end of file From 03fb2bde4bfddfa5ed7eac63e4c4cbcfc4f265b8 Mon Sep 17 00:00:00 2001 From: Leandro Ferreira Date: Fri, 7 Nov 2025 16:08:01 -0300 Subject: [PATCH 2/9] Add core.blade.php for Filament Actions version 4 documentation --- .ai/filament-actions/4/core.blade.php | 92 +++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 .ai/filament-actions/4/core.blade.php diff --git a/.ai/filament-actions/4/core.blade.php b/.ai/filament-actions/4/core.blade.php new file mode 100644 index 00000000..480ff6ca --- /dev/null +++ b/.ai/filament-actions/4/core.blade.php @@ -0,0 +1,92 @@ +## Filament Actions 4 + +### Important Version 4 Changes + +#### Unified Actions + +Actions are now fully unified across tables, forms, infolists and regular actions. +Instead of having separate Action classes for each context, all actions now use a single `Filament\Actions` namespace. + +#### Toolbar actions + +Tables now support a dedicated toolbar actions area. + +@verbatim + + use Filament\Tables\Table; + + public function table(Table $table): Table + { + return $table + ->toolbarActions([ + // ... + ]); + } + +@endverbatim + +This is useful for actions like "create", which are not tied to a specific row, or for making bulk actions more visible and accessible in the table’s toolbar. + +#### Bulk Actions + +- Bulk actions now support the `chunkSelectedRecords()` method, allowing selected records to be processed in smaller batches instead of loading everything into memory at once — improving performance and reducing memory usage with large datasets. +- You can now use `authorizeIndividualRecords()` to check a policy method for each selected record in a bulk action. Only the records the user is authorized to act on will be included in the $records array. +- You can now display a notification after a bulk action completes to inform users of the outcome — especially useful when some records are skipped due to authorization. + - Use `successNotificationTitle()` when all records are processed successfully. + - Use `failureNotificationTitle()` to show a message when some or all records fail. + - Both methods can accept a function to display the number of successful and failed records using `$successCount` and `$failureCount`. + +#### Rate limiting actions + +You can now use the `rateLimit()` method to limit how often an action can be triggered — per user IP, per minute. + +#### Authorization + +Authorization messages can now be shown in action tooltips and notifications. + +@verbatim + + use Filament\Actions\Action; + + Action::make('edit') + ->url(fn (): string => route('posts.edit', ['post' => $this->post])) + ->authorize('update') + +@endverbatim + +#### Import action + +Importing relationships: `BelongsToMany` relationships can now be imported via actions. + +#### Export action + +- You can now customize the styling of individual cells in XLSX exports using the `makeXlsxRow()` and `makeXlsxHeaderRow()` methods in your exporter class. +- You can now configure the OpenSpout XLSX writer in your exporter class: + - Use `getXlsxWriterOptions()` to set export options like column widths. + - Override `configureXlsxWriterBeforeClosing()` to modify the writer instance before it's finalized. + +#### Tooltips for disabled buttons + +You can now display `tooltips` on disabled buttons. + +#### Testing actions + +Testing actions in v4 is now simpler and more streamlined. + +@verbatim + + use Filament\Actions\Testing\TestAction; + use function Pest\Livewire\livewire; + + $invoice = Invoice::factory()->create(); + + livewire(ManageInvoices::class) + ->callAction(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()])); + + livewire(ManageInvoices::class) + ->assertActionVisible(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()])) + + livewire(ManageInvoices::class) + ->assertActionExists(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()])) + +@endverbatim \ No newline at end of file From 60ddf4c516e01d5a930647cd1daff105fc604e68 Mon Sep 17 00:00:00 2001 From: Leandro Ferreira Date: Fri, 7 Nov 2025 16:08:19 -0300 Subject: [PATCH 3/9] Add core.blade.php for Filament Actions documentation structure --- .ai/filament-actions/core.blade.php | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .ai/filament-actions/core.blade.php diff --git a/.ai/filament-actions/core.blade.php b/.ai/filament-actions/core.blade.php new file mode 100644 index 00000000..c6ad34d2 --- /dev/null +++ b/.ai/filament-actions/core.blade.php @@ -0,0 +1,9 @@ +## Filament Actions + +### Overview + +### Features + +## Testing + +### Example Tests From 8d89cf0740b179be1570ea38bff0bc30e1871d16 Mon Sep 17 00:00:00 2001 From: Leandro Ferreira Date: Fri, 7 Nov 2025 16:36:14 -0300 Subject: [PATCH 4/9] Enhance core.blade.php with comprehensive Filament Actions documentation --- .ai/filament-actions/core.blade.php | 405 +++++++++++++++++++++++++++- 1 file changed, 402 insertions(+), 3 deletions(-) diff --git a/.ai/filament-actions/core.blade.php b/.ai/filament-actions/core.blade.php index c6ad34d2..6e81b251 100644 --- a/.ai/filament-actions/core.blade.php +++ b/.ai/filament-actions/core.blade.php @@ -2,8 +2,407 @@ ### Overview -### Features +Filament Actions are a powerful feature that handle "doing something" within your application. Unlike traditional actions in web development, Filament Actions are specifically designed for user interfaces. They encapsulate the complete user workflow: the trigger (button/link), the interactive modal window (if needed), and the logic that executes when the action is completed. -## Testing +For example, a delete action might display a button that opens a confirmation modal, and when confirmed, executes the deletion logic. This entire workflow is defined as a single Action object. -### Example Tests +Actions can be used throughout your Filament application: +- Custom Livewire components and panel pages +- Table rows and headers +- Form components +- Infolists +- Notifications +- Global search results + +@verbatim + + use Filament\Actions\Action; + + Action::make('delete') + ->requiresConfirmation() + ->action(fn () => $this->record->delete()) + +@endverbatim + +### Key Features + +#### Action Types and Styles + +Actions can be displayed in different visual styles: + +@verbatim + + use Filament\Actions\Action; + + // Button (default) - with background + Action::make('edit')->button() + + // Link - no background, link appearance + Action::make('edit')->link() + + // Icon Button - icon only + Action::make('edit') + ->icon('heroicon-m-pencil-square') + ->iconButton() + + // Responsive - icon button on mobile, button with label on desktop + Action::make('edit') + ->icon('heroicon-m-pencil-square') + ->button() + ->labeledFrom('md') + +@endverbatim + +#### Prebuilt Actions + +Filament provides prebuilt actions for common Eloquent operations with sensible defaults: + +- **CreateAction** - Create new records +- **EditAction** - Edit existing records +- **ViewAction** - View records (read-only) +- **DeleteAction** - Delete records +- **ReplicateAction** - Duplicate records +- **ForceDeleteAction** - Permanently delete soft-deleted records +- **RestoreAction** - Restore soft-deleted records +- **ImportAction** - Import data from files +- **ExportAction** - Export data to files + +These prebuilt actions can be customized to fit your specific needs. + +#### Authorization and Visibility + +Control when actions are visible or enabled based on permissions or other conditions: + +@verbatim + + use Filament\Actions\Action; + + // Show/hide conditionally + Action::make('edit') + ->visible(auth()->user()->can('update', $this->post)) + ->hidden(! auth()->user()->can('update', $this->post)) + + // Disable (keeps visible but inactive) + Action::make('delete') + ->disabled(! auth()->user()->can('delete', $this->post)) + ->disabledTooltip('You do not have permission to delete this post') + +@endverbatim + +#### Confirmation Modals + +Actions can require confirmation before executing: + +@verbatim + + use App\Models\Post; + use Filament\Actions\Action; + + Action::make('delete') + ->action(fn (Post $record) => $record->delete()) + ->requiresConfirmation() + ->modalHeading('Delete post') + ->modalDescription('Are you sure you want to delete this post? This action cannot be undone.') + ->modalSubmitActionLabel('Yes, delete it') + ->modalIcon('heroicon-o-trash') + ->modalIconColor('danger') + +@endverbatim + +#### Modal Forms + +Actions can open modals with forms to collect user input: + +@verbatim + + use App\Models\Post; + use App\Models\User; + use Filament\Actions\Action; + use Filament\Forms\Components\Select; + + Action::make('updateAuthor') + ->schema([ + Select::make('authorId') + ->label('Author') + ->options(User::query()->pluck('name', 'id')) + ->required(), + ]) + ->action(function (array $data, Post $record): void { + $record->author()->associate($data['authorId']); + $record->save(); + }) + +@endverbatim + +#### Wizard Actions + +Create multi-step workflows within action modals: + +@verbatim + + use Filament\Actions\Action; + use Filament\Forms\Components\Wizard\Step; + + Action::make('create') + ->steps([ + Step::make('Basic Information') + ->schema([ + // Form fields... + ]), + Step::make('Details') + ->schema([ + // Form fields... + ]), + Step::make('Review') + ->schema([ + // Form fields... + ]), + ]) + +@endverbatim + +#### Custom Modal Content + +Add custom views to action modals: + +@verbatim + + use Filament\Actions\Action; + + Action::make('showDetails') + ->modalContent(view('filament.actions.details')) + ->modalContentFooter(view('filament.actions.footer')) + +@endverbatim + +#### Customizing Modal Actions + +Control the footer actions in modals: + +@verbatim + + use Filament\Actions\Action; + use Filament\Actions\StaticAction; + + Action::make('help') + ->modalContent(view('filament.help')) + ->modalCancelAction(fn (StaticAction $action) => $action->label('Close')) + ->modalSubmitAction(false) // Remove submit button + + // Add extra footer actions + Action::make('create') + ->form([ + // Form fields... + ]) + ->extraModalFooterActions(fn (Action $action): array => [ + $action->makeModalSubmitAction('createAnother', arguments: ['another' => true]), + ]) + ->action(function (array $data, array $arguments): void { + // Create record... + + if ($arguments['another'] ?? false) { + // Reset form without closing modal + } + }) + +@endverbatim + +### Using Actions in Livewire Components + +Integrate Filament Actions into custom Livewire components: + +@verbatim + + use App\Models\Post; + use Filament\Actions\Action; + use Filament\Actions\Concerns\InteractsWithActions; + use Filament\Actions\Contracts\HasActions; + use Filament\Forms\Concerns\InteractsWithForms; + use Filament\Forms\Contracts\HasForms; + use Livewire\Component; + + class ManagePost extends Component implements HasActions, HasForms + { + use InteractsWithActions; + use InteractsWithForms; + + public Post $post; + + // Method name must match action name or end with 'Action' + public function deleteAction(): Action + { + return Action::make('delete') + ->requiresConfirmation() + ->action(fn () => $this->post->delete()); + } + + public function render() + { + return view('livewire.manage-post'); + } + } + +@endverbatim + +Render the action in your Blade view: + +@verbatim + +
+ {{-- Render the action --}} + {{ $this->deleteAction }} + + {{-- Required for modals (once per component) --}} + +
+
+@endverbatim + +The `` component injects the HTML required to render action modals. Include it once per Livewire component, regardless of how many actions you have. + +#### Passing Arguments to Actions + +Pass data to actions when rendering: + +@verbatim + +
+ @foreach ($posts as $post) +

{{ $post->title }}

+ {{ ($this->deleteAction)(['post' => $post->id]) }} + @endforeach + + +
+
+@endverbatim + +@verbatim + + Action::make('delete') + ->action(function (array $arguments) { + $post = Post::find($arguments['post']); + $post?->delete(); + }) + +@endverbatim + +#### Checking Action Visibility + +Check if an action is visible before rendering: + +@verbatim + +
+ {{-- Check visibility before rendering --}} + @if ($this->deleteAction->isVisible()) + {{ $this->deleteAction }} + @endif + + {{-- With arguments --}} + @if (($this->deleteAction)(['post' => $post->id])->isVisible()) + {{ ($this->deleteAction)(['post' => $post->id]) }} + @endif +
+
+@endverbatim + +#### Grouping Actions + +Group multiple actions together: + +@verbatim + +
+ + + +
+
+@endverbatim + +#### Triggering Actions Programmatically + +Trigger actions using Livewire's wire methods: + +@verbatim + + + +@endverbatim + +@verbatim + + $wire.mountAction('delete', { id: 12345 }) + +@endverbatim + +#### Chaining Actions + +Chain multiple actions together, where one action can trigger another: + +@verbatim + + use Filament\Actions\Action; + + Action::make('first') + ->requiresConfirmation() + ->action(function () { + // First action logic... + }) + ->extraModalFooterActions([ + Action::make('second') + ->requiresConfirmation() + ->action(function () { + // Second action logic... + }), + ]) + +@endverbatim + +Use `->cancelParentActions()` to close the parent action's modal when triggering a chained action. + +### Testing Actions + +Test actions using Pest or PHPUnit with Livewire's testing utilities: + +@verbatim + + use function Pest\Livewire\livewire; + + it('can send invoices', function () { + $invoice = Invoice::factory()->create(); + + livewire(EditInvoice::class, [ + 'invoice' => $invoice, + ]) + ->callAction('send') + ->assertHasNoActionErrors(); + + expect($invoice->refresh()) + ->isSent()->toBeTrue(); + }); + + it('can delete posts with confirmation', function () { + $post = Post::factory()->create(); + + livewire(ManagePosts::class) + ->callAction('delete', ['post' => $post->id]) + ->assertHasNoActionErrors(); + + expect(Post::find($post->id))->toBeNull(); + }); + +@endverbatim + +### Version-Specific Features + +For detailed information about features specific to each version: +- See `.ai/filament-actions/3/core.blade.php` for Filament Actions v3 specifics +- See `.ai/filament-actions/4/core.blade.php` for Filament Actions v4 specifics and what's new From ca09633d29657a8e65604927f4660bea4f20f64e Mon Sep 17 00:00:00 2001 From: Leandro Ferreira Date: Fri, 7 Nov 2025 17:24:57 -0300 Subject: [PATCH 5/9] Update core.blade.php with important notes and context-specific action class details for Filament Actions v3 --- .ai/filament-actions/3/core.blade.php | 521 ++++++++++---------------- 1 file changed, 189 insertions(+), 332 deletions(-) diff --git a/.ai/filament-actions/3/core.blade.php b/.ai/filament-actions/3/core.blade.php index d90e30ea..fd15dbd8 100644 --- a/.ai/filament-actions/3/core.blade.php +++ b/.ai/filament-actions/3/core.blade.php @@ -1,255 +1,26 @@ ## Filament Actions 3 -### What is an Action? +### Important Note About Version 3 -In Filament, actions also handle "doing" something in your app. However, they are a bit different from traditional -actions. -They are designed to be used in the context of a user interface. For instance, you might have a button to delete a -client record, which opens a modal to confirm your decision. -When the user clicks the "Delete" button in the modal, the client is deleted. This whole workflow is an "action". +In Filament Actions v3, actions are **context-specific** and use different class namespaces depending on where they are used. +This is a key difference from v4, where actions are unified across all contexts. -@verbatim - - use Filament\Actions\Action; - - Action::make('delete') - ->requiresConfirmation() - ->action(fn () => $this->client->delete()) - -@endverbatim +**Always import the correct Action class for your context** to avoid errors and unexpected behavior. ### Types of Actions (Different Classes) -Each context uses a specific class: - -1. `Filament\Actions\Action` - Custom Livewire components and panel pages -- Supports full modals -- Can open URLs or execute logic - -2. `Filament\Tables\Actions\Action` - Table actions (rows/header) -- Supports modals -- Can be added to specific columns - -3. `Filament\Tables\Actions\BulkAction` - Bulk actions -- Executed on multiple selected records - -4. `Filament\Forms\Components\Actions\Action` - Actions in form components - -5. `Filament\Infolists\Components\Actions\Action` - Actions in infolists +Each context requires a specific Action class with its own namespace: -6. `Filament\Notifications\Actions\Action` - Actions in notifications -- Does not support modals (only URL or Livewire events) +#### 1. Page Actions (`Filament\Actions\Action`) -7. `Filament\GlobalSearch\Actions\Action` - Actions in global search results -- Does not support modals (only URL or Livewire events) +Used in custom Livewire components and panel pages. -### Prebuilt Actions +**Capabilities:** +- Supports full modals with forms +- Can open URLs or execute custom logic -Filament provides prebuilt actions for common Eloquent operations: - -- CreateAction - Create new records -- EditAction - Edit existing records -- ViewAction - View records (read-only) -- DeleteAction - Delete records -- ReplicateAction - Duplicate records -- ForceDeleteAction - Permanently delete (soft deletes) -- RestoreAction - Restore deleted records (soft deletes) -- ImportAction - Import data -- ExportAction - Export data - -These actions come with sensible default configurations and can be customized as needed. - -### Examples @verbatim - - use Filament\Actions\Action; - - // Button (default) - with background - Action::make('edit')->button() - - // Link - no background, link appearance - Action::make('edit')->link() - - // Icon Button - icon only - Action::make('edit') - ->icon('heroicon-m-pencil-square') - ->iconButton() - - // Responsive - icon button on mobile, button with label on desktop - Action::make('edit') - ->icon('heroicon-m-pencil-square') - ->button() - ->labeledFrom('md') // Label from md breakpoint - -@endverbatim - -### Authorization and Visibility - -Filament actions support conditional visibility and disabling based on authorization or other conditions. - -@verbatim - - // Show/hide conditionally - Action::make('edit') - ->visible(auth()->user()->can('update', $this->post)) - ->hidden(! auth()->user()->can('update', $this->post)) - - // Disable (keeps visible but inactive) - Action::make('delete') - ->disabled(! auth()->user()->can('delete', $this->post)) - -@endverbatim - -### Confirmation Modal - -Filament actions can require confirmation before executing: - -@verbatim - - use App\Models\Post; - use Filament\Actions\Action; - - Action::make('delete') - ->action(fn (Post $record) => $record->delete()) - ->requiresConfirmation() - ->modalHeading('Delete post') - ->modalDescription('Are you sure? This cannot be undone.') - ->modalSubmitActionLabel('Yes, delete it') - ->modalIcon('heroicon-o-trash') - ->modalIconColor('danger') - -@endverbatim - -### Modal with Form - -Filament actions can open modals with forms to collect user input: - -@verbatim - - use App\Models\Post; - use App\Models\User; - use Filament\Actions\Action; - use Filament\Forms\Components\Select; - - Action::make('updateAuthor') - ->form([ - Select::make('authorId') - ->label('Author') - ->options(User::query()->pluck('name', 'id')) - ->required(), - ]) - ->action(function (array $data, Post $record): void { - $record->author()->associate($data['authorId']); - $record->save(); - }) - -@endverbatim - -### Wizard in Modal - -You can create multi-step wizards within action modals: - -@verbatim - - use Filament\Actions\Action; - use Filament\Forms\Components\Wizard\Step; - - Actions\Action::make('create') - ->steps([ - Step::make('Step1') - ->schema([ - // ... - ]), - Step::make('Step2') - ->schema([ - // ... - ]), - ]) - -@endverbatim - -### Custom Modal Content - -Filament actions allow for custom content in modals: - -@verbatim - - use Filament\Actions\Action; - - Action::make('advance') - ->modalContent(view('filament.pages.actions.advance')) - ->modalContentFooter(view('filament.pages.actions.footer')) - -@endverbatim - -### Modal Actions - -Filament actions support customizing modal actions: - -@verbatim - - use Filament\Actions\Action; - use Filament\Actions\StaticAction; - - Action::make('help') - ->modal() - ->modalDescription('...') - ->modalCancelAction(fn (StaticAction $action) => $action->label('Close')) - ->modalSubmitAction(false), // Remove submit button - -@endverbatim - -@verbatim - - use Filament\Actions\Action; - - // Extra footer actions - Action::make('create') - ->form([ - // ... - ]) - ->extraModalFooterActions(fn (Action $action): array => [ - $action->makeModalSubmitAction('createAnother', arguments: ['another' => true]), - ]) - ->action(function (array $data, array $arguments): void { - - // Create record - - if ($arguments['another'] ?? false) { - // Reset form without closing modal - } - }), - -@endverbatim - -### Chaining Actions - -Filament actions can chain multiple actions together, allowing one action to trigger another. - -@verbatim - - use Filament\Actions\Action; - - Action::make('first') - ->requiresConfirmation() - ->action(function () {}) - ->extraModalFooterActions([ - Action::make('second') - ->requiresConfirmation() - ->action(function () {}), - ]), - -@endverbatim - -You can use `->cancelParentActions('first')` on the second action to close the first action's modal when the second action is triggered. - -### Using Actions in Livewire Components - -Filament actions can be integrated into custom Livewire components. Here's how to set up and use actions within a Livewire component: - -@verbatim - - use App\Models\Post; + use Filament\Actions\Action; use Filament\Actions\Concerns\InteractsWithActions; use Filament\Actions\Contracts\HasActions; @@ -262,145 +33,231 @@ class ManagePost extends Component implements HasActions, HasForms use InteractsWithActions; use InteractsWithForms; - public Post $post; - - // The method name must be: {actionName} or {actionName}Action - public function deleteAction(): Action + public function editAction(): Action { - return Action::make('delete') - ->requiresConfirmation() - ->action(fn () => $this->post->delete()); - } - - public function render() - { - return view('livewire.manage-post'); + return Action::make('edit') + ->icon('heroicon-m-pencil-square') + ->form([ + // Form fields... + ]) + ->action(function (array $data): void { + // Update logic... + }); } } @endverbatim -**Important**: The method must share the exact same name as the action, or the name followed by `Action`. +#### 2. Table Actions (`Filament\Tables\Actions\Action`) + +Used in table rows and headers. **Note:** This is a different class from page actions. -Now, to render the action in your Livewire component's Blade view: +**Capabilities:** +- Supports modals +- Can be added to specific columns +- Can be row actions or header actions @verbatim - -
- {{-- Render action --}} - {{ $this->deleteAction }} - - {{-- Required for modals (once per component) --}} - -
+ + use Filament\Tables\Actions\Action; + use Filament\Tables\Table; + + public function table(Table $table): Table + { + return $table + ->columns([ + // ... + ]) + ->actions([ + // Row actions - appear in each row + Action::make('edit') + ->icon('heroicon-m-pencil-square') + ->url(fn (Post $record): string => route('posts.edit', $record)), + Action::make('delete') + ->requiresConfirmation() + ->action(fn (Post $record) => $record->delete()), + ]) + ->headerActions([ + // Header actions - appear at the top of the table + Action::make('create') + ->icon('heroicon-m-plus') + ->url(route('posts.create')), + ]); + } @endverbatim -You also need `` which injects the HTML required to render action modals. -This only needs to be included within the Livewire component once, regardless of how many actions you have for that component. +**Table-specific features:** +- Use `->actions()` for row actions +- Use `->headerActions()` for actions at the top of the table +- Row actions have access to the `$record` parameter +#### 3. Bulk Actions (`Filament\Tables\Actions\BulkAction`) -### Passing Arguments +Special type of table action executed on multiple selected records at once. -You can pass arguments to actions when rendering them: +**Important:** This is a separate class, not the regular `Action` class. @verbatim - -
- @foreach ($posts as $post) -

{{ $post->title }}

- - {{ ($this->deleteAction)(['post' => $post->id]) }} - @endforeach + + use Filament\Tables\Actions\BulkAction; + use Filament\Tables\Table; + use Illuminate\Database\Eloquent\Collection; - -
+ public function table(Table $table): Table + { + return $table + ->columns([ + // ... + ]) + ->bulkActions([ + BulkAction::make('delete') + ->requiresConfirmation() + ->action(fn (Collection $records) => $records->each->delete()), + + BulkAction::make('publish') + ->icon('heroicon-m-check') + ->action(fn (Collection $records) => $records->each->publish()), + ]); + }
@endverbatim -@verbatim - - Action::make('delete') - ->action(function (array $arguments) { - $post = Post::find($arguments['post']); +**Bulk action characteristics:** +- Receives a `Collection` of records, not a single record +- Appears when user selects multiple table rows +- Can have confirmation modals and forms - $post?->delete(); - }); - -@endverbatim +#### 4. Form Component Actions (`Filament\Forms\Components\Actions\Action`) -### Visibility in Livewire +Actions attached to form components like text inputs, selects, etc. @verbatim - -
- {{-- Check if action is visible before rendering --}} - @if ($this->deleteAction->isVisible()) - {{ $this->deleteAction }} - @endif - - {{-- With arguments --}} - @if (($this->deleteAction)(['post' => $post->id])->isVisible()) - {{ ($this->deleteAction)(['post' => $post->id]) }} - @endif -
+ + use Filament\Forms\Components\Actions; + use Filament\Forms\Components\Actions\Action; + use Filament\Forms\Components\TextInput; + + TextInput::make('email') + ->suffixAction( + Action::make('sendVerification') + ->icon('heroicon-m-envelope') + ->action(function () { + // Send verification email... + }) + ), + + Actions::make([ + Action::make('sendNotification') + ->icon('heroicon-m-bell') + ->action(function () {}), + ]) @endverbatim -### Grouping Actions +**Common patterns:** +- `->suffixAction()` - Action at the end of the input +- `->prefixAction()` - Action at the start of the input +- `->hintAction()` - Action in the hint area -You can group multiple actions together for better organization and presentation. +#### 5. Infolist Actions (`Filament\Infolists\Components\Actions\Action`) + +Actions used within infolist entries. @verbatim - -
- - - -
+ + use Filament\Infolists\Components\Actions\Action; + use Filament\Infolists\Components\TextEntry; + + TextEntry::make('status') + ->badge() + ->suffixAction( + Action::make('changeStatus') + ->icon('heroicon-m-pencil-square') + ->form([ + // Form fields... + ]) + ->action(function (array $data) { + // Update status... + }) + ) @endverbatim -### Triggering Programmatically +#### 6. Notification Actions (`Filament\Notifications\Actions\Action`) + +Actions in notification messages. **Limited functionality.** -You can trigger actions programmatically using Livewire's `$wire` or `wire:click` directives. +**Important limitations:** +- Does **not** support modals +- Can only open URLs or dispatch Livewire events @verbatim - - + + use Filament\Notifications\Actions\Action; + use Filament\Notifications\Notification; + + Notification::make() + ->title('New invoice created') + ->body('Invoice #12345 has been created.') + ->actions([ + Action::make('view') + ->button() + ->url(route('invoices.show', 12345)), + Action::make('markAsRead') + ->button() + ->dispatch('markAsRead', [12345]), + ]) + ->send(); @endverbatim +#### 7. Global Search Actions (`Filament\GlobalSearch\Actions\Action`) + +Actions displayed in global search results. **Limited functionality.** + +**Important limitations:** +- Does **not** support modals +- Can only open URLs or dispatch Livewire events + @verbatim - - $wire.mountAction('test', { id: 12345 }) + + use Filament\GlobalSearch\Actions\Action; + + public static function getGlobalSearchResultActions(Model $record): array + { + return [ + Action::make('edit') + ->url(static::getUrl('edit', ['record' => $record])), + ]; + } @endverbatim -### Testing Actions +### Using Prebuilt Actions in Version 3 -Filament uses Pest for testing. However, you can easily adapt this to PHPUnit. +When using prebuilt actions (CreateAction, EditAction, etc.) in v3, import them from the context-specific namespace: @verbatim - - use function Pest\Livewire\livewire; + + // For pages + use Filament\Actions\CreateAction; + use Filament\Actions\DeleteAction; + + // For tables + use Filament\Tables\Actions\CreateAction; + use Filament\Tables\Actions\EditAction; + use Filament\Tables\Actions\DeleteAction; + use Filament\Tables\Actions\BulkActionGroup; + use Filament\Tables\Actions\DeleteBulkAction; + +@endverbatim - it('can send invoices', function () { - $invoice = Invoice::factory()->create(); +### Upgrading to Version 4 - livewire(EditInvoice::class, [ - 'invoice' => $invoice, - ]) - ->callAction('send'); +If you're planning to upgrade to Filament Actions v4, be aware that: +- All action classes are unified into `Filament\Actions` namespace +- Tables have new toolbar actions area +- Bulk actions have new capabilities like chunking and individual authorization - expect($invoice->refresh()) - ->isSent()->toBeTrue(); - }); - -@endverbatim \ No newline at end of file +See `.ai/filament-actions/4/core.blade.php` for v4-specific features. From 6629ca07045097a4da06f75b74a5bb75ffbe5744 Mon Sep 17 00:00:00 2001 From: Leandro Ferreira Date: Fri, 7 Nov 2025 17:25:14 -0300 Subject: [PATCH 6/9] Refine overview section in core.blade.php for clarity and readability --- .ai/filament-actions/core.blade.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.ai/filament-actions/core.blade.php b/.ai/filament-actions/core.blade.php index 6e81b251..d628e95a 100644 --- a/.ai/filament-actions/core.blade.php +++ b/.ai/filament-actions/core.blade.php @@ -2,9 +2,11 @@ ### Overview -Filament Actions are a powerful feature that handle "doing something" within your application. Unlike traditional actions in web development, Filament Actions are specifically designed for user interfaces. They encapsulate the complete user workflow: the trigger (button/link), the interactive modal window (if needed), and the logic that executes when the action is completed. +Filament Actions are a powerful feature that handle "doing something" within your application. Unlike traditional actions in web development, Filament Actions are specifically designed for user interfaces. +They encapsulate the complete user workflow: the trigger (button/link), the interactive modal window (if needed), and the logic that executes when the action is completed. -For example, a delete action might display a button that opens a confirmation modal, and when confirmed, executes the deletion logic. This entire workflow is defined as a single Action object. +For example, a delete action might display a button that opens a confirmation modal, and when confirmed, executes the deletion logic. +This entire workflow is defined as a single Action object. Actions can be used throughout your Filament application: - Custom Livewire components and panel pages From cb0cddb9e1a4d7d84b8c2b8f1984496a41155cc0 Mon Sep 17 00:00:00 2001 From: Leandro Ferreira Date: Fri, 7 Nov 2025 17:29:17 -0300 Subject: [PATCH 7/9] Add Heroicon enums usage example to core.blade.php documentation --- .ai/filament-actions/4/core.blade.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.ai/filament-actions/4/core.blade.php b/.ai/filament-actions/4/core.blade.php index 480ff6ca..991a2567 100644 --- a/.ai/filament-actions/4/core.blade.php +++ b/.ai/filament-actions/4/core.blade.php @@ -4,7 +4,7 @@ #### Unified Actions -Actions are now fully unified across tables, forms, infolists and regular actions. +Actions are now fully unified across tables, forms, infolists and regular actions. Instead of having separate Action classes for each context, all actions now use a single `Filament\Actions` namespace. #### Toolbar actions @@ -89,4 +89,18 @@ public function table(Table $table): Table livewire(ManageInvoices::class) ->assertActionExists(TestAction::make('send')->arguments(['invoice' => $invoice->getKey()])) -@endverbatim \ No newline at end of file +@endverbatim + +#### Heroicon enums + +You can now use Heroicon enums when specifying icons for actions. + +@verbatim + + use Filament\Actions\Action; + use Filament\Support\Icons\Heroicon; + + Action::make('create') + ->icon(Heroicon::OutlinedPlusCircle); + +@endverbatim From 813a906c1064eeeefb4e2bfee1e6fcee9c8004ad Mon Sep 17 00:00:00 2001 From: Leandro Ferreira Date: Fri, 7 Nov 2025 17:32:51 -0300 Subject: [PATCH 8/9] Improve documentation clarity in core.blade.php by refining bulk actions and other sections --- .ai/filament-actions/4/core.blade.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.ai/filament-actions/4/core.blade.php b/.ai/filament-actions/4/core.blade.php index 991a2567..460e3ff7 100644 --- a/.ai/filament-actions/4/core.blade.php +++ b/.ai/filament-actions/4/core.blade.php @@ -29,7 +29,7 @@ public function table(Table $table): Table #### Bulk Actions -- Bulk actions now support the `chunkSelectedRecords()` method, allowing selected records to be processed in smaller batches instead of loading everything into memory at once — improving performance and reducing memory usage with large datasets. +- Bulk actions now support the `chunkSelectedRecords()` method, allowing selected records to be processed in smaller batches instead of loading everything into memory at once, improving performance and reducing memory usage with large datasets. - You can now use `authorizeIndividualRecords()` to check a policy method for each selected record in a bulk action. Only the records the user is authorized to act on will be included in the $records array. - You can now display a notification after a bulk action completes to inform users of the outcome — especially useful when some records are skipped due to authorization. - Use `successNotificationTitle()` when all records are processed successfully. @@ -38,7 +38,7 @@ public function table(Table $table): Table #### Rate limiting actions -You can now use the `rateLimit()` method to limit how often an action can be triggered — per user IP, per minute. +You can now use the `rateLimit()` method to limit how often an action can be triggered per user IP, per minute. #### Authorization @@ -56,7 +56,7 @@ public function table(Table $table): Table #### Import action -Importing relationships: `BelongsToMany` relationships can now be imported via actions. +`BelongsToMany` relationships can now be imported via actions. #### Export action @@ -67,7 +67,7 @@ public function table(Table $table): Table #### Tooltips for disabled buttons -You can now display `tooltips` on disabled buttons. +You can now display tooltips on disabled buttons. #### Testing actions From 8e77cddbe00c92833797d5ce0d240c4f19084b94 Mon Sep 17 00:00:00 2001 From: Leandro Ferreira Date: Fri, 7 Nov 2025 17:47:30 -0300 Subject: [PATCH 9/9] Fix `` component in core.blade.php documentation --- .ai/filament-actions/core.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ai/filament-actions/core.blade.php b/.ai/filament-actions/core.blade.php index d628e95a..f8ccbdf0 100644 --- a/.ai/filament-actions/core.blade.php +++ b/.ai/filament-actions/core.blade.php @@ -260,7 +260,7 @@ public function render() @endverbatim -The `` component injects the HTML required to render action modals. Include it once per Livewire component, regardless of how many actions you have. +The @verbatim ``@endverbatim component injects the HTML required to render action modals. Include it once per Livewire component, regardless of how many actions you have. #### Passing Arguments to Actions