diff --git a/doc/book/menu-configuration.rst b/doc/book/menu-configuration.rst index 6fff0f99ad..9c9836655a 100644 --- a/doc/book/menu-configuration.rst +++ b/doc/book/menu-configuration.rst @@ -94,6 +94,26 @@ the ``icon`` option and leave it empty or set it to ``null``: - { entity: 'Product', icon: '' } # ... +CSS Classes +~~~~~~~~~~~ + +Applications that need full customization, for example to display each menu item +with a different color or style, can define the ``css_class`` option for one or +more menu items: + +.. code-block:: yaml + + easy_admin: + design: + menu: + - { entity: 'User', css_class: 'menu--user' } + - { entity: 'Product', css_class: 'menu--product text-bold text-center' } + - { entity: 'Category', css_class: 'default' } + # ... + +The CSS class is applied to the ```` element that wraps both the icon and +the label of the menu item. + Targets ~~~~~~~ diff --git a/src/Configuration/MenuConfigPass.php b/src/Configuration/MenuConfigPass.php index 916280415b..fd43ea51e3 100644 --- a/src/Configuration/MenuConfigPass.php +++ b/src/Configuration/MenuConfigPass.php @@ -86,6 +86,11 @@ private function normalizeMenuConfig(array $menuConfig, array $backendConfig, $p $itemConfig['icon'] = 'fa-'.$itemConfig['icon']; } + // normalize css_class configuration + if (!array_key_exists('css_class', $itemConfig)) { + $itemConfig['css_class'] = ''; + } + // normalize submenu configuration (only for main menu items) if (!isset($itemConfig['children']) && -1 === $parentItemIndex) { $itemConfig['children'] = array(); diff --git a/src/Resources/views/default/menu.html.twig b/src/Resources/views/default/menu.html.twig index 916df14631..7b77607b4e 100644 --- a/src/Resources/views/default/menu.html.twig +++ b/src/Resources/views/default/menu.html.twig @@ -18,7 +18,7 @@ {% set path = path(item.route, menu_params|merge(item.params)) %} {% endif %} - + {% if item.icon is not empty %}{% endif %} {{ item.label|trans(domain = translation_domain) }} {% if item.children|default([]) is not empty %}{% endif %} diff --git a/tests/Controller/CustomMenuTest.php b/tests/Controller/CustomMenuTest.php index 44c8fd4400..2ea354aa01 100644 --- a/tests/Controller/CustomMenuTest.php +++ b/tests/Controller/CustomMenuTest.php @@ -124,6 +124,41 @@ public function testMenuIcons() ); } + public function testMenuCssClasses() + { + $crawler = $this->getBackendHomepage(); + + $this->assertSame( + 'label-custom-css-class', + $crawler->filter('.sidebar-menu li:contains("Products") a')->attr('class'), + 'First level label menu item with custom CSS class' + ); + + $this->assertSame( + 'entity-custom-css-class', + $crawler->filter('.sidebar-menu li:contains("Images") a')->attr('class'), + 'First level entity menu item with custom CSS class' + ); + + $this->assertSame( + '', + $crawler->filter('.sidebar-menu li:contains("Purchases") a')->attr('class'), + 'First level entity menu item without custom CSS class' + ); + + $this->assertSame( + 'route-custom-css-class', + $crawler->filter('.sidebar-menu li:contains("Custom Internal Route") a')->attr('class'), + 'First level route menu item with custom CSS class' + ); + + $this->assertSame( + 'children-custom-css-class', + $crawler->filter('.sidebar-menu .treeview-menu li:contains("Categories") a')->attr('class'), + 'Second level menu item with custom CSS class' + ); + } + public function testMenuTargets() { $crawler = $this->getBackendHomepage(); diff --git a/tests/Fixtures/App/config/config_custom_menu.yml b/tests/Fixtures/App/config/config_custom_menu.yml index 20773318a5..e8663eb998 100644 --- a/tests/Fixtures/App/config/config_custom_menu.yml +++ b/tests/Fixtures/App/config/config_custom_menu.yml @@ -9,13 +9,14 @@ easy_admin: menu: - label: 'Products' icon: 'shopping-basket' + css_class: 'label-custom-css-class' children: - { entity: 'Product', icon: 'th-list', label: 'List Products', params: { sortField: 'createdAt' } } - { entity: 'Product', label: 'Add Product', params: { action: 'new' } } - { label: 'Additional Items' } - - { entity: 'Category', label: 'Categories', default: true, icon: '' } + - { entity: 'Category', label: 'Categories', default: true, icon: '', css_class: 'children-custom-css-class' } - { label: 'Absolute URL', url: 'https://github.com/javiereguiluz/EasyAdminBundle' } - - { label: 'Images', entity: 'Image' } + - { label: 'Images', entity: 'Image', css_class: 'entity-custom-css-class' } - { label: 'Purchases', entity: 'Purchase', icon: '', params: { sortField: 'deliveryDate', customParameter: 'customValue' } } - { label: 'About EasyAdmin' } - { label: 'Project Home', url: 'https://github.com/javiereguiluz/EasyAdminBundle', icon: 'home', target: '_blank' } @@ -23,4 +24,4 @@ easy_admin: - { label: 'Report Issues', url: 'https://github.com/javiereguiluz/EasyAdminBundle/issues', icon: 'github', target: 'arbitrary_value' } - { label: 'Misc.' } - { route: 'custom_route', label: 'Custom External Route', params: { custom_parameter: 'Lorem Ipsum' } } - - { route: 'easyadmin', label: 'Custom Internal Route' } + - { route: 'easyadmin', label: 'Custom Internal Route', css_class: 'route-custom-css-class' }