RGAA patches - Main menu


This page should only be applied if the script assisted migration asks you to skip manual migration skin.20240717.INTRANETSEARCH.rgaa.mainmenu

The main navigation has been redesigned for better keyboard navigation in mobile mode, and for better understanding of navigation menus by assistive technologies.

Here are the changes made and to be reported if the XSL templates concerned have been overloaded.

  1. header-left" template
  2. header-icons" template
  3. Template "user-menu
  4. Back" button management in the main menu in mobile mode

header-left" template

The <nav class="left" role="navigation" aria-label="Navigation principale"> contenant le logo et le menu principal en mode desktop est maintenant caché en mobile (< 1400px)
One element <div class="left mobile"> containing only the logo has been added and is only visible in mobile mode.

<xsl:template name="header-left">
        <nav class="left" role="navigation" aria-label="skin.{$skin}:SKIN_NAV_MAIN_NAVIGATION" i18n:attr="aria-label">
            <!-- Logo -->
            <xsl:call-template name="header-main-logo"/>
            
            <xsl:call-template name="main-menu">
                <xsl:with-param name="device">desktop</xsl:with-param>
            </xsl:call-template>
        </nav>
            
        <!-- For mobile -->
        <div class="left mobile">
            <xsl:call-template name="header-main-logo"/>    
        </div>
    </xsl:template>

header-icons" template

The <nav role="navigation" aria-label="Menu secondaire" class="icons"> a été remplacé par un <div class="icons">.
Notification icons are not navigation elements within the site, but generally external links.

The "burger" button, which opens the main menu in mobile mode, is now surrounded by a <nav role="navigation" aria-label="Menu utilisateur">

<xsl:template name="header-icons">
        <div class="icons">
            <ul>
                <xsl:call-template name="search-button"/>
                
                <xsl:call-template name="top-links"/>
                <xsl:call-template name="alerts"/>
                
                <!-- User menu -->
                <xsl:call-template name="user-menu"/>
                
                <li class="burger">
                    <nav role="navigation" aria-label="skin.{$skin}:SKIN_NAV_MAIN_NAVIGATION" i18n:attr="aria-label">
                        <button aria-haspopup="dialog" aria-label="skin.{$skin}:SKIN_NAV_MAIN_NAVIGATION_MENU" i18n:attr="aria-label" onclick="openMenuMobile(this)"><i aria-hidden="true" class="fas fa-bars"></i></button>
                    </nav>
                </li>
            </ul>
        </div>
  </xsl:template>

Template "user-menu

The user menu is now surrounded by a <nav role="navigation" aria-label="Menu utilisateur">.
In addition, the scripts for opening/closing the user menu have been reworked for better keyboard navigation and to support menu closure via the ESC key.

<xsl:template name="user-menu">
        <xsl:if test="$currentUser/user/login">
            <li class="profil" style="display: none">
                <nav role="navigation" aria-label="skin.{$skin}:SKIN_NAV_USER_MENU" i18n:attr="aria-label">
                   [...]   
                   <xsl:call-template name="profil-img"/> 
                </nav>
            </li>
      </xsl:if>
      <script type="text/javascript">
            const closeUserMenuOnEscape = (event) => {
                if (event.key === "Escape") {
                    var $openUserMenu = $j("header .icons .profil .dropdown.openAccessibility");
                    $openUserMenu.removeClass('openAccessibility');
                    $openUserMenu.prev().attr("aria-expanded", "false");
                    $openUserMenu.prev().focus();
                }
            }
    
            function openUserMenuOnClick(el)
            {
                var isOpen = $j(el).next(".dropdown").is(':visible');
                if(!isOpen) {
                    // Open menu
                    $j(el).next(".dropdown").addClass('openAccessibility');
                    $j(el).attr("aria-expanded", "true");
                    $j(el).next(".dropdown").find('ul > li a').first().focus();
                    $j(el).closest('li').get(0).addEventListener('keydown', closeUserMenuOnEscape);
                }  else {
                    // Close menu
                    $j(el).next(".dropdown").removeClass('openAccessibility');
                    $j(el).attr("aria-expanded", "false");
                    $j(el).closest('li').get(0).removeEventListener('keydown', closeUserMenuOnEscape);
                }
            }
            
            $j(".icons ul li.profil").mouseenter(function (el) {
                // Show user menu
                var $dropdown = $j(this).find(".dropdown");
                if (!$dropdown.is(':visible'))
                {
                    $dropdown.addClass("openAccessibility");
                    $j(this).find('> button').attr("aria-expanded", true);
                }
            });
            
            $j(".icons ul li.profil").mouseleave(function (el) {
                // Hide user menu 
                var $dropdown = $j(this).find(".dropdown");
                if ($dropdown.is(':visible'))
                {
                    $dropdown.removeClass("openAccessibility");
                    $j(this).find('> button').attr("aria-expanded", false);
                }
            });
            
            $j(document).ready(function() {
                var _getAmetysUserCb = function(user)
                {
                    if (user)
                    {
                        $j('.profil').show();
                    }
                    else
                    {
                        $j('.profil').hide();
                    }
                }
                
                getAmetysUser(_getAmetysUserCb);
            });
        </script>
</xsl:template>

Back" button management in the main menu in mobile mode

The positioning of the "Back" button has been revised to make it easier to navigate the main menu in mobile mode.

This change affects several XSL templates.

In the "menu-mobile" template, the call to the "menu-mobile-back" template has been removed.
In addition, the role and aria-label attributes have been added.

<xsl:template name="menu-mobile">
        <div class="menu-mobile" role="dialog" aria-label="skin.{$skin}:SKIN_NAV_MAIN_MENU" i18n:attr="aria-label">
            <xsl:call-template name="menu-mobile-close"/>
            <xsl:call-template name="menu-mobile-logo"/>
            <xsl:call-template name="main-menu-mobile"/>
            <div class="access-mobile"></div>
        </div>
    </xsl:template>

Dans le template "submenu-mobile-levels",  les éléments <ul class="submenu"> deviennent des <div class="submenu"> contenant le <ul><li> de la liste des pages et un bouton "Retour"

<xsl:template name="submenu-mobile-levels">
        <xsl:if test="page[(not(@sitemap:invisible) or @sitemap:invisible = 'false')]">
            
            <div class="submenu">
                 <xsl:call-template name="menu-mobile-back"/>
                 
                 <ul>
                    <li class="title">
                        <a href="{resolver:resolve('page', @sitemap:id)}">
                            <xsl:value-of select="@sitemap:title" />
                        </a>
                    </li>
                    
                    <xsl:apply-templates select="page[not(@sitemap:invisible) or @sitemap:invisible = 'false']" mode="level-mobile"/>
                </ul>
            </div>
        </xsl:if>
    </xsl:template>

Modification similaire pour le template <xsl:template match="page" mode="level-mobile">

<xsl:template match="page" mode="level-mobile">
        <li>
            <xsl:attribute name="class"><xsl:if test="page[not(@sitemap:invisible) or @sitemap:invisible = 'false']">has-submenu</xsl:if></xsl:attribute>
            
            <a href="{resolver:resolve('page', @sitemap:id)}">
                <xsl:if test="@sitemap:type = 'LINK' and @sitemap:link-type = 'WEB'">
                    <xsl:call-template name="external-link-attributes"/>
                </xsl:if>
                <span><xsl:value-of select="@sitemap:title" /></span>
            </a>
            <xsl:if test="page[not(@sitemap:invisible) or @sitemap:invisible = 'false']">
                <button aria-label="{@sitemap:title}" aria-expanded="false" class="open-submenu-sr">
                    <i class="fas fa-angle-right" aria-hidden="true"></i>
                </button>
            </xsl:if>
            
            <xsl:if test="page[not(@sitemap:invisible) or @sitemap:invisible = 'false']">
                <div class="submenu">
                    <xsl:call-template name="menu-mobile-back"/>
                 
                    <ul>
                        <xsl:apply-templates select="page[not(@sitemap:invisible) or @sitemap:invisible = 'false']" mode="level-mobile"/>
                    </ul>
                </div>
            </xsl:if>
        </li>
    </xsl:template>

In the "menu-mobile-back" template, the JS action when the "Back" button is clicked expects the button to be the 1st argument.

<xsl:template name="menu-mobile-back">
        <button 
            aria-label="skin.{$skin}:SKIN_NAV_MENU_MOBILE_BACK"
            i18n:attr="aria-label"
            class="return" 
            onclick="closeLevel(this)">
            <i class="fas fa-arrow-left" aria-hidden="true"></i>
        </button>
</xsl:template>
Back to top