Menu hamburger mobile : toggle sur toute la largeur de la ligne

Date : 8 juillet 2026 Fichier : les-baladins-mobile-menu-full-row-toggle.php Emplacement : wp-content/mu-plugins/ Site : les-baladins.ch

Demande initiale

Dans le menu hamburger mobile, les rubriques avec sous-menu (“Comment ça fonctionne ?”, “Activités 4-9 ans”) ne se dépliaient qu’en cliquant précisément sur la petite flèche à droite. Objectif : que le clic n’importe où sur la ligne (titre compris) ouvre/ferme le sous-menu.

Comment j’ai trouvé la cause

  1. Capture d’écran fournie du menu mobile déplié, montrant les rubriques avec chevron à droite.

  2. Récupération du HTML rendu de la page (curl sur les-baladins.ch) pour examiner la structure réelle du menu :

    <li class="menu-item menu-item-has-children ...">
      <a>Comment ça fonctionne?<span role="presentation" class="dropdown-menu-toggle">...</span></a>
      <ul class="sub-menu">...</ul>
    </li>

    Point clé : le <a> n’a aucun attribut href — ni href="#", ni href="", littéralement absent.

  3. Récupération des scripts JS du thème réellement chargés : generatepress/assets/js/menu.min.js. Lecture du code pour comprendre le mécanisme de toggle.

  4. Dans ce script, deux mécanismes coexistent :

    • Un listener attaché uniquement aux éléments .dropdown-menu-toggle (la flèche) → toggle du sous-menu (classes sfHover / toggled-on, aria-expanded).

    • Un second mécanisme, actif seulement si le body a la classe dropdown-hover (c’est le cas ici), qui permettrait de cliquer sur le lien entier — mais seulement si href vaut exactement "#" ou "" :

      ("#" === href || "" === href) && (e.preventDefault(), ...toggle...)
  5. Conclusion : ce second mécanisme existe bel et bien dans GeneratePress, mais ne s’applique pas ici parce que le thème retire complètement l’attribut href des liens parents sans URL définie (comportement volontaire de GeneratePress pour l’accessibilité — un lien sans destination ne devrait pas être un <a href> cliquable). getAttribute('href') renvoie alors null, qui ne correspond ni à "#" ni à "". C’est un fait vérifié dans le HTML et le JS réellement servis par le site, pas une supposition.

Pourquoi ce n’est pas réparable en CSS seul

L’ouverture/fermeture du sous-menu sur mobile est un comportement de clic (pas un simple :hover comme sur desktop), géré entièrement en JavaScript par le thème. Étendre la zone cliquable à toute la ligne implique donc d’intervenir en JS, pas seulement en CSS.

Solution retenue

Plutôt que de réécrire la logique de toggle (classes, aria-expanded, gestion des sous-menus déjà ouverts, etc. — tout ça déjà fait correctement par le thème), le script ajouté se contente de relayer le clic vers la flèche existante :

document.addEventListener('click', function (e) {
    var link = e.target.closest('.main-navigation .menu-item-has-children > a');
    if (!link) return;

    // Clic direct sur la flèche : le script du thème s'en charge déjà.
    if (e.target.closest('.dropdown-menu-toggle')) return;

    var nav = link.closest('nav');
    if (!nav || !nav.classList.contains('toggled')) return; // menu hamburger fermé -> ne rien faire

    var href = link.getAttribute('href');
    if (href && href !== '#') return; // vrai lien vers une page -> laisser naviguer

    var toggle = link.parentElement.querySelector('.dropdown-menu-toggle');
    if (toggle) {
        e.preventDefault();
        toggle.click(); // déclenche exactement la même logique que le clic sur la flèche
    }
}, false);

Détail des garde-fous, et pourquoi chacun est nécessaire :

  • e.target.closest('.dropdown-menu-toggle') → return : évite un double-déclenchement si l’utilisateur clique précisément sur la flèche (le script du thème gère déjà ce cas). Le clic synthétique généré plus bas (toggle.click()) remonte lui aussi jusqu’à document ; comme sa cible est la flèche elle-même, cette même ligne l’exclut aussi — pas de boucle, pas de double toggle.
  • nav.classList.contains('toggled') : cette classe n’est posée par le thème que quand le menu hamburger est effectivement ouvert (état mobile). Sur desktop/tablette, elle est absente, donc le script ne fait rien et ne modifie aucun comportement existant (survol, etc.).
  • href && href !== '#' → return : si un jour une rubrique parente pointe vraiment vers une page (contrairement aux deux rubriques actuelles, qui sont des liens vides), le script n’interceptera pas le clic — la navigation normale reste prioritaire.

Le script réutilise donc entièrement la logique existante du thème (classes sfHover/toggled-on, aria-expanded, fermeture des autres sous-menus ouverts) au lieu de la dupliquer : moins de code, aucun risque de désynchronisation avec une future mise à jour de GeneratePress.

Où et comment le script est chargé

Le fichier est un mu-plugin (comme celui de l’API CSS additionnel) : il s’auto-charge depuis wp-content/mu-plugins/, sans activation. Il utilise le hook wp_footer pour injecter le script juste avant </body>, uniquement sur le front-end (is_admin() exclu), avec une priorité de 100 pour s’exécuter après les scripts du thème.

Statut

Fichier livré le 8 juillet 2026, en attente de dépôt sur le serveur par Andrea. Vérification du rendu à faire une fois le fichier en place.