一键导入
actions
Create FilamentPHP v4 actions with modals, confirmation, forms, and bulk operations
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create FilamentPHP v4 actions with modals, confirmation, forms, and bulk operations
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Analyze, test, and prepare apps for production with Pest and Playwright testing
This skill should be used when encountering errors during development, when the user mentions an error, when debugging issues, or when asked to "fix an error", "debug this", "why is this failing", "solve this error". Provides intelligent error recognition, solution lookup from past errors, and error logging for future reference.
This skill should be used when the user asks to "manage notes", "update vault", "add to obsidian", "document in vault", "search my notes", "find related notes", or when working with Obsidian vault files. Also triggers when discussing knowledge management, note organization, or when Claude Code auto-captures commits, tasks, or component creation.
This skill should be used when conducting PRD interviews, creating product requirements documents, planning new features, documenting bug fixes, or when using commands like "/prd-builder:prd", "/prd-builder:feature", "/prd-builder:bugfix", or "/prd-builder:refine". Provides comprehensive interview frameworks and question templates for building thorough PRDs.
Execute complete user flow testing with Playwright MCP, testing end-to-end journeys through the application
Systematically test all pages for errors, functionality, and proper rendering using Playwright MCP
| name | actions |
| description | Create FilamentPHP v4 actions with modals, confirmation, forms, and bulk operations |
This skill generates FilamentPHP v4 actions for resources, pages, and tables including modal actions, form actions, bulk operations, and custom workflows.
CRITICAL: Before generating actions, read:
/home/mwguerra/projects/mwguerra/claude-code-plugins/filament-specialist/skills/docs/references/actions/use Filament\Actions;
// Create action
Actions\CreateAction::make()
->label('New Post')
->icon('heroicon-o-plus');
// Edit action
Actions\EditAction::make()
->label('Edit')
->icon('heroicon-o-pencil');
// View action
Actions\ViewAction::make()
->label('View Details')
->icon('heroicon-o-eye');
// Delete action
Actions\DeleteAction::make()
->requiresConfirmation()
->modalHeading('Delete post')
->modalDescription('Are you sure you want to delete this post? This action cannot be undone.')
->modalSubmitActionLabel('Yes, delete');
// Force delete (soft deletes)
Actions\ForceDeleteAction::make()
->requiresConfirmation();
// Restore (soft deletes)
Actions\RestoreAction::make();
// Simple confirmation action
Actions\Action::make('publish')
->label('Publish')
->icon('heroicon-o-check-circle')
->color('success')
->requiresConfirmation()
->modalHeading('Publish Post')
->modalDescription('Are you sure you want to publish this post?')
->modalSubmitActionLabel('Yes, publish')
->action(function (Model $record): void {
$record->update(['status' => 'published', 'published_at' => now()]);
Notification::make()
->title('Post published')
->success()
->send();
});
// Action with form modal
Actions\Action::make('send_email')
->label('Send Email')
->icon('heroicon-o-envelope')
->color('info')
->form([
Forms\Components\TextInput::make('subject')
->label('Subject')
->required()
->maxLength(255),
Forms\Components\Select::make('template')
->label('Template')
->options([
'welcome' => 'Welcome Email',
'reminder' => 'Reminder',
'promotion' => 'Promotion',
])
->required(),
Forms\Components\RichEditor::make('body')
->label('Message')
->required()
->columnSpanFull(),
])
->action(function (Model $record, array $data): void {
Mail::to($record->email)->send(new CustomEmail(
subject: $data['subject'],
template: $data['template'],
body: $data['body'],
));
Notification::make()
->title('Email sent successfully')
->success()
->send();
});
// Wizard action (multi-step)
Actions\Action::make('create_order')
->label('Create Order')
->icon('heroicon-o-shopping-cart')
->steps([
Forms\Components\Wizard\Step::make('Customer')
->schema([
Forms\Components\Select::make('customer_id')
->relationship('customer', 'name')
->required()
->searchable(),
]),
Forms\Components\Wizard\Step::make('Products')
->schema([
Forms\Components\Repeater::make('items')
->schema([
Forms\Components\Select::make('product_id')
->relationship('product', 'name')
->required(),
Forms\Components\TextInput::make('quantity')
->numeric()
->required()
->default(1),
])
->columns(2),
]),
Forms\Components\Wizard\Step::make('Shipping')
->schema([
Forms\Components\Textarea::make('address')
->required(),
Forms\Components\Select::make('shipping_method')
->options([
'standard' => 'Standard',
'express' => 'Express',
]),
]),
])
->action(function (array $data): void {
Order::create($data);
});
Actions\Action::make('approve')
// Visible only for specific status
->visible(fn (Model $record): bool => $record->status === 'pending')
// Hidden in certain conditions
->hidden(fn (Model $record): bool => $record->is_archived)
// Authorization check
->authorize('approve')
// Or with closure
->authorized(fn (): bool => auth()->user()->can('approve_posts'));
// Action that refreshes data
Actions\Action::make('refresh')
->icon('heroicon-o-arrow-path')
->action(fn () => null) // No action needed
->after(fn ($livewire) => $livewire->dispatch('refresh'));
// Action with redirect
Actions\Action::make('view_invoice')
->icon('heroicon-o-document')
->url(fn (Model $record): string => route('invoices.show', $record->invoice_id))
->openUrlInNewTab();
// Action with download
Actions\Action::make('download_pdf')
->icon('heroicon-o-arrow-down-tray')
->action(function (Model $record) {
return response()->download(
storage_path("invoices/{$record->invoice_id}.pdf")
);
});
use Filament\Tables\Actions;
public static function table(Table $table): Table
{
return $table
->columns([...])
->actions([
// Icon-only actions
Actions\ActionGroup::make([
Actions\ViewAction::make(),
Actions\EditAction::make(),
Actions\DeleteAction::make(),
])->dropdownPlacement('bottom-end'),
// Or inline
Actions\ViewAction::make()
->iconButton(),
Actions\EditAction::make()
->iconButton(),
// Custom inline action
Actions\Action::make('duplicate')
->icon('heroicon-o-document-duplicate')
->iconButton()
->action(function (Model $record): void {
$replica = $record->replicate();
$replica->name = $record->name . ' (Copy)';
$replica->save();
}),
]);
}
use Filament\Tables\Actions;
->bulkActions([
Actions\BulkActionGroup::make([
// Standard bulk delete
Actions\DeleteBulkAction::make(),
// Custom bulk action
Actions\BulkAction::make('publish')
->label('Publish Selected')
->icon('heroicon-o-check-circle')
->color('success')
->requiresConfirmation()
->action(function (Collection $records): void {
$records->each->update(['status' => 'published']);
Notification::make()
->title(count($records) . ' posts published')
->success()
->send();
})
->deselectRecordsAfterCompletion(),
// Bulk action with form
Actions\BulkAction::make('assign_category')
->label('Assign Category')
->icon('heroicon-o-tag')
->form([
Forms\Components\Select::make('category_id')
->label('Category')
->relationship('category', 'name')
->required(),
])
->action(function (Collection $records, array $data): void {
$records->each->update(['category_id' => $data['category_id']]);
}),
// Export bulk action
Actions\BulkAction::make('export')
->label('Export to CSV')
->icon('heroicon-o-arrow-down-tray')
->action(function (Collection $records) {
return Excel::download(
new RecordsExport($records),
'records.csv'
);
}),
]),
]);
use Filament\Tables\Actions;
->headerActions([
// Create action
Actions\CreateAction::make()
->label('New Post'),
// Import action
Actions\Action::make('import')
->label('Import')
->icon('heroicon-o-arrow-up-tray')
->form([
Forms\Components\FileUpload::make('file')
->label('CSV File')
->acceptedFileTypes(['text/csv'])
->required(),
])
->action(function (array $data): void {
// Import logic
}),
// Attach action (for relationships)
Actions\AttachAction::make()
->preloadRecordSelect()
->recordSelectSearchColumns(['name', 'email']),
]);
// In RelationManager class
protected function getHeaderActions(): array
{
return [
Tables\Actions\CreateAction::make(),
Tables\Actions\AttachAction::make()
->preloadRecordSelect()
->form(fn (Tables\Actions\AttachAction $action): array => [
$action->getRecordSelect(),
Forms\Components\TextInput::make('role')
->required(),
]),
Tables\Actions\AssociateAction::make(),
];
}
public function table(Table $table): Table
{
return $table
->columns([...])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DetachAction::make(),
Tables\Actions\DissociateAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DetachBulkAction::make(),
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
// In resource page classes
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make(),
Actions\DeleteAction::make(),
// Custom action
Actions\Action::make('preview')
->icon('heroicon-o-eye')
->url(fn (): string => route('posts.show', $this->record))
->openUrlInNewTab(),
];
}
// For List page
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
// Global action
Actions\Action::make('settings')
->icon('heroicon-o-cog')
->url(fn (): string => route('filament.admin.pages.settings')),
];
}
Actions\Action::make('custom')
// Label and icon
->label('Custom Action')
->icon('heroicon-o-star')
->iconPosition(IconPosition::After)
// Colors
->color('success') // primary, secondary, success, warning, danger, info, gray
// Size
->size(ActionSize::Large)
// Button style
->button()
->outlined()
->iconButton()
->link()
// Keyboard shortcut
->keyBindings(['mod+s'])
// Extra attributes
->extraAttributes([
'class' => 'my-custom-class',
'data-action' => 'custom',
])
// Badge
->badge(fn () => 5)
->badgeColor('danger')
// Tooltip
->tooltip('Click to perform action');
use Filament\Notifications\Notification;
use Filament\Notifications\Actions\Action;
Notification::make()
->title('Post created successfully')
->success()
->body('Your post has been created.')
->actions([
Action::make('view')
->button()
->url(route('posts.show', $record)),
Action::make('undo')
->color('gray')
->action(fn () => $record->delete()),
])
->send();
Generated actions include: