# Créer un lecteur de programme d’événementiel navigable au clavier

> Un planning de festival réparti sur plusieurs jours, avec des onglets par journée et une annonce claire du jour actif : voici le code, commenté pas à pas.

- Auteur : WordPress Développement
- Publié le : 2022-08-17
- Mis à jour le : 2022-08-17
- Catégorie : Accessibilité
- URL : https://www.wpmoderne.fr/accessibilite/lecteur-programme-evenementiel-clavier/

## L’essentiel

- Onglets ARIA conformes au motif tablist
- Annonce du jour actif sans perte de focus
- Rendu généré depuis un type de contenu personnalisé

`role="tablist"`, `role="tab"`, `role="tabpanel"` : trois rôles ARIA suffisent à transformer un simple jeu d'onglets en composant réellement navigable au clavier, à condition de respecter précisément le motif de conception attendu par les lecteurs d'écran. C'est la recette utilisée pour construire le planning d'un festival de musique répartis sur quatre jours, où chaque journée devait s'afficher sans rechargement de page tout en restant annoncée clairement.

Le programme est enregistré comme type de contenu personnalisé `evenement`, avec un champ de taxonomie `jour_festival` pour classer chaque concert. Le rendu HTML est généré en PHP côté serveur, puis le changement d'onglet est géré en JavaScript côté client, sans dépendance à une bibliothèque tierce.

## Générer la structure PHP

La fonction suivante construit la liste des onglets et les panneaux correspondants à partir des termes de taxonomie enregistrés :

```
function wpm_programme_festival() {
    $jours = get_terms([
        'taxonomy'   => 'jour_festival',
        'hide_empty' => true,
    ]);

    if (empty($jours) || is_wp_error($jours)) {
        return;
    }

    echo '<div class="programme-festival">';
    echo '<div role="tablist" aria-label="Jours du festival">';
    foreach ($jours as $index => $jour) {
        $actif = $index === 0 ? 'true' : 'false';
        $tabindex = $index === 0 ? '0' : '-1';
        printf(
            '<button role="tab" id="tab-%1$s" aria-controls="panel-%1$s" aria-selected="%2$s" tabindex="%3$s">%4$s</button>',
            esc_attr($jour->slug),
            esc_attr($actif),
            esc_attr($tabindex),
            esc_html($jour->name)
        );
    }
    echo '</div>';

    foreach ($jours as $index => $jour) {
        $cache = $index === 0 ? '' : 'hidden';
        printf(
            '<div role="tabpanel" id="panel-%1$s" aria-labelledby="tab-%1$s" %2$s>',
            esc_attr($jour->slug),
            esc_attr($cache)
        );
        wpm_liste_concerts_du_jour($jour->term_id);
        echo '</div>';
    }
    echo '</div>';
}
```

Chaque bouton reçoit un `aria-controls` qui pointe vers le panneau correspondant, et un seul onglet fait partie de l'ordre de tabulation par défaut (`tabindex="0"`), les autres étant accessibles ensuite par les flèches directionnelles.

## Gérer le changement de jour en JavaScript

> L'essentiel à retenir : Onglets ARIA conformes au motif tablist ; Annonce du jour actif sans perte de focus ; Rendu généré depuis un type de contenu personnalisé

Le script ci-dessous applique le motif de conception « tablist » recommandé : les flèches gauche et droite déplacent le focus entre les onglets, la touche `Entrée` ou `Espace` active le panneau correspondant.

```
const onglets = Array.from(document.querySelectorAll('[role="tab"]'));

function activerOnglet(cible) {
  onglets.forEach((onglet) => {
    const estCible = onglet === cible;
    onglet.setAttribute('aria-selected', estCible);
    onglet.setAttribute('tabindex', estCible ? '0' : '-1');
    const panneau = document.getElementById(onglet.getAttribute('aria-controls'));
    panneau.hidden = !estCible;
  });
  cible.focus();
}

onglets.forEach((onglet, index) => {
  onglet.addEventListener('click', () => activerOnglet(onglet));
  onglet.addEventListener('keydown', (evenement) => {
    let prochain = null;
    if (evenement.key === 'ArrowRight') prochain = onglets[index + 1] || onglets[0];
    if (evenement.key === 'ArrowLeft') prochain = onglets[index - 1] || onglets[onglets.length - 1];
    if (prochain) activerOnglet(prochain);
  });
});
```

Le focus se déplace physiquement vers l'onglet activé, ce qui garantit qu'un lecteur d'écran annonce immédiatement le nouveau jour sélectionné, sans que l'utilisateur ait besoin d'appuyer une seconde fois sur `Tab`.

## Vérifier l'annonce du jour actif

Le test au lecteur d'écran doit confirmer une annonce du type « Vendredi, onglet, sélectionné, 1 sur 4 ». Cette annonce dépend entièrement de la présence correcte de `aria-selected` et du rôle `tab` : sans eux, le lecteur d'écran se contente d'annoncer « bouton », sans indiquer ni la sélection ni la position dans le groupe.

- Vérifier que seul l'onglet actif possède `tabindex="0"` ;
- Vérifier que le panneau masqué porte bien l'attribut `hidden`, et pas seulement une classe CSS ;
- Vérifier que le focus visuel suit le focus réel après chaque changement de jour.

## Notre verdict

Un lecteur de programme d'événementiel bien construit ne nécessite aucune extension : trois rôles ARIA, une fonction PHP de rendu et une trentaine de lignes de JavaScript suffisent à obtenir un composant qui se comporte exactement comme les onglets natifs attendus par les technologies d'assistance, tout en restant entièrement personnalisable dans son style visuel.
