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

Related tags

Laravel navigator
Overview

Navigator

Tests

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')
        ->when($user->can('access.dashboard'))
])

// In a view

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

// Or as json...

Nav::toJson()

This is a headless package so you are completely free to style as you see fit.

Installation

You can install the package via composer:

composer require nedwors/navigator

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

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
Nav

Item

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

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

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 package which itself uses the awesome Heroicons icon set. They can be defined as follows - perhaps to use with a dynamic component:

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

$item->heroicon
Conditionals

You can define conditionals to determine if the given Item should be displayed or not:

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

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

They can also be composed:

Nav::item('Billing')
    ->when($aCheck)
    ->unless($someOtherCheck)
    ->when($yetAnotherCheck)

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

This behaviour can be modified if desired

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

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. Also, generators can be passed as the sub menu:

Nav::item('Billing')->subItems(fn () => yield from [
    // Sub Items here...
])

To learn more, see the 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 decendant and determining if it is active or not, you can call hasActiveDecendants:

@if ($item->hasActiveDecendants)
...
@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 decendants are active, even though hasActiveDecendants will return true, active will not. This only applies to the Item is accessed on.

Nav

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

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. Under the hood, the Items are held as a LazyCollection to aid performance. As such, a generator can be returned instead of a plain array:

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

This probably won't be needed on most projects, but the power is there if needed.

The closure that you pass to define receives both auth()->user() and app() for convenience - think for 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

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 LazyCollection 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

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

All those 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

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', 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

composer test

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

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

Credits

License

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

You might also like...
A premade, easy to use local development setup to be used for authoring Laravel applications

Laravel Drydock This project is a premade, easy to use local development setup to be used for authoring Laravel applications. The deliverables of this

A super simple package allowing for use MySQL 'USE INDEX' and 'FORCE INDEX' statements.
A super simple package allowing for use MySQL 'USE INDEX' and 'FORCE INDEX' statements.

Laravel MySQL Use Index Scope A super simple package allowing for use MySQL USE INDEX and FORCE INDEX statements. Requirements PHP ^7.4 | ^8.0 Laravel

This package lets you add uuid as primary key in your laravel applications

laravel-model-uuid A Laravel package to add uuid to models Table of contents Installation Configuration Model Uuid Publishing files / configurations I

Laravel package integrating PHP Flasher into Livewire applications
Laravel package integrating PHP Flasher into Livewire applications

A powerful and flexible flash notifications system for PHP, Laravel, Symfony 👀 PHP Flasher helps you to add flash notifications to your PHP projects.

Laravel ecommerce package for professional, ultra fast online shops, complex B2B applications and #gigacommerce
Laravel ecommerce package for professional, ultra fast online shops, complex B2B applications and #gigacommerce

Aimeos Laravel ecommerce package ⭐ Star us on GitHub — it helps! Aimeos is THE professional, full-featured and ultra fast e-commerce package for Larav

A simple to use query builder for the jQuery QueryBuilder plugin for use with Laravel.
A simple to use query builder for the jQuery QueryBuilder plugin for use with Laravel.

QueryBuilderParser Status Label Status Value Build Insights Code Climate Test Coverage QueryBuilderParser is designed mainly to be used inside Laravel

A laravel package to handle sanitize process of model data to create/update model records.

Laravel Model UUID A simple package to sanitize model data to create/update table records. Installation Require the package using composer: composer r

This package enables you to create and run a fully functioning WebSocket server in your Laravel app.

This package enables you to create and run a fully functioning WebSocket server in your Laravel app. It can optionally receive messages broadcast over ZeroMQ.

🏭This package lets you create factory classes for your Laravel project.
🏭This package lets you create factory classes for your Laravel project.

Laravel Factories Reloaded 🏭 This package generates class-based model factories, which you can use instead of the ones provided by Laravel. Laravel 8

Comments
  • L9

    L9

    Building on the work by @kamilpiech97 and @Baakoma, this PR adds support for Laravel 9 and PHP 8.1. It also updates the pipeline.

    Breaks

    This PR refactors the core to remove support for LazyCollections and generators. (I don't think they were been used properly anyway 😆 )

    opened by nedwors 0
Releases(0.5.0)
Owner
Sam Rowden
Sam Rowden
Build structured navigation menus in Filament.

Build structured navigation menus in Filament. This plugin for Filament provides a Navigation resource that allows to build structural navigation menu

HappyToDev 0 Jun 29, 2022
Fullstack komponents to write Forms, Queries and Menus in Laravel

kompo.io • Documentation • Demos • Twitter kompo/kompo kompo/kompo is a library of Fullstack Komponents to help you write forms, queries and menus in

Bass El Hachem 107 Dec 5, 2022
Build XML based USSD menus.

Instead of having tonnes of nested, complex PHP files, this package give you the ability to construct your menus in XML and execute them as though they were plain PHP files.

Brian Matovu 6 Oct 6, 2022
Framework agnostic PHP package for marking navigation items active.

Ekko Framework agnostic PHP package for marking navigation items active. Features Framework agnostic. Can be modified for any custom application and U

Laravelista 275 Jul 27, 2022
A mostly useless package to display framework versions at the bottom of the Admin navigation panel.

A mostly useless package to display framework versions at the bottom of the Filament Admin navigation panel and an optional widget to do the same in the dashboard or custom pages.

Adam Weston 10 Nov 8, 2022
Generator-hedley - Scaffold a headless Drupal backend, Angular app client, and Behat tests

generator-hedley Scaffold a headless Drupal backend, Angular app client, and Behat tests Hedley is a yeoman generator that scaffolds a headless Drupal

null 99 Jun 3, 2022
A Laravel chat package. You can use this package to create a chat/messaging Laravel application.

Chat Create a Chat application for your multiple Models Table of Contents Click to expand Introduction Installation Usage Adding the ability to partic

Tinashe Musonza 931 Dec 24, 2022
Zarinpal is a laravel package to easily use zarinpal.com payment services in your applications

پکیج اتصال به درگاه پرداخت زرین پال zarinpal.com برای اتصال به درگاه پرداخت اینترنتی زرین پال و استفاده از api های آن می توانید از این پکیج استفاده کن

Rahmat Waisi 4 Jan 26, 2022
Nebula is a minimalistic and easy to use administration tool for Laravel applications, made with Laravel, Alpine.js, and Tailwind CSS.

Nebula Nebula is a minimalistic and easy to use administration tool for Laravel applications, made with Laravel, Alpine.js, and Tailwind CSS. Nebula m

Nebula 228 Nov 11, 2022
A Laravel package that allows you to use multiple ".env" files in a precedent manner. Use ".env" files per domain (multi-tentant)!

Laravel Multi ENVs Use multiple .envs files and have a chain of precedence for the environment variables in these different .envs files. Use the .env

Allyson Silva 48 Dec 29, 2022