navigation-menu.html.twig

{% import _self as menus %}
<ul class="toolbar-block__list">
  {{ menus.menu_items(items, attributes, 0) }}
</ul>

{% macro menu_items(items, attributes, menu_level) %}
  {% for item in items %}

    {% set item_link_tag = 'a' %}

    {% if item.url.isRouted %}
      {% if item.url.routeName == '<nolink>' %}
        {% set item_link_tag = constant('\\Drupal\\Core\\GeneratedNoLink::TAG') %}
      {% elseif item.url.routeName == '<button>' %}
        {% set item_link_tag = constant('\\Drupal\\Core\\GeneratedButton::TAG') %}
      {% endif %}
    {% endif %}

    {% if item.url.options.attributes is empty %}
      {% set item_link_attributes = create_attribute() %}
    {% else %}
      {% set item_link_attributes = create_attribute(item.url.options.attributes) %}
    {% endif %}

    {% set item_id = ('navigation-link--' ~ item.original_link.pluginId)|clean_unique_id %}
    {% if menu_level == 0 %}
      {% if item.below is empty %}
        <li id="{{ item_id }}" class="toolbar-block__list-item">
          {% include 'navigation:toolbar-button' with {
            attributes: item_link_attributes.setAttribute('href', item.url|render|default(null)).setAttribute('data-drupal-tooltip', item.title).setAttribute('data-drupal-tooltip-class', 'admin-toolbar__tooltip'),
            icon: item.icon,
            html_tag: item_link_tag,
            text: item.title,
            modifiers: [
              'collapsible',
              item_link_tag == 'span' ? 'non-interactive' : null
            ]|filter(v => v is not null),
          } only %}
        </li>
      {% else %}
        <li id="{{ item_id }}" class="toolbar-block__list-item toolbar-popover" data-toolbar-popover>
          {% include 'navigation:toolbar-button' with {
            action: 'Extend'|t,
            attributes: create_attribute({
              'aria-expanded': 'false',
              'aria-controls': item_id,
              'data-toolbar-popover-control': true,
              'data-has-safe-triangle': true,
            }),
            icon: item.icon,
            text: item.title,
            modifiers: [
              'expand--side',
              'collapsible',
            ],
            extra_classes: [
              'toolbar-popover__control',
            ],
          } only %}
          <div class="toolbar-popover__wrapper" data-toolbar-popover-wrapper inert>
            {% if item.url %}
              {% include 'navigation:toolbar-button' with {
                attributes: item_link_attributes.setAttribute('href', item.url|render),
                html_tag: item_link_tag,
                text: item.title,
                modifiers: [
                  'large',
                  'dark',
                ],
                extra_classes: [
                  'toolbar-popover__header',
                ],
              } only %}
            {% else %}
              {% include 'navigation:toolbar-button' with {
                attributes: create_attribute(),
                modifiers: [
                  'large',
                  'dark',
                  'non-interactive',
                ],
                extra_classes: [
                  'toolbar-popover__header',
                ],
                html_tag: 'span',
                text: item.title,
              } only %}
            {% endif %}
            <ul class="toolbar-menu toolbar-popover__menu">
              {{ menus.menu_items(item.below, attributes, 1) }}
            </ul>
          </div>
        </li>
      {% endif %}

    {% elseif menu_level == 1 %}
      <li class="toolbar-menu__item toolbar-menu__item--level-{{ menu_level }}">
        {% if item.below is empty  %}
          {% include 'navigation:toolbar-button' with {
            attributes: item_link_attributes.setAttribute('href', item.url|render|default(null)),
            text: item.title,
            html_tag: item_link_tag,
            extra_classes: [
              item_link_tag == 'span' ? 'toolbar-button--non-interactive'
            ],
          } only %}
        {% else %}
          {% include 'navigation:toolbar-button' with {
            attributes: create_attribute({
              'aria-expanded': 'false',
              'data-toolbar-menu-trigger': menu_level,
            }),
            text: item.title,
            modifiers: ['expand--down'],
          } only %}
          <ul class="toolbar-menu toolbar-menu--level-{{ menu_level + 1 }}" inert>
            {{ menus.menu_items(item.below, attributes, menu_level + 1) }}
          </ul>
        {% endif %}
      </li>
    {% else %}
      <li class="toolbar-menu__item toolbar-menu__item--level-{{ menu_level }}">
        {% if item.below is empty  %}
          {{ link(item.title, item.url, {
            'class': [
              'toolbar-menu__link',
              'toolbar-menu__link--' ~ menu_level,
            ],
            'data-index-text': item.title|first|lower
          }) }}
        {% else %}
          <button
            class="toolbar-menu__link toolbar-menu__link--{{ menu_level }}"
            data-toolbar-menu-trigger="{{ menu_level }}"
            aria-expanded="false"
            data-index-text="{{ item.title|first|lower }}"
          >
            <span data-toolbar-action class="toolbar-menu__link-action visually-hidden">{{ 'Extend'|t }}</span>
            <span class="toolbar-menu__link-title">{{ item.title }}</span>
            {{ icon('navigation', 'chevron', { class: 'toolbar-menu__chevron', size: 16 }) }}
          </button>
          <ul class="toolbar-menu toolbar-menu--level-{{ menu_level + 1 }}" inert>
            {{ menus.menu_items(item.below, attributes, menu_level + 1) }}
          </ul>
        {% endif %}
      </li>
    {% endif %}
  {% endfor %}
{% endmacro %}
5 theme calls to navigation-menu.html.twig
NavigationLinkBlock::build in core/modules/navigation/src/Plugin/Block/NavigationLinkBlock.php
Builds and returns the renderable array for this block plugin.
NavigationShortcutsBlock::build in core/modules/navigation/src/Plugin/Block/NavigationShortcutsBlock.php
Builds and returns the renderable array for this block plugin.
NavigationTestBlock::build in core/modules/navigation/tests/navigation_test_block/src/Plugin/Block/NavigationTestBlock.php
Builds and returns the renderable array for this block plugin.
ShortcutLazyBuilder::lazyLinks in core/modules/navigation/src/ShortcutLazyBuilder.php
The #lazy_builder callback; builds shortcut navigation links.
WorkspacesLazyBuilder::renderNavigationLinks in core/modules/navigation/src/WorkspacesLazyBuilder.php
Lazy builder callback for rendering navigation links.

File

core/themes/stable9/templates/navigation/navigation-menu.html.twig

View source
  1. {% import _self as menus %}
  2. <ul class="toolbar-block__list">
  3. {{ menus.menu_items(items, attributes, 0) }}
  4. </ul>
  5. {% macro menu_items(items, attributes, menu_level) %}
  6. {% for item in items %}
  7. {% set item_link_tag = 'a' %}
  8. {% if item.url.isRouted %}
  9. {% if item.url.routeName == '<nolink>' %}
  10. {% set item_link_tag = constant('\\Drupal\\Core\\GeneratedNoLink::TAG') %}
  11. {% elseif item.url.routeName == '<button>' %}
  12. {% set item_link_tag = constant('\\Drupal\\Core\\GeneratedButton::TAG') %}
  13. {% endif %}
  14. {% endif %}
  15. {% if item.url.options.attributes is empty %}
  16. {% set item_link_attributes = create_attribute() %}
  17. {% else %}
  18. {% set item_link_attributes = create_attribute(item.url.options.attributes) %}
  19. {% endif %}
  20. {% set item_id = ('navigation-link--' ~ item.original_link.pluginId)|clean_unique_id %}
  21. {% if menu_level == 0 %}
  22. {% if item.below is empty %}
  23. <li id="{{ item_id }}" class="toolbar-block__list-item">
  24. {% include 'navigation:toolbar-button' with {
  25. attributes: item_link_attributes.setAttribute('href', item.url|render|default(null)).setAttribute('data-drupal-tooltip', item.title).setAttribute('data-drupal-tooltip-class', 'admin-toolbar__tooltip'),
  26. icon: item.icon,
  27. html_tag: item_link_tag,
  28. text: item.title,
  29. modifiers: [
  30. 'collapsible',
  31. item_link_tag == 'span' ? 'non-interactive' : null
  32. ]|filter(v => v is not null),
  33. } only %}
  34. </li>
  35. {% else %}
  36. <li id="{{ item_id }}" class="toolbar-block__list-item toolbar-popover" data-toolbar-popover>
  37. {% include 'navigation:toolbar-button' with {
  38. action: 'Extend'|t,
  39. attributes: create_attribute({
  40. 'aria-expanded': 'false',
  41. 'aria-controls': item_id,
  42. 'data-toolbar-popover-control': true,
  43. 'data-has-safe-triangle': true,
  44. }),
  45. icon: item.icon,
  46. text: item.title,
  47. modifiers: [
  48. 'expand--side',
  49. 'collapsible',
  50. ],
  51. extra_classes: [
  52. 'toolbar-popover__control',
  53. ],
  54. } only %}
  55. <div class="toolbar-popover__wrapper" data-toolbar-popover-wrapper inert>
  56. {% if item.url %}
  57. {% include 'navigation:toolbar-button' with {
  58. attributes: item_link_attributes.setAttribute('href', item.url|render),
  59. html_tag: item_link_tag,
  60. text: item.title,
  61. modifiers: [
  62. 'large',
  63. 'dark',
  64. ],
  65. extra_classes: [
  66. 'toolbar-popover__header',
  67. ],
  68. } only %}
  69. {% else %}
  70. {% include 'navigation:toolbar-button' with {
  71. attributes: create_attribute(),
  72. modifiers: [
  73. 'large',
  74. 'dark',
  75. 'non-interactive',
  76. ],
  77. extra_classes: [
  78. 'toolbar-popover__header',
  79. ],
  80. html_tag: 'span',
  81. text: item.title,
  82. } only %}
  83. {% endif %}
  84. <ul class="toolbar-menu toolbar-popover__menu">
  85. {{ menus.menu_items(item.below, attributes, 1) }}
  86. </ul>
  87. </div>
  88. </li>
  89. {% endif %}
  90. {% elseif menu_level == 1 %}
  91. <li class="toolbar-menu__item toolbar-menu__item--level-{{ menu_level }}">
  92. {% if item.below is empty %}
  93. {% include 'navigation:toolbar-button' with {
  94. attributes: item_link_attributes.setAttribute('href', item.url|render|default(null)),
  95. text: item.title,
  96. html_tag: item_link_tag,
  97. extra_classes: [
  98. item_link_tag == 'span' ? 'toolbar-button--non-interactive'
  99. ],
  100. } only %}
  101. {% else %}
  102. {% include 'navigation:toolbar-button' with {
  103. attributes: create_attribute({
  104. 'aria-expanded': 'false',
  105. 'data-toolbar-menu-trigger': menu_level,
  106. }),
  107. text: item.title,
  108. modifiers: ['expand--down'],
  109. } only %}
  110. <ul class="toolbar-menu toolbar-menu--level-{{ menu_level + 1 }}" inert>
  111. {{ menus.menu_items(item.below, attributes, menu_level + 1) }}
  112. </ul>
  113. {% endif %}
  114. </li>
  115. {% else %}
  116. <li class="toolbar-menu__item toolbar-menu__item--level-{{ menu_level }}">
  117. {% if item.below is empty %}
  118. {{ link(item.title, item.url, {
  119. 'class': [
  120. 'toolbar-menu__link',
  121. 'toolbar-menu__link--' ~ menu_level,
  122. ],
  123. 'data-index-text': item.title|first|lower
  124. }) }}
  125. {% else %}
  126. <button
  127. class="toolbar-menu__link toolbar-menu__link--{{ menu_level }}"
  128. data-toolbar-menu-trigger="{{ menu_level }}"
  129. aria-expanded="false"
  130. data-index-text="{{ item.title|first|lower }}"
  131. >
  132. <span data-toolbar-action class="toolbar-menu__link-action visually-hidden">{{ 'Extend'|t }}</span>
  133. <span class="toolbar-menu__link-title">{{ item.title }}</span>
  134. {{ icon('navigation', 'chevron', { class: 'toolbar-menu__chevron', size: 16 }) }}
  135. </button>
  136. <ul class="toolbar-menu toolbar-menu--level-{{ menu_level + 1 }}" inert>
  137. {{ menus.menu_items(item.below, attributes, menu_level + 1) }}
  138. </ul>
  139. {% endif %}
  140. </li>
  141. {% endif %}
  142. {% endfor %}
  143. {% endmacro %}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.