https://github.com/datlechin/filament-menu-builder
Create and manage menu in your Filament app.
https://github.com/datlechin/filament-menu-builder
filament filament-plugin filamentphp menu menu-builder
Last synced: 4 months ago
JSON representation
Create and manage menu in your Filament app.
- Host: GitHub
- URL: https://github.com/datlechin/filament-menu-builder
- Owner: datlechin
- License: mit
- Created: 2024-08-01T00:12:21.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2025-05-12T08:33:44.000Z (about 1 year ago)
- Last Synced: 2025-05-12T09:57:36.696Z (about 1 year ago)
- Topics: filament, filament-plugin, filamentphp, menu, menu-builder
- Language: PHP
- Homepage:
- Size: 1.67 MB
- Stars: 110
- Watchers: 3
- Forks: 23
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE.md
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
# Filament Menu Builder
[](https://packagist.org/packages/datlechin/filament-menu-builder)
[](https://github.com/datlechin/filament-menu-builder/actions?query=workflow%3Arun-tests+branch%3Amain)
[](https://packagist.org/packages/datlechin/filament-menu-builder)

A [Filament](https://filamentphp.com) plugin for creating and managing menus with drag-and-drop ordering, nested items, custom links, and dynamic menu panels.
## Requirements
- PHP 8.3+
- Filament 5.0+
- Laravel 12+
## Upgrading
### From v0.7.x (Filament v3) to v1.x (Filament v5)
1. Update your `composer.json`:
```bash
composer require datlechin/filament-menu-builder:^1.0
```
2. Publish and run the new migration to add the `panel`, `icon`, and `classes` columns:
```bash
php artisan vendor:publish --tag="filament-menu-builder-migrations"
php artisan migrate
```
The upgrade migration is safe to run even on fresh installs — it checks for existing columns before adding them.
3. If you published the config file, re-publish it to pick up any changes:
```bash
php artisan vendor:publish --tag="filament-menu-builder-config" --force
```
## Installation
Install the package via Composer:
```bash
composer require datlechin/filament-menu-builder
```
Publish and run the migrations:
```bash
php artisan vendor:publish --tag="filament-menu-builder-migrations"
php artisan migrate
```
Optionally publish the config file:
```bash
php artisan vendor:publish --tag="filament-menu-builder-config"
```
Or use the install command:
```bash
php artisan filament-menu-builder:install
```
## Usage
Register the plugin in your Filament panel provider:
```php
use Datlechin\FilamentMenuBuilder\FilamentMenuBuilderPlugin;
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
FilamentMenuBuilderPlugin::make(),
]);
}
```
### Defining Locations
Locations define where menus can be displayed in your application (e.g., header, footer, sidebar):
```php
FilamentMenuBuilderPlugin::make()
->addLocations([
'header' => 'Header',
'footer' => 'Footer',
])
```
### Custom Menu Panels
Menu panels are sources for adding items to menus. You can create panels from Eloquent models or static items.
#### Model Panel
To add a panel from an Eloquent model, implement the `MenuPanelable` interface on your model:
```php
use Datlechin\FilamentMenuBuilder\Contracts\MenuPanelable;
class Page extends Model implements MenuPanelable
{
public function getMenuPanelTitle(): string
{
return $this->title;
}
public function getMenuPanelUrl(): string
{
return route('pages.show', $this);
}
public function getMenuPanelName(): string
{
return 'Pages';
}
}
```
Then register it with the plugin:
```php
use Datlechin\FilamentMenuBuilder\MenuPanel\ModelMenuPanel;
FilamentMenuBuilderPlugin::make()
->addMenuPanels([
ModelMenuPanel::make()
->model(Page::class),
])
```
#### Static Panel
You can also add static items:
```php
use Datlechin\FilamentMenuBuilder\MenuPanel\StaticMenuPanel;
FilamentMenuBuilderPlugin::make()
->addMenuPanels([
StaticMenuPanel::make()
->name('pages')
->add('Home', '/')
->add('About', '/about')
->add('Contact', '/contact'),
])
```
### Custom Link & Custom Text Panels
The custom link panel is shown by default. You can toggle it and also enable the custom text panel (for non-link items like headings):
```php
FilamentMenuBuilderPlugin::make()
->showCustomLinkPanel(true)
->showCustomTextPanel(true)
```
### Custom Fields
You can add extra fields to the menu form or the menu item edit form:
```php
use Filament\Forms\Components\TextInput;
FilamentMenuBuilderPlugin::make()
->addMenuFields([
TextInput::make('description'),
])
->addMenuItemFields([
TextInput::make('badge'),
])
```
### Customizing Navigation
```php
FilamentMenuBuilderPlugin::make()
->navigationLabel('Menus')
->navigationGroup('Content')
->navigationIcon('heroicon-o-bars-3')
->navigationSort(3)
->navigationCountBadge(true)
```
### Indent / Unindent
Nested menu items are supported via indent/unindent actions. This is enabled by default:
```php
FilamentMenuBuilderPlugin::make()
->enableIndentActions(true)
```
### Translatable Menus
The plugin has built-in support for multilingual menu titles. No additional packages are required — translatable fields are stored as JSON and the form UI shows locale tabs.
#### Setup
1. Enable translatable on the plugin with your desired locales:
```php
FilamentMenuBuilderPlugin::make()
->translatable(['en', 'nl', 'vi'])
```
2. Publish and run the translatable migration to convert existing columns from `string` to `json`:
```bash
php artisan vendor:publish --tag="filament-menu-builder-translatable-migrations"
php artisan migrate
```
The migration automatically wraps existing string data in the default locale (`en`). To change the default locale, edit the `$defaultLocale` property in the published migration before running it.
#### Configuring Translatable Fields
By default, only `MenuItem.title` is translatable. You can customize which fields are translatable:
```php
FilamentMenuBuilderPlugin::make()
->translatable(['en', 'nl', 'vi'])
->translatableMenuItemFields(['title']) // default
->translatableMenuFields(['name']) // opt-in: make Menu name translatable too
```
#### Rendering Translated Titles
In your Blade views, use `resolveLocale()` to display the title in the current app locale:
```blade
@foreach($menu->menuItems as $item)
{{ $item->resolveLocale($item->title) }}
@endforeach
```
`resolveLocale()` handles both string and array values — it returns the translation for `app()->getLocale()`, falls back to the first available translation, or returns the string as-is for non-translatable setups.
#### Spatie Translatable Compatibility
The JSON data format is fully compatible with [Spatie Laravel Translatable](https://github.com/spatie/laravel-translatable). If you later add the `HasTranslations` trait to a custom model, the plugin detects it automatically and skips its own JSON casting — Spatie's mutators take over seamlessly.
```php
use Spatie\Translatable\HasTranslations;
class CustomMenuItem extends MenuItem
{
use HasTranslations;
public array $translatable = ['title'];
}
```
### Custom Models
You can replace the default models with your own:
```php
FilamentMenuBuilderPlugin::make()
->usingMenuModel(CustomMenu::class)
->usingMenuItemModel(CustomMenuItem::class)
->usingMenuLocationModel(CustomMenuLocation::class)
```
### Rendering Menus
Retrieve a menu by its location in your views or controllers:
```php
use Datlechin\FilamentMenuBuilder\Models\Menu;
$menu = Menu::location('header');
```
This uses caching under the hood for performance. The cache is automatically busted when menus or menu items are updated.
Loop through menu items:
```blade
@if($menu)
-
@if($item->url)
{{ $item->resolveLocale($item->title) }}
@else
{{ $item->resolveLocale($item->title) }}
@endif@if($item->children->isNotEmpty())
-
{{ $child->resolveLocale($child->title) }}
@foreach($item->children as $child)
@endforeach
@endif
-
@foreach($menu->menuItems as $item)
@endforeach
@endif
```
#### Active State Detection
Menu items provide methods for checking if they match the current URL:
```php
$item->isActive(); // exact URL match
$item->isActiveOrHasActiveChild(); // matches self or any descendant
```
### MenuItem Properties
| Property | Type | Description |
|------------|----------|---------------------------------------|
| `title` | string\|array | The display title (array when translatable) |
| `url` | ?string | The URL (null for text-only items) |
| `target` | string | Link target (`_self`, `_blank`, etc.) |
| `icon` | ?string | Icon identifier (e.g. `heroicon-o-home`) |
| `classes` | ?string | CSS classes for the item |
| `type` | string | Panel name / source type (accessor) |
| `children` | Collection | Nested child items |
## Testing
```bash
composer test
```
## Changelog
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
## License
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.