"MENU" Button Not Displaying on Mobile

Created on 27 March 2023, over 1 year ago
Updated 20 September 2023, 9 months ago

Problem/Motivation

The "MENU" button on mobile devices does not display the menu as expected. It would be beneficial for mobile device users to be able to use the graphical navigation menu .

Steps to reproduce

To replicate this issue, follow these steps:

1. Install a fresh Drupal 10 with DDEV (other fresh install methods may result in the same issue).
2. Install Base USWDS (uswds_base 3.4.x-dev or "drupal/uswds_base": "^3.3", among others).
3. Set [https://cdn.jsdelivr.net/npm/@uswds/uswds@3.3.0/dist/js/packages/usa-footer/src/index.js](https://cdn.jsdelivr.net/npm/@uswds/uswds@3.3.0/dist/js/packages/usa-footer/src/index.js) as the JS CDN using Base USWDS theme settings.
4. Configure the footer menu as a big footer (other footer configurations may also be affected).
5. Emulate a mobile device in the Chrome browser (Version 110.0.5481.177 (Official Build) (64-bit)), or use an actual mobile device (reproducible in Android/Chrome v 111.0.xxx, Apple Safari/Webkit also likely among others).
6. Open the test website in the mobile device/mobile emulated browser and attempt to use the MENU button for navigation. Observe that the menu button does not open.
7. Inspect the developer console.
8. Observe the browser console message:

index.js:66 Uncaught TypeError: Cannot read properties of null (reading 'setAttribute')
    at index.js:66:41
    at NodeList.forEach (<anonymous>)
    at c (index.js:42:16)
    at Object.init (index.js:91:7)
    at behavior.js:15:22
    at Array.forEach (<anonymous>)
    at Object.on (behavior.js:13:9)
    at start.js:20:14
    at Array.forEach (<anonymous>)
    at HTMLDocument.e (start.js:18:27)

Proposed resolution

I am uncertain about what the proposed resolution should be. If this is something that should be addressed within the theme, I am happy to help and take assignment of the bug report and fix. If it should be addressed by the USWDS JavaScript, I am also willing to try and get that done there. Additionally, I may just be missing something obvious here.

The primary point of failure appears to be line 62 of `index.js`

function toggleHtmlTag(isMobile) {
  const bigFooter = document.querySelector(SCOPE);

  if (!bigFooter) {
    return;
  }

  const primaryLinks = bigFooter.querySelectorAll(BUTTON);
  const newElementType = isMobile ? "button" : "h4";

  primaryLinks.forEach((currentElement) => {
    const currentElementClasses = currentElement.getAttribute("class");

    // Create the new element
    const newElement = document.createElement(newElementType);
    newElement.setAttribute("class", currentElementClasses);
    newElement.classList.toggle(
      `${PREFIX}-footer__primary-link--button`,
      isMobile
    );
    newElement.textContent = currentElement.textContent;

    if (isMobile) {
      const menuId = `${PREFIX}-footer-menu-list-${Math.floor(
        Math.random() * 100000
      )}`;

      newElement.setAttribute("aria-controls", menuId);
      newElement.setAttribute("aria-expanded", "false");
62>   currentElement.nextElementSibling.setAttribute("id", menuId);
      newElement.setAttribute("type", "button");
    }

    // Insert the new element and delete the old
    currentElement.after(newElement);
    currentElement.remove();
  });
}

`currentElement.nextElementSibling.setAttribute("id", menuId);` user wants to set attributes on siblings of the usa-footer__primary-linkโ€”button element. However, the Base USWDS template provides single elements in the template file, so no siblings are present. This results in a null value and an error.

Have not researched this on the USWDS side. It may be possible the Javascript could be modified to handle the null state of `Element.nextElementSibling` query. Maybe even a simple `if (Element.nextElementSibling) { // then try to set attributes}` would do it.

As an alternative, the Base USWDS theme twig file at this path could be modified:
`web/themes/contrib/uswds_base/templates/navigation/menu--footer_menu.html.twig`

Adding a phony sibling element along with the actual link item avoids the Javascript failure:

<div class="mobile-lg:grid-col-6 desktop:grid-col">
  <section class="usa-footer__primary-content usa-footer__primary-content--collapsible">
    <strong>
      {{ link(item.title, item.url, link_attributes.addClass('usa-footer__primary-link'))}}
      | <span>test sibling</span>
    </strong>
    <ul class="usa-list usa-list--unstyled">
      {% if item.below %}
        {{ menus.menu_links(item.below, 1, footer_style, link_attributes) }}
      {% endif %}
    </ul>
  </section>
</div>

Very possible I am missing the point altogether, and some setting or configuration is needed.

Remaining tasks

Unknownโ€ฆ

User interface changes

Unknownโ€ฆ

API changes

Unknownโ€ฆ

Data model changes

Unknownโ€ฆ

๐Ÿ› Bug report
Status

Fixed

Version

3.4

Component

Code

Created by

๐Ÿ‡บ๐Ÿ‡ธUnited States alexb7217

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @alexb7217
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States alexb7217
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States alexb7217
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States mferanda

    I didn't see anything specifically on this with USWDS issue queue. There's another ticket on here related to mobile review... perhaps we can get this all figured out for the 3.4.x release.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States alexb7217

    Looking at the example code for the Big Footer, as an example: https://designsystem.digital.gov/components/footer/

    The

    elements are in place alongside a
      which gives the markup a structure that works with the Javascript code and avoids the error state.

      It may be there are two actions to pursue:

      1. This theme could implement the footer code to provide markup compatible with the Javascript in USWDS
      2. The USWDS Javascript could provide better case handling to accomodate the failure mode without breaking the functionality

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States alexb7217

    If I removed the strong element from the code in `web/themes/contrib/uswds_base/templates/navigation/menu--footer_menu.html.twig` --

    Then it appears the Big Footer menu JS issue is resolved, and the footer collapses properly in mobile view. I think it may be just that simple.

    From this:

    <div class="mobile-lg:grid-col-6 desktop:grid-col">
      <section class="usa-footer__primary-content usa-footer__primary-content--collapsible">
        <strong>
          {{ link(item.title, item.url, link_attributes.addClass('usa-footer__primary-link'))}}
        </strong>
        <ul class="usa-list usa-list--unstyled">
          {% if item.below %}
            {{ menus.menu_links(item.below, 1, footer_style, link_attributes) }}
          {% endif %}
        </ul>
      </section>
    </div>
    

    To this ...:

    <div class="mobile-lg:grid-col-6 desktop:grid-col">
      <section class="usa-footer__primary-content usa-footer__primary-content--collapsible">
          {{ link(item.title, item.url, link_attributes.addClass('usa-footer__primary-link'))}}
        <ul class="usa-list usa-list--unstyled">
          {% if item.below %}
            {{ menus.menu_links(item.below, 1, footer_style, link_attributes) }}
          {% endif %}
        </ul>
      </section>
    </div>
    

    Is it possible the strong element is unnecessary?

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States alexb7217

    Not an exact match, this issue reports on a related problem: https://github.com/uswds/uswds/issues/4809

    The poster reports the console log error related to currentElement.nextElementSibling.setAttribute("id", menuId);

    The poster also describes the resulting lack of MENU button functionality and footer rendering problems that follow the error.

    The poster also suggests a simple condition check to resolve it: if (currentElement.nextElementSibling) { currentElement.nextElementSibling.setAttribute("id", menuId);} -- which was my naive proposed fix as well.

    The Javascript could be made more resilient on the USWDS side, for sure. We can also resolve the issue on the theme side if the twig template doesn't need the <strong> tag in web/themes/contrib/uswds_base/templates/navigation/menu--footer_menu.html.twig

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States mferanda

    If removing strong resolves an issue, then I say it's a good change. If someone wanted to keep the strong, they can do it through he sub theme.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States alexb7217

    Yes, we have already resolved the issue we are having by removing the <strong> tag from the footer menu template in the sub-theme. Curious still to know why the <strong> tag is there to begin with, since the USWDS source code does not prescribe it, and appears to have no visible or semantic benefit.

    The issue appeared to be intermittent at first. I was only able to really isolate it on an actual mobile device using Chrome to debug over USB. Now able to reproduce it consistently with a fresh install of everything, emulating a mobile device in Chrome dev tools.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Just experienced this too on a fresh install.

  • @smustgrave opened merge request.
  • Status changed to Needs review 10 months ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Removed the strong tag and added text-bold which should still make the links bold, to avoid any backwards breaking.

  • ๐Ÿ‡บ๐Ÿ‡ธUnited States mferanda

    Duplicated myself. Fix is good.

  • Status changed to Fixed 9 months ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States mferanda
  • Status changed to Fixed 9 months ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States mferanda
Production build 0.69.0 2024