Claude-skill-registry filament-actions
Create FilamentPHP v4 actions with modals, confirmation, forms, and bulk operations
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/filament-actions" ~/.claude/skills/majiayu000-claude-skill-registry-filament-actions && rm -rf "$T"
manifest:
skills/data/filament-actions/SKILL.mdsource content
FilamentPHP Actions Generation Skill
Overview
This skill generates FilamentPHP v4 actions for resources, pages, and tables including modal actions, form actions, bulk operations, and custom workflows.
Documentation Reference
CRITICAL: Before generating actions, read:
/home/mwguerra/projects/mwguerra/claude-code-plugins/filament-specialist/skills/filament-docs/references/actions/
Action Types
Standard CRUD 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();
Custom Actions with Modals
// 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); });
Action Visibility and Authorization
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'));
Actions with Side Effects
// 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") ); });
Table Row Actions
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(); }), ]); }
Bulk Actions
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' ); }), ]), ]);
Header Actions
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']), ]);
Relation Manager Actions
// 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(), ]), ]); }
Page Actions
// 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')), ]; }
Action Styling and Configuration
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');
Notifications with Actions
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();
Output
Generated actions include:
- Proper action type selection
- Modal configurations
- Form schemas for modal forms
- Authorization checks
- Notifications
- Proper styling and icons