Context Menu plugin screenshot
Dark mode ready
Multilingual support
Supports v5.x

Context Menu

Customizable context menu (right click menu) for your app.

Tags: Panels
Supported versions:
4.x 3.x
Ayman Alhattami avatar Author: Ayman Alhattami

Documentation

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads


Add a context menu (right click menu) for resource pages, custom pages and table cells of Filament Admin Panel.

  • It uses Filament Actions to set menu actions.
  • It supports dark and light modes.
  • It supports left-to-right and right-to-left direction.
  • You can set a divider between menu actions.
  • It supports resource pages and custom pages.
  • You can set a context menu for table cells.
  • Three actions are available for usage in the page context menu:
    • AymanAlhattami\FilamentContextMenu\Actions\RefreshAction to refresh the page.
    • AymanAlhattami\FilamentContextMenu\Actions\GoBackAction to go back to the previous page.
    • AymanAlhattami\FilamentContextMenu\Actions\GoForward to go back to the forward page.

Demo project | Youtube video | Laravel Daily (Povilas Korop) Video

#Installation

You can install the package via Composer:

composer require aymanalhattami/filament-context-menu

#Usage 1: resource pages and custom pages

  1. Add the trait AymanAlhattami\FilamentContextMenu\PageHasContextMenu to the page you want to add the context menu.
  2. Then, define a getContextMenuActions method inside the page, the method should return an array of Filament Actions
use App\Filament\Resources\UserResource\Pages\CreateUser;
use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Actions\Action;
use Filament\Resources\Pages\ListRecords;

class ListUsers extends ListRecords
{
    use PageHasContextMenu;
    
    public function getContextMenuActions(): array
    {
        return [
            Action::make('Create user')
                ->url(CreateUser::getUrl())
        ];
    }
    
    // 
}

#Divider

You can use AymanAlhattami\FilamentContextMenu\ContextMenuDivider to set divider between menu actions

use App\Filament\Resources\UserResource\Pages\CreateUser;
use App\Filament\Resources\UserResource\Pages\TrashedUsers;
use AymanAlhattami\FilamentContextMenu\ContextMenuDivider;
use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Actions\Action;
use Filament\Resources\Pages\ListRecords;

class ListUsers extends ListRecords
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            Action::make('Create user')
                ->url(CreateUser::getUrl()),
            ContextMenuDivider::make(),
            Action::make('Trashed user')
                ->url(TrashedUsers::getUrl()),
        ];
    }
    
    // 
}

#Create Action

You can use Filament\Actions\CreateAction, visit filament create action for more information.

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ListRecords;
use Filament\Actions\CreateAction;

class ListUsers extends ListRecords
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            CreateAction::make()
                ->model(App\Models\User::class)
                 ->form([
                    TextInput::make('name')
                        ->required(),
                    // ...
                ])
        ];
    }
    
    // 
}

#Edit Action

You can use Filament\Actions\EditAction, visit filament edit action for more information.

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ViewRecord;
use Filament\Actions\EditAction;

class ViewUser extends ViewRecord
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            EditAction::make()
                ->record($this->user)
                ->form([
                    TextInput::make('name')
                        ->required(),
                    // ...
                ])
        ];
    }
    
    // 
}

#View Action

You can use Filament\Actions\ViewAction, visit filament view action for more information.

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\EditRecord;
use Filament\Actions\ViewAction;

class EditUser extends EditRecord
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            ViewAction::make()
                ->record($this->user)
                 ->form([
                    TextInput::make('name')
                        ->required(),
                    // ...
                ])
                
        ];
    }
    
    // 
}

#Delete Action

You can use Filament\Actions\DeleteAction, visit filament delete action for more information.

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ViewRecord;
use Filament\Actions\DeleteAction;

class ViewUser extends ViewRecord
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            DeleteAction::make()
                ->record($this->user)
        ];
    }
    
    // 
}

#Replicate Action

You can use Filament\Actions\ReplicateAction, visit filament replicate action for more information.

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ViewRecord;
use Filament\Actions\ReplicateAction;

class ViewUser extends ViewRecord
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            ReplicateAction::make()
                ->record($this->user)
        ];
    }
    
    // 
}

#Force Delete Action

You can use Filament\Actions\ForceDeleteAction, visit filament force delete action for more information.

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ViewRecord;
use Filament\Actions\ForceDeleteAction;

class ViewUser extends ViewRecord
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            ForceDeleteAction::make()
                ->record($this->user)
        ];
    }
    
    // 
}

#Restore Action

You can use Filament\Actions\RestoreAction, visit filament restore action for more information.

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ListRecords;
use Filament\Actions\RestoreAction;

class ListUsers extends ListRecords
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            RestoreAction::make()
                ->record($this->user)
        ];
    }
    
    // 
}

#Import Action

You can use Filament\Actions\ImportAction, visit filament import action for more information.

use App\Filament\Imports\UserImporter;
use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ListRecords;
use Filament\Actions\ImportAction;

class ListUsers extends ListRecords
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            ImportAction::make()
                ->importer(UserImporter::class)
        ];
    }
    
    // 
}

#Export Action

You can use Filament\Actions\ExportAction, visit filament export action for more information.

use App\Filament\Exports\UserExporter;
use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ListRecords;
use Filament\Actions\ExportAction;

class ListUsers extends ListRecords
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            ExportAction::make()
                ->exporter(UserExporter::class)
        ];
    }
    
    // 
}

#Example: action with modal

You can use filament action with modal

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ViewRecord;
use Filament\Actions\Action;

class ViewUser extends ViewRecord
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            Action::make('Quick edit user')
                ->form([
                    \Filament\Forms\Components\Grid::make(2)
                        ->schema([
                            TextInput::make('name'),
                            TextInput::make('email'),
                        ])
                ])
                ->action(function($data){
                    $this->getRecord()->update([
                        'name' => $data['name'],
                        'email' => $data['email'],
                    ]);
                })
        ];
    }
    
    // 
}

#Example: refresh, go back and go forward actions

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ViewRecord;
use AymanAlhattami\FilamentContextMenu\Actions\{ RefreshAction, GoBackAction, GoForwardAction}; 

class ViewUser extends ViewRecord
{
    use PageHasContextMenu;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [
            RefreshAction::make(),
            GoBackAction::make(),
            GoForwardAction::make()
        ];
    }
    
    // 
}

#Enable / Disable context menu in resource pages and custom pages

Method 1: To globally enable or disable the context menu, you need to define an env variable called CONTEXT_MENU_ENABLED and to set the value to true or false.

Method 2: You can also define a static variable called public static bool $contextMenuEnabled in the page and set the value to true or false;

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ViewRecord;

class ViewUser extends ViewRecord
{
    use PageHasContextMenu;
    
    # enable / disable context menu
    public static bool $contextMenuEnabled = true;

    // 
    
    public static function getContextMenuActions(): array
    {
        return [];
    }
    
    // 
}

Method 3: define a static method called isContextMenuEnabled in the page

use AymanAlhattami\FilamentContextMenu\Traits\PageHasContextMenu;
use Filament\Resources\Pages\ViewRecord;

class ViewUser extends ViewRecord
{
    use PageHasContextMenu;
    
    public static function isContextMenuEnabled(): bool
    {
        return true;
    }

    // 
    
    public static function getContextMenuActions(): array
    {
        return [];
    }
    
    // 
}

#Usage 2: table cells

To add a context menu to the table cell, you can use the following columns:

 AymanAlhattami\FilamentContextMenu\Columns\ContextMenuTextColumn;
 AymanAlhattami\FilamentContextMenu\Columns\ContextMenuCheckboxColumn;
 AymanAlhattami\FilamentContextMenu\Columns\ContextMenuSelectColumn;
 AymanAlhattami\FilamentContextMenu\Columns\ContextMenuColorColumn;
 AymanAlhattami\FilamentContextMenu\Columns\ContextMenuIconColumn;
 AymanAlhattami\FilamentContextMenu\Columns\ContextMenuImageColumn; 
 AymanAlhattami\FilamentContextMenu\Columns\ContextMenuTextInputColumn;
 AymanAlhattami\FilamentContextMenu\Columns\ContextMenuToggleColumn;
use Filament\Tables\Table;
use Filament\Actions\Action;
use AymanAlhattami\FilamentContextMenu\Columns\ContextMenuTextColumn;
use App\Filament\Resources\UserResource\Pages\{ ViewUser, EditUser };

//
public static function table(Table $table): Table
    {
        return $table
            ->columns([
                ContextMenuTextColumn::make('id')
                    ->searchable()
                    ->contextMenuActions(fn (Model $record) => [
                        Action::make('View user')
                            ->url(ViewUser::getUrl(['record' => $record]))
                            ->link()
                            ->icon('heroicon-o-user'),
                    ]),
                ContextMenuTextColumn::make('name')
                    ->searchable()
                    ->contextMenuActions(fn (Model $record) => [
                        Action::make('View user')
                            ->url(Pages\ViewUser::getUrl(['record' => $record]))
                            ->link()
                            ->icon('heroicon-o-user'),
                        Action::make('Edit user')
                            ->url(Pages\EditUser::getUrl(['record' => $record]))
                            ->link()
                            ->icon('heroicon-o-pencil'),
                    ])
                    ,
                ,
            ])
}

Use AymanAlhattami\FilamentContextMenu\ContextMenuDivider to set a divider between menu actions.

#enable / disable table cell context menu

Use ->contextMenuEnabled() method to enable/disable the context menu for the table cell.

//
public static function table(Table $table): Table
    {
        return $table
            ->columns([
                ContextMenuTextColumn::make('id')
                    ->contextMenuEnabled(false)
                    ->contextMenuActions(fn (Model $record) => [
                        Action::make('View user')
                            ->url(ViewUser::getUrl(['record' => $record]))
                            ->link()
                            ->icon('heroicon-o-user'),
                    ]),
//

#Note

For action to have a nice style, use ->link() method of the action, more information

public static function getContextMenuActions(): array
{
    return [
        Action::make('Create user')
            ->url(CreateUser::getUrl())
            ->link()
        ];
}

#Testing

composer test

#Changelog

Please see CHANGELOG for more information on what has changed recently.

#Contributing

Please see CONTRIBUTING for details.

#Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

#Credits

#License

The MIT License (MIT). Please see License File for more information.