Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Menu Laravel Package

spatie/menu

Fluent, extensible menu builder for Laravel. Compose navigation with a clean API, render as HTML, and customize output via presenters and macros. Supports active state handling, links, submenus, and easy integration with Blade and your app’s routing.

View on GitHub
Deep Wiki
Context7

Getting Started

Begin by installing the package via Composer:

composer require spatie/menu

In Laravel, the service provider auto-registers. Start building a menu using the fluent Menu builder — for example, in a service provider or a dedicated menu class:

use Spatie\Menu\Menu;
use Spatie\Menu\Html\Link;

$menu = Menu::new()
    ->addItem(Link::to('/', 'Home'))
    ->addItem(Link::to('/about', 'About'))
    ->addItem(Link::to('/contact', 'Contact'));

Render it directly in a Blade view:

{!! $menu !!}

The first use case is typically a site-wide main navigation — simple, static links with optional active-state highlighting.

Implementation Patterns

  • Reusable Menu Classes: Encapsulate menu logic in dedicated classes (e.g., MainMenu) in app/Menus, resolving them via dependency injection or facades for consistency across views.
  • Dynamic Links & Conditions: Use closures for active-state logic based on current route, query parameters, or user permissions:
    ->addItem(Link::to('/admin', 'Admin')->when(fn() => Auth::user()->isAdmin()))
    ->addItem(Link::to('/dashboard', 'Dashboard')->activeWhen(fn() => request()->is('dashboard*')))
    
  • Nested Submenus: Build dropdowns or sidebars with nested Menu instances:
    ->addItem((new Menu)
        ->addItem(Link::to('/settings/profile', 'Profile'))
        ->addItem(Link::to('/settings/password', 'Password'))
        ->setLabel('Settings'))
    
  • Custom HTML Items: Inject icons, dividers, or custom markup using Html::item('<li class="divider"></li>').
  • Blade Rendering Hooks: Pass variables into Blade views for styling — e.g., ->setAttributes(['class' => 'nav-item']) or use the attributes() method for per-item markup control.
  • Integration with Laravel Routing: Tie menu items to named routes with Link::toRoute('home', 'Home') or Link::toAction('HomeController@index', 'Home').

Gotchas and Tips

  • Auto-escaping: Menu renders raw HTML — always trust your generated content. Never inject untrusted user input directly into items. Use Html::raw() only when safe.
  • Active State Pitfall: The default activeWhen(fn() => request()->is($path)) is a simple string match — use request()->path() or Route::is() for more accurate route matching.
  • Nested Menu Rendering: Submenus auto-render as <ul> wrappers unless customised. Override wrapper classes using ->setWrapperTag('div')->setWrapperAttributes([...]) on the submenu instance.
  • Extensibility: Extend Spatie\Menu\MenuItem to create domain-specific items (e.g., DropdownItem, MenuItemWithIcon) or register custom renderers via Menu::setRenderer().
  • Performance: Avoid heavy logic (e.g., DB queries) inside menu closures. Cache resolved menus or use lazy closures with once() if needed.
  • Styling Tips: Use Tailwind or Bootstrap? Prefer Link::to(...)->addClass('px-4 py-2 text-gray-700') over inline styles. Add activeClass('font-bold text-blue-500') for visual feedback.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport