Aug 27, 2020 in Drupal 8, Snippets

For a use case with a lot of custom menu items I had to add arrows or buttons inside a menu. I prefer to just make them all regular menu items and tweak them with twig. Below is my menu--main.html.twig file. You can see a lot of levels and custom classes or html. You'll find a lot of what you might need in here.

{#
/**
 * @file
 * Default theme implementation to display a menu.
 *
 * Available variables:
 * - menu_name: The machine name of the menu.
 * - items: A nested list of menu items. Each menu item contains:
 *   - attributes: HTML attributes for the menu item.
 *   - below: The menu item child items.
 *   - title: The menu link title.
 *   - url: The menu link url, instance of \Drupal\Core\Url
 *   - localized_options: Menu link localized options.
 *   - is_expanded: TRUE if the link has visible children within the current
 *     menu tree.
 *   - is_collapsed: TRUE if the link has children within the current menu tree
 *     that are not currently visible.
 *   - in_active_trail: TRUE if the link is in the active trail.
 *
 * @ingroup themeable
 */
#}
{% import _self as menus %}

{#
  We call a macro which calls itself to render the full tree.
  @see https://twig.symfony.com/doc/1.x/tags/macro.html
#}
{{ menus.menu_links(items, attributes, 0) }}

{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {% if items %}
    {% if menu_level == 0 %}
      <ul class="list-reset flex-1 lg:flex items-center relative lg:justify-between lg:ml-5 lg:mr-5">
        {% for item in items %}
            {% if item.below %}
              <li{{ item.attributes.addClass('menu-level-1','block', 'no-underline', 'py-6', 'border-b-1', 'border-0', 'leading-7', 'border-white') }} aria-haspopup="true" aria-expanded="false" aria-controls="{{ item.url }}" aria-label="Navigation">
              {{ link(item.title, item.url, { 'class': ['block', 'text-white', 'lg:text-blue700',  'text-3xl', 'lg:text-lg', 'cursor-pointer'] }) }}
              {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
            {% else %}
              <li{{ item.attributes.addClass('block', 'no-underline', 'py-6', 'border-b-1', 'leading-7', 'border-white') }}>
              {{ link(item.title, item.url, { 'class': ['block', 'text-white', 'lg:text-blue700',  'text-3xl'] }) }}
            {% endif %}
           </li>
          {% set parentLevel = item.title %}
        {% endfor %}
    {% elseif menu_level == 1 %}
      <ul class="hidden list-reset flex-1 items-center lg:absolute lg:bg-white lg:p-12 lg:py-10  lg:z-10">
        {% for item in items %}
          {% if item.below %}
          <li{{ item.attributes.addClass('my-4', 'block', 'no-underline', 'py-2', 'menu-level-2') }} >
            {{ link(item.title, item.url, { 'class': ['pb-1', 'block', 'text-white', 'lg:text-blue700', 'text-normal', 'lg:text-lg', 'lg:font-bold', 'border-b-1', 'border-white', 'lg:border-b-1', 'lg:border-blue700', 'lg:pb-2', 'lg:mb-3'] }) }}
            {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
          {% else %}
            <li{{ item.attributes.addClass('block', 'mt-4', 'w-full') }}>
            {{ link(item.title, item.url, { 'class': ['pb-1', 'border-0', 'block', 'text-white', 'lg:text-blue700',  'text-normal', 'font-bold'] }) }}
          {% endif %}
          </li>
        {% endfor %}
    {% else %}
      <ul class="list-reset flex-1 items-center">
        {% for item in items %}
          {% if item.below %}
          <li{{ item.attributes.addClass('my-4', 'block', 'no-underline', 'py-2') }} aria-haspopup="true" aria-expanded="false" aria-controls="menu-{{ menu_level + 1 }}" aria-label="Navigation">
            {{ link(item.title, item.url, { 'class': ['pb-1', 'block', 'text-white', 'lg:text-blue700',  'text-normal', 'font-bold'] }) }}
            {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
          {% else %}
            <li{{ item.attributes.addClass('block', 'mt-4', 'w-full') }}>
            {% if item.url.getOption('attributes').class == 'entrepreneurs' %}
              {% set title %}
                <img src="/themes/custom/mytheme/img/icon/building_white.svg" class="inline float-left w-2/12 w-auto mr-3"> {{ item.title }}
              {% endset %}
              {{ link(title, item.url, { 'class': ['btn bg-white lg:bg-blue500 text-blue700 lg:text-white text-2xl py-4 px-4 block border-0'] }) }}
            {% elseif item.url.getOption('attributes').class == 'researchers' %}
              {% set title %}
                <img src="/themes/custom/mytheme/img/icon/magnifier_white.svg" class="inline float-left w-2/12 w-auto mr-3"> {{ item.title }}
              {% endset %}
              {{ link(title, item.url, { 'class': ['btn bg-green500 text-blue700 text-2xl py-4 px-4 block border-0'] }) }}
            {% elseif item.url.getOption('attributes').class == 'governments' %}
              {% set title %}
                <img src="/themes/custom/mytheme/img/icon/office_white.svg" class="inline float-left w-2/12 w-auto mr-3"> {{ item.title }}
              {% endset %}
              {{ link(title, item.url, { 'class': ['btn bg-blue700 text-white text-2xl py-4 px-4 block border-0'] }) }}
            {% else %}
            {{ link(item.title, item.url, { 'class': ['pb-1', 'border-0', 'block', 'text-white', 'lg:text-blue700',  'text-normal', 'font-bold', 'no-underline'] }) }}

            {% endif %}
          </li>
          {% endif %}
        {% endfor %}
    {% endif %}
        
    </ul>
  {% endif %}
{% endmacro %}