variable-titles on active link on buerger menu

This commit is contained in:
2026-10-20 20:04:23 +02:00
parent e15236c6eb
commit 0e3b1c9c2d
+68
View File
@@ -147,6 +147,74 @@ function parse_menu_item(&$items, $key){
} }
} }
/**
* Implements hook_preprocess_HOOK() for menu.html.twig.
*
* Burger (block leshed_navigationprincipale, menu 'main') : le lien actif
* passe en typo « variable title ». La classe est posée côté serveur pour
* être présente au premier rendu — titles.js la cherche à ce moment-là, et
* le CSS masque .variable-title jusqu'au split (pas de flash de typo brute).
*
* Détection du lien actif : on compare le chemin système courant au chemin
* interne de chaque lien (même logique que active-link.js / ActiveLinkResponse
* Filter, dont la classe `is-active` n'est dans le HTML que pour les réponses
* anonymes en cache). On ne peut PAS utiliser `in_active_trail` : les liens
* de menu vers des pages de vues ne matchent jamais — la route courante
* expose des paramètres (view_id, display_id, arg_0) absents du lien, donc
* loadLinksByRoute() ne le retrouve pas et le trail reste vide (mesuré).
*/
function leshed_preprocess_menu(&$variables) {
if (($variables['menu_name'] ?? '') !== 'main') {
return;
}
// La détection dépend du chemin courant, mais le bloc ne varie par défaut
// que par route.menu_active_trails:main — vide sur ce site à cause des
// liens views (cf. ci-dessous). Sans ce contexte, le bloc mis en cache sur
// une page resservirait sur une autre avec le mauvais lien marqué.
$variables['#cache']['contexts'][] = 'url.path';
// isFrontPage() lit la config page.front : invalider si elle change.
$variables['#cache']['tags'][] = 'config:system.site';
$current = \Drupal::service('path.current')->getPath();
$is_front = \Drupal::service('path.matcher')->isFrontPage();
leshed_menu_variable_title($variables['items'], $current, $is_front);
}
/**
* Pose la classe .variable-title sur l'item actif (chemin système courant).
*
* Chemin interne normalisé avec un « / » initial : la route <front> a un
* chemin interne vide. La page d'accueil est configurée sur un chemin
* système (page.front), donc sur la page d'accueil on marque l'item
* <front> via isFrontPage() plutôt que par le chemin.
*
* Marque au plus UN item (le premier trouvé) : un lien <front> et un lien
* pointant la page d'accueil configurée ne doivent pas être marqués ensemble.
*
* NB : $item est une copie du tableau, mais $item['url'] est un objet Url
* partagé — le setOptions() mute bien celui que rendra le template.
*
* @param string $current
* Chemin système courant (ex. « /projets », « / »).
* @param bool $is_front
* La page courante est la page d'accueil.
*/
function leshed_menu_variable_title(array $items, $current, $is_front) {
foreach ($items as $item) {
if (!empty($item['below']) && leshed_menu_variable_title($item['below'], $current, $is_front)) {
return TRUE;
}
$url = $item['url'];
if ($url->isRouted()
&& (($is_front && $url->getRouteName() === '<front>') || '/' . $url->getInternalPath() === $current)) {
$options = $url->getOptions();
$options['attributes']['class'][] = 'variable-title';
$url->setOptions($options);
return TRUE;
}
}
return FALSE;
}
/** /**
* Implements hook_preprocess_HOOK() for node.html.twig. * Implements hook_preprocess_HOOK() for node.html.twig.
*/ */