rawilk/filament-inner-nav

为 filament 面板页面添加内嵌导航。

资助包维护!
rawilk

安装: 355

依赖者: 0

建议者: 0

安全性: 0

星标: 3

关注者: 2

分支: 1

开放问题: 1

语言:Blade

v1.1.1 2023-12-04 14:20 UTC

README

Latest Version on Packagist Tests Total Downloads PHP from Packagist License

Social image

filament-inner-nav 包允许您将 Filament 面板中的资源页面组织成一组“内嵌导航”页面。这对于拥有许多子页面的资源页面非常有用,例如查看/编辑用户记录时。

base screenshot

安装

您可以通过 composer 安装此包

composer require rawilk/filament-inner-nav

您可以使用以下命令发布配置文件

php artisan vendor:publish --tag="filament-inner-nav-config"

您可以在以下位置查看默认配置: https://github.com/rawilk/filament-inner-nav/blob/main/config/filament-inner-nav.php

可以使用以下命令发布视图

php artisan vendor:publish --tag="filament-inner-nav-views"

用法

  1. 首先,您需要生成一个 Filament 资源页面,然后将您的自定义资源页面添加到 getPages 数组中。例如,一个 UserResource

    use App\Filament\Resources\UserResource\Pages;
    use Filament\Resources\Resource;
    
    class UserResource extends Resource
    {
        // ...
    
        public static function getPages(): array
        {
            'index' => Pages\ListUsers::route('/'),
            'create' => Pages\CreateUser::route('/create'),
            'edit' => Pages\EditUser::route('/{record}/edit'),
    
            // custom pages...
            'authentication' => Pages\UserAuthentication::route('/{record}/authentication'),
            'contact' => Pages\Contact::route('/{record}/contact'),
            'activity' => Pages\Activity::route('/{record}/activity'),
        }
    
        // ...
    }
  2. 在您的每个自定义资源页面上定义一个 $record 属性

    public ModelName $record; // public User $record;

    请务必将 ModelName 更改为您的模型类名。

  3. 在您的资源上定义一个 innerNav 静态方法

    use App\Models\User;
    use Filament\Resources\Resource;
    use Rawilk\FilamentInnerNav\InnerNav;
    use Rawilk\FilamentInnerNav\InnerNavItem;
    
    class UserResource extends Resource
    {
        // ...
    
        public static function innerNav(User $record): InnerNav
        {
            return InnerNav::make()
                ->setNavigationItems([
                    InnerNavItem::make('Edit User')
                        ->url(fn (): string => static::getUrl('edit', ['record' => $record])),
                    InnerNavItem::make('Password & Authentication')
                        ->url(fn (): string => static::getUrl('authentication', ['record' => $record])),
                    InnerNavItem::make('Contact Information')
                        ->url(fn (): string => static::getUrl('contact', ['record' => $record])),
                    InnerNavItem::make('Activity')
                        ->url(fn (): string => static::getUrl('activity', ['record' => $record])),
                ]);
        }
    }
  4. 在每个自定义页面上,使用 <x-filament-inner-nav::page> Blade 组件包裹内容

    <!-- file: filament.resources.user-resource.pages.authentication -->
    <x-filament-panels::page>
        <x-filament-inner-nav::page>
            <!-- page content here -->
        </x-filament-inner-nav::page>
    </x-filament-panels::page>

如果导航样式不正确,您可能需要运行 filament:upgrade 命令来确保发布最新的资源。

高级用法

启用 wire:navigate

通过在 InnerNav 对象上使用 wireNavigate() 方法,允许使用 livewire 的 wire:navigate

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->wireNavigate()
        ->setNavigationItems([
            // ...
        ]);
}

此选项可以在服务提供器中全局配置。请参阅 全局配置

标题 & 描述

您可以通过在 InnerNav 对象上使用 setTitle()setDescription() 方法设置导航的标题和/或描述。这些将直接显示在导航项上方。

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->setTitle('Nav title')
        ->setDescription('Nav description')
        ->setNavigationItems([
            // ...
        ]);
}

对于更高级的定制,您可以从闭包中返回一个 HtmlString 对象,使用这些方法中的任何一个

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->setTitle(fn (): HtmlString => new HtmlString('<h1>' . $record->name . '</h1>'))
        ->setDescription(fn (): HtmlString => new HtmlString('<p>Nav description</p>'))
        ->setNavigationItems([
            // ...
        ]);
}

如果需要,您也可以通过在 title() 方法的闭包中调用 view('...') 来返回一个自定义视图。

项目图标

您可以通过在 InnerNavItem 对象上使用 icon() 方法为每个导航项设置一个图标。

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->setNavigationItems([
            InnerNavItem::make('Edit User')
                ->url(fn (): string => static::getUrl('edit', ['record' => $record]))
                ->icon('heroicon-o-pencil'),
        ]);
}

项目激活状态

默认情况下,没有设置任何导航项的激活状态。您可以通过在 InnerNavItem 对象上调用 isActiveWhen() 方法来设置激活状态。

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->setNavigationItems([
            InnerNavItem::make('Edit User')
                ->url(fn (): string => static::getUrl('edit', ['record' => $record]))
                ->isActiveWhen(fn (): bool => request()->route()->action['as'] === 'filament.resources.users.edit')
        ]);
}

项目可见性

可以通过在 InnerNav 对象上调用 visible()hidden() 方法来隐藏项目,使其在 UI 中不可见。

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->setNavigationItems([
            InnerNavItem::make('Edit User')
                ->url(fn (): string => static::getUrl('edit', ['record' => $record]))
                ->visible(fn (): bool => auth()->user()->can('edit', $record)),
        ]);
}

禁用项目

在某些情况下,您可能仍然想显示导航链接,但禁用用户实际访问它。您可以使用 InnerNavItem 对象上的 isDisabledWhen() 方法来实现这一点。

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->setNavigationItems([
            InnerNavItem::make('Edit User')
                ->url(fn (): string => static::getUrl('edit', ['record' => $record]))
                ->isDisabledWhen(fn (): bool => ! auth()->user()->can('edit', $record)),
        ]);
}

项目徽章

您可以通过在 InnerNavItem 对象上调用 badge() 方法向任何导航项添加徽章。

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->setNavigationItems([
            InnerNavItem::make('Edit User')
                ->url(fn (): string => static::getUrl('edit', ['record' => $record]))
                ->badge('New'),
        ]);
}

分组

您可以使用 InnerNavGroup 对象在导航中将项目分组。一个组可以是可折叠的或静态的。可折叠的组可以嵌套在静态组内部。下面是每个组的示例。

可折叠组

可折叠分组允许您在可以切换项目可见性的按钮下方嵌套一组导航项。这个UI的设计灵感来源于GitHub在您的账户设置页面上处理子导航的方式。

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->setNavigationItems([
            InnerNavItem::make('Edit User')
                ->url(fn (): string => static::getUrl('edit', ['record' => $record])),
            InnerNavGroup::make('Settings')
                ->icon('heroicon-o-cog')
                ->items([
                    InnerNavItem::make('Group item 1')
                        ->url('#'),
                    InnerNavItem::make('Group Item 2')
                        ->url('#'),
                ])
        ]);
}

collapsible group

注意:InnerNavGroup对象上,icon方法是可选的。

InnerNavGroup下方的InnerNavItem对象不允许有图标。

默认情况下,可折叠分组是折叠的。您可以通过调用InnerNavGroup对象上的expandByDefault()方法来更改此设置。如果组内的任何项目被设置为活动状态,组也将展开。

静态分组

也受GitHub UI的启发,静态分组允许您在标题下方渲染导航链接。您需要做的就是向InnerNavGroup对象上的collapsible()方法提供一个假值。

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
            ->setNavigationItems([
                InnerNavItem::make('Edit User')
                    ->url(fn () => self::getUrl('edit', ['record' => $record]))
                    ->icon('heroicon-o-user'),
                InnerNavGroup::make('Settings')
                    ->collapsible(false)
                    ->items([
                        InnerNavGroup::make('Sub Group')
                            ->icon('heroicon-o-rectangle-stack')
                            ->items([
                                InnerNavItem::make('Sub group item 1')
                                    ->url('#'),
                            ]),
                        InnerNavItem::make('Group item 1')
                            ->icon('heroicon-o-rectangle-stack')
                            ->url('#'),
                        InnerNavItem::make('Group Item 2')
                            ->icon('heroicon-o-rectangle-stack')
                            ->url('#'),
                    ]),
}

static group

与可折叠分组不同,直接InnerNavItem子项允许有图标。

顶部布局

如果您想将链接渲染在内容顶部而不是侧边,您可以使用InnerNav对象上的setLayout()方法。

use Rawilk\FilamentInnerNav\Enums\InnerNavLayout;
use Rawilk\FilamentInnerNav\InnerNav;

public static function innerNav(User $record): InnerNav
{
    return InnerNav::make()
        ->setLayout(InnerNavLayout::Top)
        ->setNavigationItems([
            // ...
        ]);
}

top layout

使用此布局添加的任何InnerNavGroup对象都将渲染为下拉菜单。

全局配置

许多在InnerNavInnerNavItemInnerNavGroup对象上的选项都可以进行全局配置,通常在某个服务提供者中。

use Illuminate\Support\ServiceProvider;
use Rawilk\FilamentInnerNav\Enums\InnerNavLayout;
use Rawilk\FilamentInnerNav\InnerNav;
use Rawilk\FilamentInnerNav\InnerNavGroup;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        InnerNav::configureUsing(function (InnerNav $nav) {
            $nav
                ->wireNavigate()
                ->setLayout(InnerNavLayout::Side);
        });

        InnerNavGroup::configureUsing(function (InnerNavGroup $group) {
            // Expand collapsible groups by default.
            $group->expandByDefault();
        });
    }
}

样式

此包提供的UI的许多部分都带有自定义CSS类前缀,您可以使用自己的样式覆盖这些样式。所有类名都将以fi-inner-nav-开头,例如,导航项都有一个类名为fi-inner-nav-item

在此列出和维护所有使用的类名并不实用,因此如果您想要对某个元素进行不同的样式设计,您可以在浏览器中检查该元素或查看此存储库中blade组件的源代码。

如果需要样式的元素没有自定义类,您可以提交一个PR来添加一个类,但我不能保证我会合并它。

脚本

设置

为了方便,您可以运行设置二进制脚本来轻松安装本地开发。

./bin/setup.sh

格式化

虽然格式化是通过工作流程自动完成的,但您可以在提交之前使用composer脚本来本地格式化PHP代码。

composer format

测试

composer test

变更日志

请参阅变更日志以获取有关最近更改的更多信息。

贡献

请参阅贡献指南以获取详细信息。

安全性

请审查我的安全策略以了解如何报告安全漏洞。

致谢

替代方案

此包的一些替代方案包括

如果您有类似的包想要添加,请提交一个PR并更新README。

许可协议

MIT许可协议(MIT)。请参阅许可文件以获取更多信息。