aymanalhattami/filament-context-menu
Installation:
composer require aymanalhattami/filament-context-menu
Ensure compatibility with your Filament version (3.x, 4.x, or 5.x).
First Use Case:
Add the PageHasContextMenu trait to a Filament page (e.g., ListRecords or ViewRecord):
use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
class ListUsers extends ListRecords
{
use PageHasContextMenu;
public function getContextMenuActions(): array
{
return [
Action::make('Refresh')
->action(fn () => $this->refresh())
];
}
}
getContextMenuActions() method in your page class.Basic Actions:
Use Filament’s built-in actions (e.g., CreateAction, EditAction) or custom actions:
public function getContextMenuActions(): array
{
return [
CreateAction::make()->model(User::class),
Action::make('Custom Action')
->action(fn () => $this->customLogic())
];
}
Dynamic Actions:
Pass context (e.g., $this->record) to actions:
Action::make('Delete')
->action(fn () => $this->record->delete())
->requiresConfirmation()
->visible(fn () => $this->record->trashed())
Grouping Actions:
Use ContextMenuDivider to separate actions logically:
return [
Action::make('Edit'),
ContextMenuDivider::make(),
Action::make('Export'),
];
Prebuilt Actions:
Leverage built-in actions like RefreshAction, GoBackAction, or GoForwardAction:
use AymanAlhattami\FilamentContextMenu\Actions\{RefreshAction, GoBackAction};
public function getContextMenuActions(): array
{
return [
RefreshAction::make(),
GoBackAction::make(),
];
}
Column Integration: Replace standard columns with context-menu-enabled variants:
ContextMenuTextColumn::make('name')
->getContextMenuActions(fn ($record) => [
Action::make('View')
->url(fn () => $this->getResource()::getUrl('view', ['record' => $record])),
]);
Dynamic Actions: Pass the record to cell-specific actions:
ContextMenuIconColumn::make('status')
->getContextMenuActions(fn ($record) => [
Action::make('Toggle Status')
->action(fn () => $record->toggleStatus())
]);
Conditional Visibility: Hide/show actions based on record state:
->visible(fn ($record) => !$record->isArchived())
Resource Pages:
ListRecords, CreateRecord, EditRecord, etc.ListRecords:
public function getContextMenuActions(): array
{
return [
Action::make('Bulk Delete')
->action(fn () => $this->table->getSelectedRecords()->each->delete())
->requiresConfirmation(),
];
}
Custom Pages:
class SettingsPage extends Page
{
use PageHasContextMenu;
public function getContextMenuActions(): array
{
return [
Action::make('Reset Settings')
->action(fn () => $this->resetSettings()),
];
}
}
Modals and Forms:
Action::make('Quick Edit')
->form([
TextInput::make('name'),
])
->action(fn (array $data) => $this->record->update($data))
Action Scope:
getContextMenuActions() may not have access to $this if defined as static.Action::make('Edit')
->action(fn () => $this->edit($this->record))
Performance:
->async() where possible.Overriding Defaults:
isContextMenuEnabled() may conflict with global CONTEXT_MENU_ENABLED.$this->contextMenuEnabled).Table Cell Actions:
ContextMenu*Column may not persist across pagination.->getContextMenuActions() with the full record context.Disabled Menu:
CONTEXT_MENU_ENABLED env var or $contextMenuEnabled property.PageHasContextMenu trait is applied.Missing Actions:
getContextMenuActions() returns an array of valid Action instances.->visible(fn () => true) temporarily to test visibility.Styling Issues:
styles config or custom assets.Reusability:
trait HasCommonContextMenuActions
{
public function getCommonActions(): array
{
return [
RefreshAction::make(),
Action::make('Export')->url(fn () => route('exports.index')),
];
}
}
Testing:
test helpers:
$this->rightClickOn($table->getTableCell('name', $record))
->assertSee('Edit')
->click('Edit');
Localization:
__() helper:
Action::make(__('filament-context-menu::actions.edit'))
Permissions:
can():
Action::make('Delete')
->canSee(fn () => auth()->user()->can('delete', $this->record))
Extension Points:
ContextMenu*Column for new column types.How can I help you explore Laravel packages today?