owl-concept / menu-bundle
Bundle Symfony pour la navigation dynamique — sidebar repliable, topbar, breadcrumbs, groupes accordion, badges, icônes, filtrage par rôles, détection active automatique.
Package info
github.com/Jaecko/owl-menu-bundle
Type:symfony-bundle
pkg:composer/owl-concept/menu-bundle
Requires
- php: >=8.1
- symfony/framework-bundle: ^6.4 || ^7.0
- symfony/security-bundle: ^6.4 || ^7.0
- symfony/twig-bundle: ^6.4 || ^7.0
- twig/twig: ^3.0
Suggests
- owl-concept/settings-bundle: Pour persister la préférence sidebar_collapsed via owl-settings
- owl-concept/theme-bundle: Pour utiliser les variables CSS du thème OWL dans la sidebar
This package is auto-updated.
Last update: 2026-05-06 15:50:39 UTC
README
🇫🇷 Français
Bundle Symfony pour la navigation dynamique — sidebar repliable, topbar horizontale, breadcrumbs auto-générés, groupes accordion, badges, icônes, filtrage par rôles, détection active automatique.
Fonctionnalités
- Sidebar repliable — largeur 260px → 60px (icônes seules) avec transition fluide
- Topbar horizontale — alternative navbar avec dropdowns
- Breadcrumbs auto-générés — fil d'Ariane basé sur la hiérarchie du menu
- Groupes accordion — sous-menus pliables avec animation
- Badges / Compteurs — notifications visuelles sur les items
- Icônes — préfixe configurable (Bootstrap Icons, FontAwesome, etc.)
- Filtrage par rôles — masque les items selon les rôles Symfony
- Détection active automatique — highlight basé sur l'URL courante
- Anti-flash — script inline lit localStorage avant le premier rendu
- Responsive — burger menu sur mobile ≤ 768px
- Variables CSS — fonctionne avec ou sans
owl-theme-bundle - Zéro dépendance JS — vanilla JS, pattern IIFE
Installation
composer require owl-concept/menu-bundle
Configuration
# config/packages/owl_menu.yaml owl_menu: css_class_prefix: 'owl-menu' # Préfixe BEM collapse_storage: 'localStorage' # localStorage | settings active_detection: 'auto' # auto | manual icon_prefix: 'bi bi-' # Préfixe CSS des icônes
Utilisation
Créer un menu dans un contrôleur ou service
use OwlConcept\MenuBundle\Builder\MenuBuilder; class AppController extends AbstractController { public function index(MenuBuilder $menuBuilder): Response { $menu = $menuBuilder->create('sidebar') ->addItem('dashboard', 'Tableau de bord', '/dashboard', [ 'icon' => 'house', ]) ->addGroup('crm', 'CRM', ['icon' => 'people'], function ($group) { $group->addItem('clients', 'Clients', '/clients', [ 'badge' => 5, 'badge_color' => 'danger', ]) ->addItem('contacts', 'Contacts', '/contacts'); }) ->addDivider() ->addItem('settings', 'Paramètres', '/settings', [ 'icon' => 'gear', 'position' => 'bottom', 'roles' => ['ROLE_ADMIN'], ]) ->setCollapsible(true) ->setActiveAuto(true) ->build(); return $this->render('base.html.twig', ['menu' => $menu]); } }
Templates Twig
{# Sidebar #} {% include '@OwlMenu/sidebar.html.twig' with { menu: menu } %} {# Topbar (alternative) #} {% include '@OwlMenu/topbar.html.twig' with { menu: menu } %} {# Breadcrumb #} {% include '@OwlMenu/breadcrumb.html.twig' with { menu: menu } %}
Fonctions Twig
{# Récupérer un menu enregistré par ID #} {% set menu = owl_menu('sidebar') %} {# Breadcrumb depuis l'ID #} {% set crumbs = owl_menu_breadcrumb('sidebar') %} {# Vérifier si un item est actif #} {% if owl_menu_is_active('clients') %}...{% endif %} {# Icône HTML #} {{ owl_menu_icon('house') }} {# → <i class="bi bi-house"></i> #} {# Préfixe CSS #} {{ owl_menu_prefix() }} {# → owl-menu #}
Options des items
| Option | Type | Défaut | Description |
|---|---|---|---|
icon |
string |
null |
Nom de l'icône (sans préfixe) |
badge |
int|string |
null |
Texte ou compteur du badge |
badge_color |
string |
null |
Couleur : danger, warning, success |
roles |
string[] |
[] |
Rôles Symfony requis (OR) |
position |
string |
default |
default ou bottom |
target |
string |
null |
Attribut target du lien |
css_class |
string |
null |
Classe CSS supplémentaire |
divider_before |
bool |
false |
Séparateur avant l'item |
divider_after |
bool |
false |
Séparateur après l'item |
Détection active (scoring URL)
Le bundle compare l'URL courante avec chaque item :
| URL courante | Item /dashboard |
Item /clients |
Item /contacts |
|---|---|---|---|
/dashboard |
100 (exact) | 0 | 0 |
/clients/123/edit |
0 | 8 (prefix) | 0 |
/contacts |
0 | 0 | 100 (exact) |
L'item avec le score le plus élevé est marqué actif, et son groupe parent est auto-déplié.
Intégrations optionnelles
- owl-theme-bundle — les variables CSS
var(--owl-*)sont automatiquement utilisées - owl-settings-bundle —
collapse_storage: settingspersiste l'état via DBAL
Assets
{# CSS #} <link rel="stylesheet" href="{{ asset('bundles/owlmenu/css/owl-menu.css') }}"> {# JS (en fin de body) #} <script src="{{ asset('bundles/owlmenu/js/owl-menu.js') }}"></script>
Installer les assets :
php bin/console assets:install public
API JavaScript
// Accéder à l'API window.OwlMenu.init(); // Ré-initialiser (après AJAX) // Écouter les événements document.addEventListener('owl-menu:collapse', function(e) { console.log(e.detail.id, e.detail.collapsed); }); document.addEventListener('owl-menu:mobile', function(e) { console.log(e.detail.id, e.detail.open); });
🇬🇧 English
Symfony bundle for dynamic navigation — collapsible sidebar, horizontal topbar, auto-generated breadcrumbs, accordion groups, badges, icons, role-based filtering, automatic active detection.
Features
- Collapsible sidebar — 260px → 60px (icons only) with smooth transition
- Horizontal topbar — alternative navbar with dropdowns
- Auto-generated breadcrumbs — breadcrumb trail based on menu hierarchy
- Accordion groups — collapsible sub-menus with animation
- Badges / Counters — visual notifications on items
- Icons — configurable prefix (Bootstrap Icons, FontAwesome, etc.)
- Role-based filtering — hides items based on Symfony roles
- Automatic active detection — highlight based on current URL
- Anti-flash — inline script reads localStorage before first paint
- Responsive — burger menu on mobile ≤ 768px
- CSS variables — works with or without
owl-theme-bundle - Zero JS dependencies — vanilla JS, IIFE pattern
Installation
composer require owl-concept/menu-bundle
Configuration
# config/packages/owl_menu.yaml owl_menu: css_class_prefix: 'owl-menu' # BEM prefix collapse_storage: 'localStorage' # localStorage | settings active_detection: 'auto' # auto | manual icon_prefix: 'bi bi-' # Icon CSS prefix
Usage
Create a menu in a controller or service
use OwlConcept\MenuBundle\Builder\MenuBuilder; class AppController extends AbstractController { public function index(MenuBuilder $menuBuilder): Response { $menu = $menuBuilder->create('sidebar') ->addItem('dashboard', 'Dashboard', '/dashboard', [ 'icon' => 'house', ]) ->addGroup('crm', 'CRM', ['icon' => 'people'], function ($group) { $group->addItem('clients', 'Clients', '/clients', [ 'badge' => 5, 'badge_color' => 'danger', ]) ->addItem('contacts', 'Contacts', '/contacts'); }) ->addDivider() ->addItem('settings', 'Settings', '/settings', [ 'icon' => 'gear', 'position' => 'bottom', 'roles' => ['ROLE_ADMIN'], ]) ->setCollapsible(true) ->setActiveAuto(true) ->build(); return $this->render('base.html.twig', ['menu' => $menu]); } }
Twig Templates
{# Sidebar #} {% include '@OwlMenu/sidebar.html.twig' with { menu: menu } %} {# Topbar (alternative) #} {% include '@OwlMenu/topbar.html.twig' with { menu: menu } %} {# Breadcrumb #} {% include '@OwlMenu/breadcrumb.html.twig' with { menu: menu } %}
Twig Functions
{# Get a registered menu by ID #} {% set menu = owl_menu('sidebar') %} {# Breadcrumb from ID #} {% set crumbs = owl_menu_breadcrumb('sidebar') %} {# Check if an item is active #} {% if owl_menu_is_active('clients') %}...{% endif %} {# Icon HTML #} {{ owl_menu_icon('house') }} {# → <i class="bi bi-house"></i> #} {# CSS prefix #} {{ owl_menu_prefix() }} {# → owl-menu #}
Item Options
| Option | Type | Default | Description |
|---|---|---|---|
icon |
string |
null |
Icon name (without prefix) |
badge |
int|string |
null |
Badge text or counter |
badge_color |
string |
null |
Color: danger, warning, success |
roles |
string[] |
[] |
Required Symfony roles (OR logic) |
position |
string |
default |
default or bottom |
target |
string |
null |
Link target attribute |
css_class |
string |
null |
Additional CSS class |
divider_before |
bool |
false |
Divider before item |
divider_after |
bool |
false |
Divider after item |
Active Detection (URL scoring)
The bundle compares the current URL against each item:
| Current URL | Item /dashboard |
Item /clients |
Item /contacts |
|---|---|---|---|
/dashboard |
100 (exact) | 0 | 0 |
/clients/123/edit |
0 | 8 (prefix) | 0 |
/contacts |
0 | 0 | 100 (exact) |
The item with the highest score is marked active, and its parent group is auto-expanded.
Optional Integrations
- owl-theme-bundle — CSS variables
var(--owl-*)are automatically used - owl-settings-bundle —
collapse_storage: settingspersists state via DBAL
Assets
{# CSS #} <link rel="stylesheet" href="{{ asset('bundles/owlmenu/css/owl-menu.css') }}"> {# JS (at end of body) #} <script src="{{ asset('bundles/owlmenu/js/owl-menu.js') }}"></script>
Install assets:
php bin/console assets:install public
JavaScript API
// Access the API window.OwlMenu.init(); // Re-initialize (after AJAX) // Listen to events document.addEventListener('owl-menu:collapse', function(e) { console.log(e.detail.id, e.detail.collapsed); }); document.addEventListener('owl-menu:mobile', function(e) { console.log(e.detail.id, e.detail.open); });
License
Proprietary — All rights reserved.