PHPackages                             nedwors/navigator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. nedwors/navigator

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

nedwors/navigator
=================

A Laravel package to ease defining navigation menus

3.0.0(2mo ago)433.1k3MITPHPPHP ^8.3CI passing

Since Nov 16Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/nedwors/navigator)[ Packagist](https://packagist.org/packages/nedwors/navigator)[ Docs](https://github.com/nedwors/navigator)[ RSS](/packages/nedwors-navigator/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (12)Versions (17)Used By (0)

[![](https://camo.githubusercontent.com/f34a59f7f8a30c8bc0e3f8c89726ce13f9031bcd2d609e87c97a55c452e5c696/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f4e6176696761746f722e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d6e6564776f72732532466e6176696761746f72267061747465726e3d6d656c74267374796c653d7374796c655f31266465736372697074696f6e3d412b686561646c6573732b4c61726176656c2b6e617669676174696f6e2b6d656e752b7061636b616765266d643d312673686f7757617465726d61726b3d3126666f6e7453697a653d313030707826696d616765733d7365617263682d636972636c65)](https://camo.githubusercontent.com/f34a59f7f8a30c8bc0e3f8c89726ce13f9031bcd2d609e87c97a55c452e5c696/68747470733a2f2f62616e6e6572732e6265796f6e64636f2e64652f4e6176696761746f722e706e673f7468656d653d6c69676874267061636b6167654d616e616765723d636f6d706f7365722b72657175697265267061636b6167654e616d653d6e6564776f72732532466e6176696761746f72267061747465726e3d6d656c74267374796c653d7374796c655f31266465736372697074696f6e3d412b686561646c6573732b4c61726176656c2b6e617669676174696f6e2b6d656e752b7061636b616765266d643d312673686f7757617465726d61726b3d3126666f6e7453697a653d313030707826696d616765733d7365617263682d636972636c65)

Navigator
=========

[](#navigator)

[![Tests](https://github.com/nedwors/laravel-menu/actions/workflows/main.yml/badge.svg)](https://github.com/nedwors/laravel-menu/actions/workflows/main.yml/badge.svg)

Navigator is a package to create headless navigation menus for use in Laravel applications:

```
// In a Service Provider

Nav::define(fn ($user) => [
    Nav::item('Dashboard')
        ->for('dashboard')
        ->icon('dashboard.svg')
        ->includeWhen($user->can('access.dashboard'))
])

// In a view

@foreach(navitems() as $item)
    //
@endforeach

// Or as json...

Nav::toJson()
```

> This is a headless package, the styling is left to you!

Requirements
------------

[](#requirements)

Navigator requires PHP 8.3 or higher and Laravel 13 or higher.

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require nedwors/navigator
```

Usage
-----

[](#usage)

Select a Service Provider - or perhaps make a dedicated one - and pop the following in:

```
Nav::define(fn () => [
    Nav::item('Dashboard')
        ->for('dashboard')
        ->icon('dashboard')
]);
```

Et voila! You now have a menu ready to use. You can retrieve the items as follows:

```
@foreach(navitems())
    //
@endforeach

// or

@foreach(Nav::items())
    //
@endforeach
```

Now, you'll probably want more than just a dashboard link - then again maybe not, it's your app! - but hopefully you can see how easy it is to get up and running.

Let's dig further into the features available to you:

### API

[](#api)

The package consists of two main features - each `Nav` and the `Items` within. We will explore the `Item` and then the `Nav`.

It's worth noting at this point that `Item` extends `Illuminate\Support\Fluent` to allow for custom methods/properties on a per project basis. Also, `Nav` is macroable to allow for custom functionality in your projects.

##### `Item`

[](#item)

- [Name](#name)
- [URL](#url)
- [Icons](#icons)
- [Conditionals](#conditionals)
- [Determining Active Status](#determining-active-status)
- [Sub Items](#sub-items)

##### `Nav`

[](#nav)

- [Define](#define)
- [Items](#items)
- [toJson](#tojson)
- [Filter](#filter)
- [Active When](#active-when)

#### `Item`

[](#item-1)

##### Name

[](#name)

A new `Item` is created using the `Nav::item()` method. This method receives the name of the `Item`:

```
Nav::item('Dashboard')

$item->name // Dashboard
```

> The name is passed into the Laravel `__()` lang helper before outputting.

##### URL

[](#url)

The url is defined and retrieved as follows:

```
Nav::item('Dashboard')->for('/dashboard')

$item->url // /dashboard
```

The `for()` method can also be used to construct Laravel routes:

```
Nav::item('Dashboard')->for('dashboard.show', $customer)
```

The url is not required for an item to function. By default, all items have a `null` url.

##### Icons

[](#icons)

A reference to an icon in your app can be defined and retrieved as follows:

```
Nav::item('Dashboard')->icon('dashboard.svg')

$item->icon
```

You may want to use the awesome [Blade Heroicons](https://github.com/blade-ui-kit/blade-heroicons) package which itself uses the awesome [Heroicons](https://heroicons.com/) icon set. They can be defined as follows - perhaps to use with a [dynamic component](https://laravel.com/docs/master/blade#dynamic-components):

```
Nav::item('Dashboard')->heroicon('o-cog')

$item->heroicon
```

##### Conditionals

[](#conditionals)

You can define conditionals to determine if the given `Item` should be included or not in the menu:

```
Nav::item('Billing')->includeWhen(auth()->user()->is_subscribed)

Nav::item('Registration')->includeUnless(auth()->user()->is_subscribed)
```

They can also be composed:

```
Nav::item('Billing')
    ->includeWhen($aCheck)
    ->includeUnless($someOtherCheck)
    ->includeWhen($yetAnotherCheck)
```

When your nav items are loaded, any falsey `Items` are filtered out by default.

> This behaviour can be [modified if desired](#filter)

##### Determining Active Status

[](#determining-active-status)

A basic need of any menu item is to determine if it is active or not. To do so, simply access the `active` property:

```
@if ($item->active)
...
@endif
```

> By default, an `Item` will return true if the current URL matches its URL. You can [configure this behaviour](#active-when)

##### Sub Items

[](#sub-items)

Creating sub items for any given item is simple - just define as so:

```
Nav::item('Billing')->subItems([
    Nav::item('Invoices'),
    ...
])
```

There's no limit to the number of sub menus you can have, and sub menus themselves can have sub menus. It's probably rare that would be needed, but the power is there if needed:

```
Nav::item('Billing')->subItems([
    // Sub Items here...
])
```

> To learn more, see the [`define`](#define) section.

A common need with sub menus is determing if any of the sub items are active, perhaps to expand the drop down list of the parent `Item`. Rather than looping through each descendant and determining if it is [`active`](#determining-active-status) or not, you can call `hasActiveDescendants`:

```
@if ($item->hasActiveDescendants)
...
@endif
```

This will return true regardless of nesting - even for grandchildren or great-great-greatgrandchildren (you get the idea). If one of a parent's descendants are active, even though `hasActiveDescendants` will return `true`, `active` will not. This only applies to the `Item` is accessed on.

#### Nav

[](#nav-1)

Now we've seen how to make some `Items`, we need to actually make a menu! At its simplest, we can define a menu and retrieve a menu. But we also have control over advanced functions such as filtering. Let's start by making a menu:

#### Define

[](#define)

To create a menu, use the `define` method:

```
Nav::define(fn () => [
    // Items go here...
]);
```

As you can see, the `define` method should be passed a closure that returns an `iterable`.

The closure that you pass to define receives both `auth()->user()` and `app()` for convenience - think for [`conditionals`](#conditionals):

```
Nav::define(fn (?Authenticable $user, Application $app) => [
    // Items go here...
]);
```

How about multiple menus? No problem, just pass the menu name as the second argument to each menu definition:

```
Nav::define(fn () => [
    // Items go here...
], 'admin');
```

#### Items

[](#items)

Now we've defined the menus, we need to output them in our views! This can be acheived by:

```
Nav::items()

// or

navitems()
```

Both these return a `Collection` of the menu `Items`. If you need access to a specific menu, this can be passed as an argument:

```
Nav::items('admin')

// or

navitems('admin')
```

> You will want to add an alias to your `app.php` config file to use `Nav::items()` without the full namespace

#### toJson

[](#tojson)

Nav items can also be retrieved as their json representation:

```
Nav::toJson()
```

Just like `Nav::items()`, if you need access to a specific menu, this can be passed as an argument:

```
Nav::toJson('admin')
```

#### Filter

[](#filter)

All those [`conditionals`](#conditionals) you set up need to do something right? Well, by default all `Items` that are not truthy because of their conditionals will be filtered out. If you would like to control what should be filtered out, use the `filter` method. This method accepts a `Closure`with the same structure as a `Collection` filter:

```
Nav::filter(fn (Item $item) => ...)
```

You can also define filters for multiple menus:

```
Nav::filter(fn (Item $item) => ..., 'app')
Nav::filter(fn (Item $item) => ..., 'admin')
```

> All `filters` are applied to all sub items of the given menu too.

You probably won't need to use this functionality, but it's there if needed.

#### Active When

[](#active-when)

By default, `Items` active property will be true when the current url is the `Item's` url. This applies whether you defined the `Item` using a named route or a url. If you would like to override what constitutes an `Item` as being active, you cna use the `activeWhen` method. This should be passed a `Closure` that receives an `Item`:

```
Nav::activeWhen(fn (Item $item) => ...)
```

This may be useful for use cases outside the realms of traditional routing. Like [`filter'](#filter), this can be defined per menu:

```
Nav::activeWhen(fn (Item $item) => ..., 'app')
Nav::activeWhen(fn (Item $item) => ..., 'admin')
```

> The active check will be used for all sub menus within the menu too.

### Testing

[](#testing)

```
composer test
```

### Changelog

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. Please see [UPGRADING](UPGRADING.md) for upgrading information.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

### Security

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Sam Rowden](https://github.com/nedwors)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

56

—

FairBetter than 98% of packages

Maintenance88

Actively maintained with recent releases

Popularity33

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor1

Top contributor holds 95.9% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~105 days

Recently: every ~77 days

Total

16

Last Release

62d ago

Major Versions

0.x-dev → 1.0.02025-03-19

1.x-dev → 2.0.02025-05-28

2.x-dev → 3.0.02026-03-18

PHP version history (5 changes)0.1.0PHP ^8.0

0.3.0PHP ^8.0|^8.1

0.7.0PHP ^8.0|^8.1|^8.2|^8.3

1.0.0PHP ^8.2

3.0.0PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/8581f7aef8679c8f7501cd36239817172bd23a8c83804055f41c73b44e93642f?d=identicon)[nedwors](/maintainers/nedwors)

---

Top Contributors

[![nedwors](https://avatars.githubusercontent.com/u/59183434?v=4)](https://github.com/nedwors "nedwors (71 commits)")[![lukeraymonddowning](https://avatars.githubusercontent.com/u/12202279?v=4)](https://github.com/lukeraymonddowning "lukeraymonddowning (2 commits)")[![BrayanCaro](https://avatars.githubusercontent.com/u/41640423?v=4)](https://github.com/BrayanCaro "BrayanCaro (1 commits)")

---

Tags

laravelmenunavigationnedwors

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/nedwors-navigator/health.svg)

```
[![Health](https://phpackages.com/badges/nedwors-navigator/health.svg)](https://phpackages.com/packages/nedwors-navigator)
```

###  Alternatives

[caffeinated/menus

Laravel Menus

134159.5k5](/packages/caffeinated-menus)[akaunting/laravel-menu

Menu and sidebar management package for Laravel

38233.8k](/packages/akaunting-laravel-menu)[kodicomponents/navigation

The KodiCMS Support package.

12232.6k10](/packages/kodicomponents-navigation)[rinvex/laravel-menus

Rinvex Menus is a simple menu builder package for Laravel, that supports hierarchical structure, ordering, and styling with full flexibility using presenters for easy styling and custom structure of menu rendering.

294.0k20](/packages/rinvex-laravel-menus)[nguyendachuy/laravel-menu

Laravel Menu Builder | Drag &amp; Drop | Bootstrap | Laravel 7 | Laravel 8 | Laravel 9 | Laravel 10 | Laravel 11 | Laravel 12

162.2k](/packages/nguyendachuy-laravel-menu)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
