| name | filament-actions |
| description | Use this skill whenever creating, editing, reviewing, or debugging Filament UI actions, including page actions, table record actions, toolbar and bulk actions, modal schemas, wizard actions, import/export actions, notifications, and action authorization. |
Filament Action Workflow
Use this skill for UI actions rendered by Filament. Do not confuse these with
domain actions under app/Actions/; a Filament action should call domain logic,
not contain it.
Read First
Resolve paths from the current project root:
app/Filament/CLAUDE.md
app/Filament/Actions/CLAUDE.md
app/Filament/Resources/Tables/CLAUDE.md for table actions
app/Filament/Resources/Schemas/CLAUDE.md for modal schemas
tests/Feature/Filament/CLAUDE.md when tests are expected
Check global action defaults in service providers before adding modal, color,
slide-over, icon, or confirmation settings locally.
Build Flow
- Identify the action surface:
- page header action
- table header action
- table record action
- toolbar or bulk action
- schema action
- notification action
- Use
Filament\Actions\* imports.
- Use
schema([...]) or steps([...]) for action modal input.
- Add
requiresConfirmation() for destructive or irreversible actions.
- Set visibility and authorization from policies or explicit abilities.
- Delegate non-trivial work to an app-level action/service.
- Add success and failure notifications for work that changes state or can
fail.
- Chunk or queue bulk work that can touch many records.
- Extract the action class only when it is reused or too large inline.
Review Checklist
- The action has the right scope for the data it needs.
- The UI does not show unauthorized actions.
- Modal input is validated by the schema.
- Bulk actions are authorized and do not process huge selections in one
request.
- Tests call the action and cover validation/error paths where meaningful.
Deep Pattern: Reuse Across Surfaces
An extracted Action can be reused on page headers, table rows, and relation
manager headers when its setup does not assume a record exists. Keep bulk
behavior in a separate BulkAction class.
protected function getHeaderActions(): array
{
return [
EmailCustomerAction::make(),
];
}
$table->recordActions([
EmailCustomerAction::make(),
]);
$table->toolbarActions([
BulkActionGroup::make([
EmailCustomersBulkAction::make(),
]),
]);
If behavior varies by surface, branch on $this->getRecord() or split the
action. Do not duplicate the same visible(), authorization, modal, and
notification chains inline across multiple surfaces.
Deep Pattern: Modal And Notification Details
Prefer modal intent over trigger-button color:
DeleteAction::make()
->modalIcon(Heroicon::OutlinedTrash)
->modalIconColor('danger');
Action::make('approve')
->modalIcon(Heroicon::OutlinedCheckCircle)
->modalIconColor('success');
For reversible destructive actions, put the undo in the notification action
only when the mutation is genuinely reversible:
Notification::make()
->title('Order archived')
->success()
->actions([
NotificationAction::make('undo')
->color('gray')
->action(fn () => app(RestoreOrderAction::class)->run($record)),
])
->send();