GithubHelp home page GithubHelp logo

aymanalhattami / filament-page-with-sidebar Goto Github PK

View Code? Open in Web Editor NEW
153.0 3.0 20.0 470 KB

Organize pages in the sidebar in order to make navigation between pages more comfortable.

Home Page: https://github.com/aymanalhattami/filament-page-with-sidebar

License: MIT License

PHP 35.42% Blade 63.71% CSS 0.23% JavaScript 0.64%
filament laravel

filament-page-with-sidebar's Introduction

Filament Page With Sidebar

StandWithPalestine Latest Version on Packagist Total Downloads

Organize pages in the sidebar in order to make navigation between pages more comfortable.

Note: It supports both pages and resource pages.

Note: For Filament 2.x use version 1.x

Screenshots

LTR (Left to Right) filament-page-with-sidebar

RTL (Right to Left) filament-page-with-sidebar

Please check out this video by Povilas Korop (Laravel Daily) to learn more about our package: link

Installation

composer require aymanalhattami/filament-page-with-sidebar

optionally you can publish config, views and components files

php artisan vendor:publish --tag="filament-page-with-sidebar-config"
php artisan vendor:publish --tag="filament-page-with-sidebar-views"

Usage with Resource Pages

  1. First you need to prepare resource pages, for example, we have an edit page, view page, manage page, change password page, and dashboar page for UserResource
use Filament\Resources\Resource;

class UserResource extends Resource 
{
    // ...

    public static function getPages(): array
    {
        return [
            'index' => App\Filament\Resources\UserResource\Pages\ListUsers::route('/'),
            'edit' => App\Filament\Resources\UserResource\Pages\EditUser::route('/{record}/edit'),
            'view' => App\Filament\Resources\UserResource\Pages\ViewUser::route('/{record}/view'),
            'manage' => App\Filament\Resources\UserResource\Pages\ManageUser::route('/{record}/manage'),
            'password.change' => App\Filament\Resources\UserResource\Pages\ChangePasswordUser::route('/{record}/password/change'),
            'dashboard' => App\Filament\Resources\UserResource\Pages\DashboardUser::route('/{record}/dashboard'),
            // ... more pages
        ];
    }

    // ...
}
  1. Define a $record property in each custom page, example
public ModelName $record; // public User $record;
  1. Then, define the sidebar method as static in the resource
use Illuminate\Database\Eloquent\Model;
use Filament\Resources\Resource;
use AymanAlhattami\FilamentPageWithSidebar\FilamentPageSidebar;
use AymanAlhattami\FilamentPageWithSidebar\PageNavigationItem;

class UserResource extends Resource 
{
    // ....

    public static function sidebar(Model $record): FilamentPageSidebar
    {
        return FilamentPageSidebar::make()
            ->setNavigationItems([
                PageNavigationItem::make('User Dashboard')
                    ->url(function () use ($record) {
                        return static::getUrl('dashboard', ['record' => $record->id]);
                    }),
                PageNavigationItem::make('View User')
                    ->url(function () use ($record) {
                        return static::getUrl('view', ['record' => $record->id]);
                    }),
                PageNavigationItem::make('Edit User')
                    ->url(function () use ($record) {
                        return static::getUrl('edit', ['record' => $record->id]);
                    }),
                PageNavigationItem::make('Manage User')
                    ->url(function () use ($record) {
                        return static::getUrl('manage', ['record' => $record->id]);
                    }),
                PageNavigationItem::make('Change Password')
                    ->url(function () use ($record) {
                        return static::getUrl('password.change', ['record' => $record->id]);
                    }),

                // ... more items
            ]);
    }

    // ....
}
  1. Use x-filament-page-with-sidebar::page component in the page blade file as a wrapper for the whole content
// filament.resources.user-resource.pages.change-password-user
<x-filament-page-with-sidebar::page>
    // ... page content
</x-filament-page-with-sidebar::page>

or add the trait AymanAlhattami\FilamentPageWithSidebar\Traits\HasPageSidebar on any page you want the sidebar included. This trait will add the sidebar to the Page. Add it to all your Resource Pages :

// ...
use AymanAlhattami\FilamentPageWithSidebar\Traits\HasPageSidebar;

class ViewUser extends ViewRecord
{
    use HasPageSidebar; // use this trait to activate the Sidebar

    protected static string $resource = UserResource::class;

    protected function getHeaderActions(): array
    {
        return [
            Actions\EditAction::make(),
        ];
    }
}

If you want to use custom view, you can still overwrite the default value with protected static string $hasSidebar = false; and protected static $view = 'filament.[...].user-resource.pages.view-user';

Usage with Page

  1. Add the trait AymanAlhattami\FilamentPageWithSidebar\Traits\HasPageSidebar on any page you want the sidebar included.
  2. Then, define the sidebar method as static in the page
// ...
use AymanAlhattami\FilamentPageWithSidebar\Traits\HasPageSidebar;
use Filament\Pages\Page;

class GeneralSettings extends Page
{
    use HasPageSidebar; // use this trait to activate the Sidebar

    // ...
    public static function sidebar(): FilamentPageSidebar
    {
        return FilamentPageSidebar::make()
            ->setTitle('Application Settings')
            ->setDescription('general, admin, website, sms, payments, notifications, shipping')
            ->setNavigationItems([
                PageNavigationItem::make('General Settings')
                    ->translateLabel()
                    ->url(GeneralSettings::getUrl())
                    ->icon('heroicon-o-cog-6-tooth')
                    ->isActiveWhen(function () {
                        return request()->routeIs(GeneralSettings::getRouteName());
                    })
                    ->visible(true),
                PageNavigationItem::make('Admin Panel Settings')
                    ->translateLabel()
                    ->url(AdminPanelSettings::getUrl())
                    ->icon('heroicon-o-cog-6-tooth')
                    ->isActiveWhen(function () {
                        return request()->routeIs(AdminPanelSettings::getRouteName());
                    })
                    ->visible(true),
                PageNavigationItem::make('Web Settings')
                    ->translateLabel()
                    ->url(WebsiteSettings::getUrl())
                    ->icon('heroicon-o-cog-6-tooth')
                    ->isActiveWhen(function () {
                        return request()->routeIs(WebsiteSettings::getRouteName());
                    })
                    ->visible(true),
                // ...
            ]);
    }
    
    // ...
}

More Options

Set title and description for sidebar

You can set the title or description by using setTitle, setDescription, setDescriptionCopyable methods for the sidebar that will be at the beginning of the sidebar on the top, for example

// ...

public static function sidebar(Model $record): FilamentPageSidebar
{
    return FilamentPageSidebar::make()
        ->setTitle('Sidebar title')
        ->setDescription('Sidebar description')
        ->setDescriptionCopyable()
        ->setNavigationItems([
            PageNavigationItem::make(__('User Dashboard'))
                ->url(function () use ($record) {
                    return static::getUrl('dashboard', ['record' => $record->id]);
                }),
            PageNavigationItem::make(__('View User'))
                ->url(function () use ($record) {
                    return static::getUrl('view', ['record' => $record->id]);
                }),

            // ... more items
        ]);
}

// ...

Set navigation layout

You can set navigation as sidebar by using ->sidebarNavigation() or as topbar by using ->topbarNavigation(). The default layout is sidebar

Sidebar

filament-page-with-sidebar

// ...

public static function sidebar(Model $record): FilamentPageSidebar
{
    return FilamentPageSidebar::make()
        ->sidebarNavigation();
        // 
}

// ...

Topbar

filament-page-with-sidebar

// ...

public static function sidebar(Model $record): FilamentPageSidebar
{
    return FilamentPageSidebar::make()
        ->topbarNavigation();
        // 
}

// ...

Add icon

You can add an icon to the item by using the icon method, for example

// ...

public static function sidebar(Model $record): FilamentPageSidebar
{
    return FilamentPageSidebar::make()
        ->setNavigationItems([
            PageNavigationItem::make('Change Password')
                ->url(function () use ($record) {
                    return static::getUrl('password.change', ['record' => $record->id]);
                })->icon('heroicon-o-collection')

            // ... more items
        ]);
}

// ...

Add group

You may group navigation items, for example

// ...

public static function sidebar(Model $record): FilamentPageSidebar
{
    return FilamentPageSidebar::make()
        ->setNavigationItems([
            PageNavigationItem::make('Change Password')
                ->url(function () use ($record) {
                    return static::getUrl('password.change', ['record' => $record->id]);
                })
                ->group('Manage User')

            // ... more items
        ]);
}

// ...

Set active item

You can make an item active "has a different background color" by using isActiveWhen method, for example

// ...
public static function sidebar(Model $record): FilamentPageSidebar
{
    return FilamentPageSidebar::make()
        ->setNavigationItems([
            PageNavigationItem::make('Change Password')
                ->url(function () use ($record) {
                    return static::getUrl('password.change', ['record' => $record->id]);
                })
                ->isActiveWhen(function () {
                    return request()->route()->action['as'] == 'filament.resources.users.password.change';
                })
            // ... more items
        ]);
}
// ...

Hide the item

You can control the visibility of an item from the sidebar by using visible method, for example

// ...

public static function sidebar(Model $record): FilamentPageSidebar
{
    return FilamentPageSidebar::make()
        ->setNavigationItems([
            PageNavigationItem::make('Change Password')
                ->url(function () use ($record) {
                    return static::getUrl('password.change', ['record' => $record->id]);
                })
                ->visible(false)
            // ... more items
        ]);
}
    ,
// ...

Add bage to the item

You can add a badge to the item by using the badge method, for example

// ...
public static function sidebar(Model $record): FilamentPageSidebar
{
    return FilamentPageSidebar::make()
        ->setNavigationItems([
            PageNavigationItem::make('Change Password')
                ->url(function () use ($record) {
                    return static::getUrl('password.change', ['record' => $record->id]);
                })
                ->badge("badge name")
            // ... more items
        ]);
}
    ,
// ...

Translate the item

You can translate a label by using translateLabel method, for example

// ...
public static function sidebar(Model $record): FilamentPageSidebar
{
    return FilamentPageSidebar::make()->translateLabel()
        ->setNavigationItems([
            PageNavigationItem::make('Change Password')
                ->url(function () use ($record) {
                    return static::getUrl('password.change', ['record' => $record->id]);
                })
            // ... more items
        ]);
}
    ,
// ...

License

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

Demo Project Link

filament-page-with-sidebar's People

Contributors

aymanalhattami avatar faizananwerali avatar fouteox avatar jeffersonsimaogoncalves avatar marco76tv avatar muath-ye avatar thiktak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

filament-page-with-sidebar's Issues

Display/CSS Issue with Initial Setup

Hi there, thanks for making this package. I've setup the package as per the instructions, however there seems to be a display or CSS issue with how the menus are displayed. The top bar also is missing the styles.

They do not match the screenshots in the readme, and can't seem to pickup the existing styles.

I can also see that public/css/aymanalhattami/filament-page-with-sidebar/filament-page-with-sidebar.css is published.

Using version 2.4.2.

image

Can you help on 2nd and 4th steps.

I followed your documentation, but I am stuck at 2nd and 4th points.

  1. public ModelName $record; // public User $record;
  2. // filament.resources.user-resource.pages.change-password-user
    x-filament-page-with-sidebar::page
    // ... page content
    </x-filament-page-with-sidebar::page>

I am not sure where I have added that code, can you specify the names of pages for example of Users?
Thank you

SPA mode

It seems there is no support for SPA mode, is that correct? When we enable SPA mode the page sidebar is not adding wire:navigate to the items.

Or did I miss a setting for it?

Filamet V3

Because Filament V3 still doesn't provide a native way to have a page sidebar, it would be awesome if this package would support the new upcoming V3 version.

Thank you so much for your work!

demo project for filament v3?

demo project for filament v3? the current demo project is still for filament v2, which no longer works with filament v3 because views doesn't work on them, can you please update them?

ViewRessource : Infolist & relation manager

Hello,

I tested this package with a Filament V3, based on a ViewPage with Infolist.
Unfortunately, no relation have been rendered (missing the Tab + content)

Created ressource + sidebar(), with following blade view:

<x-filament-page-with-sidebar::page>
    <x-filament::page>
        {{ $this->infolist }}
    </x-filament::page>
</x-filament-page-with-sidebar::page>

Also tested with <x-filament-panels::page>

When I check filament\resources\view\resources\pages\view-record, we are missing the relation managers panels ( -- and more stuff).
image

Adding the missing part is rendering correctly the panel. But I guess some class & objects could still be missing ?
image

Idea:

  • is it maybe possible to overwrite the layout instead of using a specific view ?
  • A dynamic call of the component that should have been called ?

Ideas : Add group & custom block & actions 1 topSideBar

Hello,

I am using your package, and now I implemented some ideas ... but maybe there is a better way.

Issue 1

Is the dark mode title correct ? text-slate-700 dark:text-navy-100 navy-100 seems a bit off in a dark mode.
image

Idea 1 - Add group.

I know there is NavigationGroup, and subgroup on the main filament package. Effort on these tips or implementing the filament WoW ?

Idea 2 - More than just items

For example, the possibility to include Infolist or custom Html ?

Idea 3 - Add Header, top and/or footer block of Actions ?

For example the header with a triple dot dropdown, or a list of button (group) for top/footer ?

Idea 4 - Possibility to switch left/right sidebar to top (tabs) ?

Or even better: a SideBar and a TopBar ? (with the TopBar we could implement page section (anchor), filters or sub-pages)

Here a preview of some implementation:
image

If the idea seems good for you I can PR this version or separately, but I think some ideas could be reviewed.

My implementations

Groups

page.blade.php

@php
    $sidebar = static::getResource()::sidebar($this->record);
    $items = collect($sidebar->getNavigationItems())->groupBy(function ($it) {
        return $it->getGroup();
    });
@endphp

...

                @foreach ($items as $group => $groupItems)
                    <h3 class="mt-4 mb-2 text-sm font-semibold text-gray-700 dark:text-gray-200">{{ $group }}</h3>
                    <ul class="space-y-2 font-inter font-medium" wire:ignore>
                        @foreach ($groupItems as $item)
                            @if (!$item->isHidden())
                                    <x-filament-page-with-sidebar::item :active="$item->isActive()" :icon="$item->getIcon()"
                                        :active-icon="$item->getActiveIcon()" :url="$item->getUrl()" :badge="$item->getBadge()" :badgeColor="$item->getBadgeColor()"
                                        :shouldOpenUrlInNewTab="$item->shouldOpenUrlInNewTab()">
                                        {{ $item->getLabel() }}
                                    </x-filament-page-with-sidebar::item>
                            @endif
                        @endforeach
                    </ul>
                @endforeach

group / getGroup is already implemented.

Use with ->group('name') (empty go first)

                PageNavigationItem::make('Matrix')
                    ->url(function () use ($record) {
                        return static::getUrl('matrix', ['record' => $record->id]);
                    })
                    ->icon('heroicon-m-table-cells')
                    ->group('Matrix'),

More than Item ?

page.blade.php

                            @if (!$item->isHidden())
                                @if (is_a($item, \AymanAlhattami\FilamentPageWithSidebar\PageNavigationHTML::class))
                                    {!! $item->getHTML() !!}
                                @elseif(is_a($item, \AymanAlhattami\FilamentPageWithSidebar\PageNavigationBlock::class))
                                    {{ $item->render() }}
                                @else
                                    <x-filament-page-with-sidebar::item [...]

I also created a PageNavigationHTML (in order to add divider <hr />) with html() (or content()) and getHtml().

and new class:

use Closure;
use Filament\Infolists\Concerns\InteractsWithInfolists;
use Filament\Infolists\Contracts\HasInfolists;
use Filament\Infolists\Infolist;
use Filament\Navigation\NavigationItem;
use Illuminate\Support\HtmlString;

class PageNavigationBlock extends \Livewire\Component implements HasInfolists
{
    use InteractsWithInfolists;
    use \Filament\Infolists\Components\Concerns\HasChildComponents;

    protected string | Closure | null $group = null;

    public function group(string | Closure | null $group): static
    {
        $this->group = $group;

        return $this;
    }

    public function getGroup(): mixed
    {
        return $this->group;
    }

    public function isHidden()
    {
        return false;
    }

    static public function make(): static
    {
        return new self();
    }

    public function blockInfolist(Infolist $infolist): Infolist
    {
        return $infolist
            ->schema($this->childComponents);
    }

    public function render()
    {
        $i = new \Filament\Infolists\Infolist($this);
        $i->name('PageNavigationBlock');

        return new HtmlString($this->blockInfolist($i)->render());
    }
}

And usage with;

                    PageNavigationBlock::make()
                        ->schema([
                            \Filament\...\Infolists\...Entry::make()
                                ->label(false)
                        ])
                        ->group('More')

Documentation needs improvement.

I am tinkering with Filament for the last 2 days. And I needed a multilevel menu and found this package via Laravel daily. Its a great and versatile package but I had to go through the demo project to figure out how things worked.

So I think introducing some steps in the usage section will greatly improve the user experience.

Great package by the way and thanks for your work.

Error in define a $record property in each custom page

When to set a $record property on each custom page this error

Type of App\Filament\Resources\IssuerResource\Pages\EditIssuer::$record must not be defined (as in class Filament\Resources\Pages\EditRecord)

and the Demo Project Link not working

Tks

Dropdown for mobile view

Hello,

Thanks for a great plugin.
You saved a lot of time and effort for us.

I have a question about is it possible to make a quick mobile view for this plugin?
When the list gets bigger, it is more complex on mobile. For example;

Screenshot 2023-05-16 at 17 42 35

Maybe it is useful to put a dropdown when mobile view is enabled is a better approach.
I have limited CSS knowledge, because of that I opened an issue.
Do you have a quick solution for this?

Thanks.

Keep side navigation on left

Hi,

because every filament page has a "container" wrapped around and the sidebar is added for each page in the view, the sidebar is also inside the container, which shortens the amount of space inside the container (for the rest of the forms etc.) and create a big gap on larger screens between the normal sidebar and the page sidebar.

Is there any possible way to prevent this and always have the sidebar on the left outside the container?

Thank you for your work!

[question] does this only for resource?

Hello, can I implement this package for filament pages instead of resources?
my case is I want to make a Settings page which hase some tabs (account setting, security, and so on)
I've tried but I got error ::getResource does not exist.

License

Hey, would you mind adding a License to your project?
I would like to fork your Project and modify it to work for custom pages.

A license I find really nice and would suggest is the MIT license however since it is your project it is obviously up to you.

Thank you for your great work!

SetTitle() Light Mode

image
Light Mode

image
Dark Mode

use AymanAlhattami\FilamentPageWithSidebar\FilamentPageSidebar;
use AymanAlhattami\FilamentPageWithSidebar\PageNavigationItem;
public static function sidebar(Model $record): FilamentPageSidebar
    {
        return FilamentPageSidebar::make()
            ->setTitle($record->name)
            ->setDescription($record->email)
            ->setNavigationItems([
                PageNavigationItem::make('View User')
                    ->url(function () use ($record) {
                        return static::getUrl('view', ['record' => $record->id]);
                    }),
            ]);
    }

Source Code

Not Visible when in light mode. Currently using Filament v.3.0.102.

[IDEA] Support custom pages

Hi @aymanalhattami, thank you for the great package.

I suggest you support custom pages also. Every project had some pages unrelated to resource but related to the same aim, like setting pages. It'll be helpful to sort these pages together.

I got conflict issue with File upload

When I enable to a create page, I got livewire error and then conflict to the Forms\Components\FileUpload fail to work.
image

I also modify the page.blade file, since I got issue with responsive menu in mobile screen for the sidebar
image

Please advise how I could fix this.

The active item loses the activity indication when working with components

Package version : 2.4.2

On first open page, menu item has indication "active", on work with any components (table filters, sorting, trigger button actions) menu item loses indication.

->isActiveWhen(function () {
    return request()->routeIs(static::getRouteBaseName() . '.activities.user');
})

Filament package has "Sub Navigation", and when you update components, its state remains unchanged. This can be clearly seen if you use, for example, this code

->label(function() {
    return request()->route()->getName() . ' | ' . microtime(true);
})

Steps to reproduce
Repo : https://github.com/aymanalhattami/filament-page-with-sidebar-project
Url : http://127.0.0.1:8000/admin/users/1/activities/user
Open page "User Activities", menu item "User Activities" has indication "active".
On click 'View' button on any record, a modal popup will be open.
Close modal popup.
Current menu item "User Activities" without indication "active".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.