Внешний вид

Меню

Основы

Menu является основой для навигации по админ-панели, поэтому мы постарались создать гибкую систему, которая позволит вам сделать полную кастомизацию меню для разных страниц и пользователей.

Настройка навигационного меню осуществляется в классе, который расширяет MoonShine\Laravel\Layouts\AppLayout через метод menu().

В процессе установки админ-панели, в зависимости от выбранных вами конфигураций, будет создан класс App\MoonShine\Layouts\MoonShineLayout, который уже содержит метод menu().

В дальнейшем, если вам потребуется, вы сможете создавать другие Layout для определенных страниц.

Попробуйте так же альтернативный способ генерации меню с помощью автозагрузки.

Элементы

Для того чтобы добавить пункт меню, необходимо воспользоваться классом MenuItem.

make(
Closure|string $label,
Closure|MenuFillerContract|string $filler,
string $icon = null,
Closure|bool $blank = false,
)
  • $label - название пункта меню,
  • $filler - элемент для формирования url,
  • $icon - иконка для пункта меню,
  • $blank - открыть в новой вкладке.

В качестве второго параметра можно передать ModelResource, Page или CrudResource.

 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuItem::make('Admins', MoonShineUserResource::class),
MenuItem::make('Home', fn() => route('home')),
MenuItem::make('Docs', 'https://moonshine-laravel.com/docs'),
MenuItem::make('Laravel Docs', 'https://laravel.com/docs', blank: true),
];
}
}

Если меню создается для ModelResource или CrudResource, для элемента меню будет использоваться первая страница, объявленная в методе pages().

Группы

Пункты меню можно объединять в группы. Для этого воспользуетесь классом MenuGroup.

make(
Closure|string $label,
iterable $items,
string|null $icon = null,
)
  • $label - название группы,
  • $items - массив компонентов меню,
  • $icon - иконка для группы.
 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuGroup::make('System', [
MenuItem::make('Admins', MoonShineUserResource::class),
MenuItem::make('Roles', MoonShineUserRoleResource::class),
])
];
}
}

Также группе можно добавить элементы через метод setItems().

setItems(iterable $items)
 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuGroup::make('System')->setItems([
MenuItem::make('Admins', MoonShineUserResource::class),
MenuItem::make('Roles', MoonShineUserRoleResource::class),
])
];
}
}

Для создания многоуровневого меню, группы можно делать вложенными.

Разделитель

Пункты меню можно визуально разделить с помощью MenuDivider.

/**
* @param (Closure(MenuElementContract $context): string)|string $label
*/
make(Closure|string $label = '')
 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuDivider;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuItem::make('Admins', MoonShineUserResource::class),
MenuDivider::make(),
MenuItem::make('Roles', MoonShineUserRoleResource::class),
];
}
}

Иконка

У пункта меню и у группы можно задать иконку. Это можно реализовать несколькими методами.

Через параметр

Иконку можно задать, передав третьим параметром название в статическом методе make().

 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuItem::make('Admins', MoonShineUserResource::class, 'users'),
MenuItem::make('Roles', MoonShineUserRoleResource::class, 'hashtag')
];
}
}

Через метод

Воспользоваться методом icon().

icon(
string $icon,
bool $custom = false,
?string $path = null,
)
  • $icon - название иконки или html (если используется кастомный режим),
  • $custom - кастомный режим,
  • $path - путь до директории где лежат Blade шаблоны иконок.
 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuGroup::make('System', [
MenuItem::make('Admins', MoonShineUserResource::class)
->icon('users'),
MenuItem::make('Roles', MoonShineUserRoleResource::class)
->icon(svg('path-to-icon-pack')->toHtml(), custom: true),
])
->icon('cog', path: 'icons')
];
}
}

Через атрибут

У пункта меню отобразится иконка, если у класса ModelResource, Page или Resource задан атрибут Icon и иконка не переопределена другими способами.

 namespaces
namespace MoonShine\Resources;
 
#[Icon('users')]
class MoonShineUserResource extends ModelResource
{
// ...
}

За более подробной информацией обратитесь к разделу Иконки.

Метка

Также есть возможность добавить значок к пункту меню.

Через элемент меню

Для добавления значка к пункту меню используется метод badge(), который в качестве параметра принимает замыкание.

/**
* @param Closure(MenuElementContract $context): string|int|float|null $value
*/
badge(Closure|string|int|float|null $value)
namespace App\MoonShine\Layouts;
 
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
 
// ...
 
protected function menu(): array
{
return [
MenuItem::make('Comments', CommentResource::class)
->badge(fn() => Comment::count())
];
}
}

Перевод

Для перевода пунктов меню необходимо в качестве названия передать ключ перевода и добавить метод translatable().

translatable(string $key = '')
 namespaces
namespace App\MoonShine\Layouts;
 
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuItem::make('menu.Comments', CommentResource::class)
->translatable()
// or
MenuItem::make('Comments', CommentResource::class)
->translatable('menu')
];
}
}
// lang/ru/menu.php
 
return [
'Comments' => 'Комментарии',
];

Для перевода меток меню можно воспользоваться средствами перевода Laravel.

namespace App\MoonShine\Layouts;
 
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuItem::make('Comments', CommentResource::class)
->badge(fn() => __('menu.badge.new'))
];
}
}

Открытие в новой вкладке

У пункта меню можно указать флаг, указывающий, открывать ссылку в новой вкладке или нет. Это можно реализовать несколькими способами.

Через параметр

Флаг можно задать, передав четвёртым параметром true/false или замыкание в статическом методе make().

 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuItem::make('MoonShine Docs', 'https://moonshine-laravel.com/docs', 'heroicons.arrow-up', true),
MenuItem::make('Laravel Docs', 'https://laravel.com/docs', blank: fn() => true),
];
}
}

Через метод

Воспользоваться методом blank().

/**
* @param (Closure(MenuElementContract $context): bool)|bool $blankCondition
*/
blank(Closure|bool $blankCondition = true)
 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuItem::make('MoonShine Docs', 'https://moonshine-laravel.com/docs', 'heroicons.arrow-up', true),
MenuItem::make('Laravel Docs', 'https://laravel.com/docs')->blank(fn() => true),
];
}
}

Условие отображения

Отображать элементы меню можно по условию, воспользовавшись методом canSee().

/**
* @param Closure(MenuElementContract $context): bool $callback
*/
canSee(Closure $callback)
 namespaces
namespace App\Providers;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuDivider;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuGroup::make('System', [
MenuItem::make('Admins', MoonShineUserResource::class),
MenuDivider::make()
->canSee(fn() => true),
MenuItem::make('Roles', MoonShineUserRoleResource::class)
->canSee(fn() => false)
])
->canSee(static fn(): bool => request()->user('moonshine')?->id === 1)
];
}
}

Активный пункт

Пункт меню становится активным если он соответствует url, но метод whenActive() позволяет принудительно сделать пункт активным.

/**
* @param Closure(string $path, string $host, MenuElementContract $context): bool $when
*/
whenActive(Closure $when)
 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuItem::make('Label', '/endpoint')
->whenActive(fn() => request()->fullUrlIs('*admin/endpoint/*')),
];
}
}

Атрибуты

Группам и элементам меню, как и другим компонентам, можно назначить кастомные атрибуты.

За более подробной информацией обратитесь к разделу Атрибуты компонентов.

 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\Laravel\Resources\MoonShineUserResource;
use MoonShine\Laravel\Resources\MoonShineUserRoleResource;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuGroup::make('System')->setItems([
MenuItem::make('Admins', MoonShineUserResource::class),
MenuItem::make('Roles', MoonShineUserRoleResource::class)
->customAttributes(['class' => 'group-li-custom-class'])
])
->setAttribute('data-id', '123')
->class('group-li-custom-class')
];
}
}

Изменение кнопки

Пункт меню является ActionButton и изменить его атрибуты можно, воспользовавшись методом changeButton.

/**
* @param Closure(ActionButtonContract $button): ActionButtonContract $callback
*/
changeButton(Closure $callback)
 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\MenuManager\MenuItem;
use MoonShine\UI\Components\ActionButton;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuItem::make('Label', '/endpoint')
->changeButton(static fn(ActionButton $button) => $button->class('new-item')),
];
}
}

Некоторые параметры ActionButton, такие, как url, badge, icon и другие, системно переопределяются. Для их изменения используйте соответствующие методы.

Изменение шаблона

Если нужно изменить view с использованием fluent interface, можно применить метод customView().

customView(string $path)
  • $path - путь до Blade шаблона.
 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
use MoonShine\MenuManager\MenuGroup;
use MoonShine\MenuManager\MenuItem;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return [
MenuGroup::make('Group', [
MenuItem::make('Label', '/endpoint')
->customView('admin.custom-menu-item'),
])
->customView('admin.custom-menu-group'),
];
}
}

Чтобы активировать альтернативный вариант создания меню, замените массив в методе menu() на вызов метода autoloadMenu().

 namespaces
namespace App\MoonShine\Layouts;
 
use MoonShine\Laravel\Layouts\AppLayout;
 
final class MoonShineLayout extends AppLayout
{
// ...
 
protected function menu(): array
{
return $this->autoloadMenu();
}
}

Если вам нужно пропустить страницу или ресурс в меню, используйте атрибут SkipMenu.

 namespaces
use MoonShine\MenuManager\Attributes\SkipMenu;
 
#[SkipMenu]
class ProfilePage extends Page {}

Если вам нужно объединить страницы или ресурсы в группы, используйте атрибут Group. Элементы будут сгруппированы по названию. В атрибуте так же можно указать иконку и флаг translatable.

 namespaces
use MoonShine\MenuManager\Attributes\Group;
 
#[Group('moonshine::ui.profile', 'users', translatable: true)]
class ProfilePage extends Page {}

Если вам нужно отобразить элемент меню по условию, используйте атрибут CanSee. Добавьте метод в ресурсе или странице, который будет отвечать за условие отображения.

 namespaces
use MoonShine\MenuManager\Attributes\CanSee;
 
#[CanSee(method: 'someMethod')]
class ArticleResource extends ModelResource
{
public function someMethod(): bool
{
return false;
}
}

Если вам нужно задать порядок элементов меню, используйте атрибут Order.

 namespaces
use MoonShine\MenuManager\Attributes\Order;
 
#[Order(1)]
class ArticleResource extends ModelResource {}