doriiaan/filament-menu

A filament menu, inspired by datlechin/filament-menu-builder to reproduce WordPress menu system

v1.0.4 2025-09-13 19:04 UTC

This package is auto-updated.

Last update: 2025-09-13 19:04:44 UTC


README

Latest Version on Packagist Total Downloads

Filament plugin. A filament menu, inspired by datlechin/filament-menu-builder to reproduce Wordpress menu system.

Works with Filament v4 only.

Installation

You can install the package via composer:

composer require doriiaan/filament-menu

You need to publish the migrations and run them:

php artisan vendor:publish --tag="filament-menu-migrations"
php artisan migrate

You can publish the config file with:

php artisan vendor:publish --tag="filament-menu-config"

Optionally, if you want to customize the views, you can publish them with:

php artisan vendor:publish --tag="filament-menu-views"

This is the contents of the published config file:

return [
    'tables' => [
        'menus' => 'menus',
        'menu_items' => 'menu_items',
    ],
];

Add the plugin to AdminPanelProvider:

use Doriiaan\FilamentMenu\FilamentMenuPlugin;

$panel
    ...
    ->plugin(FilamentMenuPlugin::make())

Usage

Setting up Menu Panels

Menu panels are the panels that contain the menu items which you can add to the menus.

Custom Text Menu Panel

This package provides a Custom Text menu panel that allows you to add custom text items to the menus.

It is identical to the Custom Link menu panel except for the fact that you only set a title without a URL or target. This can be useful to add headers to mega-style menus.

The panel is disabled by default to prevent visual clutter. To enable the Custom Text menu panel, you can use the following when configuring the plugin.

use Doriiaan\FilamentMenu\FilamentMenuPlugin;

$panel
    ...
    ->plugin(
        FilamentMenuPlugin::make()
            ->showCustomTextPanel()
    )

Model Menu Panel

The model menu panel allows you to add menu items from a model.

To create a model menu panel, your model must implement the \Doriiaan\FilamentMenu\Contracts\MenuPanelable interface and \Doriiaan\FilamentMenu\Concerns\HasMenuPanel trait.

Then you must also implement the getMenuPanelTitleColumn and getMenuPanelUrlUsing methods. A complete example of this implementation is as follows:

use Doriiaan\FilamentMenu\Concerns\HasMenuPanel;
use Doriiaan\FilamentMenu\Contracts\MenuPanelable;
use Illuminate\Database\Eloquent\Model;

class Course extends Model implements MenuPanelable
{
    use HasMenuPanel;

    public function getMenuPanelTitleColumn(): string
    {
        return 'title';
    }

    public function getMenuPanelUrlUsing(): callable
    {
        return fn (self $model) => route('courses.show', $model->slug);
    }
}

Then you can add the model menu panel to the plugin:

use Doriiaan\FilamentMenu\FilamentMenuPlugin;
use Doriiaan\FilamentMenu\MenuPanel\ModelMenuPanel;

$panel
    ...
    ->plugin(
        FilamentMenuPlugin::make()
            ->addMenuPanels([
                ModelMenuPanel::make()
                    ->model(\App\Models\Category::class),
            ])
    )

Model Menu Panel

Additional Menu Panel Options

When registering a menu panel, multiple methods are available allowing you to configure the panel's behavior such as collapse state and pagination.

use Doriiaan\FilamentMenu\FilamentMenuPlugin;

$panel
    ...
    ->plugin(
        FilamentMenuPlugin::make()
            ->addMenuPanels([
                ModelMenuPanel::make()
                    ->description('Lorem ipsum...')
                    ->icon('heroicon-m-link')
                    ->collapsed(true)
                    ->collapsible(true)
                    ->paginate(perPage: 5, condition: true)
            ])
    )

Custom Fields

In some cases, you may want to extend menu and menu items with custom fields. To do this, start by passing an array of form components to the addMenuFields and addMenuItemFields methods when registering the plugin:

use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Doriiaan\FilamentMenu\FilamentMenuPlugin;

$panel
    ...
    ->plugin(
        FilamentMenuPlugin::make()
            ->addMenuFields([
                Toggle::make('is_logged_in'),
            ])
            ->addMenuItemFields([
                TextInput::make('classes'),
            ])
    )

Next, create a migration adding the additional columns to the appropriate tables:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::table(config('filament-menu-builder.tables.menus'), function (Blueprint $table) {
            $table->boolean('is_logged_in')->default(false);
        });

        Schema::table(config('filament-menu-builder.tables.menu_items'), function (Blueprint $table) {
            $table->string('classes')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::table(config('filament-menu-builder.tables.menus'), function (Blueprint $table) {
            $table->dropColumn('is_logged_in');
        });

        Schema::table(config('filament-menu-builder.tables.menu_items'), function (Blueprint $table) {
            $table->dropColumn('classes');
        });
    }
}

Once done, simply run php artisan migrate.

Customizing the Resource

Out of the box, a default Menu Resource is registered with Filament when registering the plugin in the admin provider. This resource can be extended and overridden allowing for more fine-grained control.

Start by extending the Doriiaan\FilamentMenu\Resources\MenuResource class in your application. Below is an example:

namespace App\Filament\Plugins\Resources;

use Doriiaan\FilamentMenu\Resources\MenuResource as BaseMenuResource;

class MenuResource extends BaseMenuResource
{
    protected static ?string $navigationGroup = 'Navigation';

    public static function getNavigationBadge(): ?string
    {
        return number_format(static::getModel()::count());
    }
}

Now pass the custom resource to usingResource while registering the plugin with the panel:

use App\Filament\Plugins\Resources\MenuResource;
use Doriiaan\FilamentMenu\FilamentMenuPlugin;

$panel
    ...
    ->plugin(
        FilamentMenuPlugin::make()
            ->usingResource(MenuResource::class)
    )

Customizing the Models

The default models used by the plugin can be configured and overridden similarly to the plugin resource as seen above.

Simply extend the default models and then pass the classes when registering the plugin in the panel:

use App\Models\Menu;
use App\Models\MenuItem;
use App\Models\MenuLocation;
use Doriiaan\FilamentMenu\FilamentMenuPlugin;

$panel
    ...
    ->plugin(
        FilamentMenuPlugin::make()
            ->usingMenuModel(Menu::class)
            ->usingMenuItemModel(MenuItem::class)
            ->usingMenuLocationModel(MenuLocation::class)
    )

Using Menus

Getting the assigned menu for a registered location can be done using the Menu model. Below we will call the menu assigned to the primary location:

use Doriiaan\FilamentMenu\Models\Menu;

$menu = Menu::location('primary');

Menu items can be iterated from the menuItems relationship:

@foreach ($menu->menuItems as $item)
    <a href="{{ $item->url }}">{{ $item->title }}</a>
@endforeach

When a menu item is a parent, a collection of the child menu items will be available on the children property:

@foreach ($menu->menuItems as $item)
    <a href="{{ $item->url }}">{{ $item->title }}</a>

    @if ($item->children)
        @foreach ($item->children as $child)
            <a href="{{ $child->url }}">{{ $child->title }}</a>
        @endforeach
    @endif
@endforeach

Configuring Indent/Unindent Actions

The package includes indent and unindent buttons that provide an alternative to drag-and-drop for organizing menu hierarchy. This feature is enabled by default but can be configured:

use Doriiaan\FilamentMenu\FilamentMenuPlugin;

$panel
    ...
    ->plugin(
        FilamentMenuPlugin::make()
            ->enableIndentActions(false) // Disable
    )

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.