Files
XC_VM/docs/en/development/navbar-rendering.md
T
Divarion-D 76844fef11 docs: restructure, fix PSR-4 drift, and unify en/ru
Overhaul the Docsify documentation (English + Russian) so it matches the current
codebase and follows one consistent pattern.

Content accuracy (post-migration):
- Rewrite development/autoloader.md to PSR-4 / Composer (the old XC_Autoloader
  scanner, igbinary tmp/cache/autoload_map and registerDirectories are gone).
- PascalCase every source path (src/core -> src/Core, domain/Stream, cli/Commands,
  public/Controllers, Infrastructure/Redis, ...) across all docs.
- Replace the removed autoload.php references with vendor/autoload.php
  (build_system, bootstrap-contexts, error-handling, modules).
- ssl-generation: note that the installer now auto-generates a unique self-signed
  certificate before Nginx starts.

Common pattern (Clean & uniform):
- Strip emoji from headings; remove the in-page Navigation blocks (the Docsify
  sidebar already provides navigation).
- One H1 + intro per doc; uniform "Related files" / "Связанные файлы" section,
  added to the code-centric docs that lacked it.

Structure:
- Remove the empty stray docs/api/; move updates_checklist.md into builds/;
  link the previously-orphaned ucs-integration.md.
- Regroup the sidebars (split the oversized guides group into Developer Guides /
  Security & Access / Integrations; fold builds into Build & Release).

Augment:
- dev-workflow: Local Setup (make dev-tools) + Quality Checks (phpstan, cs, gates).
- build_system: Composer Dependencies section (committed prod-only vendor,
  committed lock, dev tools via composer install, no build-time vendor step).

en/ru parity:
- Apply the same structure, fixes and pattern to docs/ru/ (translated), including
  a new Russian ucs-integration.md. The en and ru file sets are now identical.
2026-06-26 15:56:15 +03:00

2.8 KiB

Navbar rendering in module panel

Technical documentation for building and rendering the navbar in the admin panel.

Purpose

The navbar is built declaratively from a NavbarItem tree, not from hardcoded HTML menus.

Tree sources:

  1. Core nodes from CoreNavbarProvider::register().
  2. Module nodes from ModuleInterface::registerNavbar().

Lifecycle

  1. ModuleLoader::bootAll() calls CoreNavbarProvider::register().
  2. Then registerNavbar() is called for each loaded module.
  3. In Public/Views/admin/header.php, the tree is rendered from NavbarRegistry.

Rendering in header

Rendering is done by helper functions:

  1. _xc_nav_visible() - visibility filtering for a node.
  2. _xc_nav_label() - text label resolution.
  3. _xc_nav_children() - recursive rendering of child items.

Top-level nodes come from NavbarRegistry::getTopLevel(), child nodes come from NavbarRegistry::getChildren($key).

Visibility rules

Checks are performed in _xc_nav_visible():

  1. desktopOnly: hides node on mobile.
  2. settingDisabled: hides node when a setting flag is enabled.
  3. permissions: OR-check via Authorization::check('adv', $permission).
  4. A group with url='#' is shown only if at least one child is visible.
  5. divider is always passed through and rendered as separator.

Rendering specifics

  1. divider renders as separator without a link.
  2. submenuClass('megamenu') enables two-column rendering for long lists.
  3. noMobileSubmenu disables child submenu expansion on mobile.

How a module adds a menu item

A module adds items only through 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));
}

Practical rules for modules

  1. Use unique key values in section.group.item format.
  2. Set parent to an existing core tree node or your own already-added node.
  3. Position items using order inside one parent.
  4. Use label('translation_key') for translatable text.
  5. Use label('', 'Literal Text') for fixed literal text.
  6. If the module has no menu items, keep registerNavbar() empty.
File Role
src/Core/Module/NavbarRegistry.php Collects navbar items from providers
src/Core/Module/NavbarItem.php Navbar item value object
src/Core/Module/CoreNavbarProvider.php Built-in core menu items
src/Public/Views/admin/header.php Renders the navbar tree