Files
XC_VM/docs/ru/development/navbar-rendering.md
T
Divarion-D f4555e7943 docs: reorganize structure, sync with current code, add missing framework reference
Structure:
- Split development/ (20 files) into development/ (framework reference) and guides/ (how-to)
- Moved 13 how-to files into new guides/ category (auth, cli, error-handling, etc.)
- Moved navbar-rendering.md from system/ into development/
- Deleted empty system/README.md files
- Deleted documentation_gaps.md (all gaps resolved) and redundant info/update.md

Sidebar / navbar:
- Removed all emojis from _sidebar.md (EN + RU) — fixes tree hierarchy rendering
- Removed flag emojis from _navbar.md language switcher
- Removed duplicate entries from the old "System Documentation" section
- Renamed section headers: "Development" -> "Framework Reference" + "Developer Guides"

Content fixes (modules.md EN + RU):
- Updated "Class naming" section: now documents XcVm\Module\{Pascal} namespaces
  (was "global PHP namespace — Until PHP namespaces are introduced")
- Updated main module class example to use namespace declaration + use statements
- Updated class naming in ModuleLoader description to FQN
- Replaced installCrontab() manual crontab instruction with getCronEntries() API
- Updated enable/disable section: added ModuleState enum table, updated config examples
- Fixed FAQ answer for disabling a module

Content fixes (bootstrap-contexts.md EN + RU):
- Replaced CONTEXT_* string constants with BootContext enum cases throughout
- Updated boot() signature: string $context -> BootContext $context
- Updated getContext() return type: ?string -> ?BootContext

New framework reference docs (EN + RU):
- docs/{en,ru}/development/event-system.md: EventDispatcher singleton bridge,
  #[ListensTo] attribute, getEventSubscribers() array API, stoppable events,
  built-in event catalog, custom event authoring, ListensTo attribute reference
- docs/{en,ru}/development/exception-hierarchy.md: full XcVmException tree,
  container vs module subtrees, PSR-11 compliance notes, catch-by-subsystem examples
2026-06-15 18:27:23 +03:00

3.6 KiB
Raw Blame History

Рендер navbar в панели модулей

Техническая документация по формированию и рендерингу navbar в админ-панели.

Назначение

Navbar строится декларативно из дерева NavbarItem, а не из hardcoded HTML-меню.

Источник дерева:

  1. Core-узлы из CoreNavbarProvider::register().
  2. Модульные узлы из ModuleInterface::registerNavbar().

Жизненный цикл

  1. ModuleLoader::bootAll() вызывает CoreNavbarProvider::register().
  2. Затем для каждого загруженного модуля вызывается registerNavbar().
  3. В public/Views/admin/header.php дерево рендерится из NavbarRegistry.

Рендер в header

Рендер выполняется helper-функциями:

  1. _xc_nav_visible() — фильтрация видимости узла.
  2. _xc_nav_label() — получение текстовой подписи.
  3. _xc_nav_children() — рекурсивный вывод дочерних пунктов.

Верхний уровень берётся через NavbarRegistry::getTopLevel(), дочерние узлы — через NavbarRegistry::getChildren($key).

Правила видимости

Проверки выполняются в _xc_nav_visible():

  1. desktopOnly: скрывает узел на мобильных.
  2. settingDisabled: скрывает узел при включённом settings-флаге.
  3. permissions: OR-проверка через Authorization::check('adv', $permission).
  4. Группа с url='#' показывается только если есть хотя бы один видимый потомок.
  5. divider всегда пропускается в рендер как разделитель.

Особенности рендера

  1. divider выводится как разделитель без ссылки.
  2. submenuClass('megamenu') включает двухколоночный вывод длинных списков.
  3. noMobileSubmenu выключает раскрытие дочернего меню на мобильных.

Как модулю добавить кнопку

Модуль добавляет пункты только через registerNavbar():

public function registerNavbar(): void {
    NavbarRegistry::add((new NavbarItem('management.service_setup.my_module'))
        ->parent('management.service_setup')
        ->url('my_module')
        ->label('my_module')
        ->permissions(['my_module'])
        ->order(60));

    NavbarRegistry::add((new NavbarItem('management.logs.my_module_log'))
        ->parent('management.logs')
        ->url('my_module_logs')
        ->label('', 'My Module Logs')
        ->permissions(['my_module'])
        ->order(170));
}

Практические правила для модулей

  1. Используйте уникальные key в формате section.group.item.
  2. Указывайте существующий parent из core-дерева или своего уже добавленного узла.
  3. Позиционируйте пункты через order внутри одного parent.
  4. Используйте label('translation_key') для переводимых строк.
  5. Используйте label('', 'Literal Text') для фиксированного текста.
  6. Если модуль не добавляет меню, оставляйте registerNavbar() пустым.