Skip to content

Intégration base Slider — carrousel accessible - #510

Open
cedric07 wants to merge 2 commits into
masterfrom
feat/a11y-slider
Open

cedric07 wants to merge 2 commits into
masterfrom
feat/a11y-slider

Conversation

@cedric07

@cedric07 cedric07 commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Contexte et objectif

Cette évolution ajoute au thème Be API Frontend Framework une base réutilisable pour les carrousels basés sur Swiper (v14). L’objectif est de centraliser la configuration (modules, navigation, messages d’accessibilité), d’aligner le markup et les styles sur les conventions du thème, et de préparer l’internationalisation des chaînes exposées aux technologies d’assistance.

Il ne s’agit pas d’un bloc Gutenberg ni d’un composant visuel figé : c’est une brique technique (classe JS, partial PHP, feuille SCSS) que les projets enfants ou les futurs blocs/composants pourront brancher selon leurs besoins (slidesPerView, pagination, autoplay, etc.).

Dépendances

Package Rôle
swiper (^14.3.0) Bibliothèque de carrousel (import ESM + modules)
@wordpress/i18n Traduction des messages A11y côté JavaScript

Les styles de base Swiper sont importés dans le SCSS du thème (swiper/css, swiper/css/a11y).

Fichiers livrés

src/js/classes/Slider.js

Wrapper fin autour de Swiper, héritant de AbstractDomElement comme les autres classes DOM du thème.

Comportement par défaut

  • Modules toujours actifs : A11y et Navigation.
  • Les modules passés dans options.modules sont ajoutés sans écraser les défauts (évite la perte d’A11y/Navigation quand l’utilisateur ne redéclare pas tout).
  • Messages d’accessibilité Swiper traduits via __() et le text domain beapi-frontend-framework (prevSlideMessage, nextSlideMessage, première/dernière diapositive, pagination, libellé de slide).
  • Callback onChange (option du wrapper) branché sur l’événement slideChange de Swiper.

Options spécifiques au wrapper

Option Défaut Description
hideNavigationFromA11y false Si true : boutons préc./suiv. retirés de l’arbre d’accessibilité (tabindex="-1", aria-hidden="true") et suppression de .swiper-notification, utile quand chaque slide est déjà navigable au clavier (cartes focusables). Réappliqué après transitionEnd car Swiper réinitialise le tabindex.
fixLastSlideActiveOnEnd false Corrige .swiper-slide-active en fin de parcours pour slidesPerView: 'auto' ou des fractions « non demi » (ex. 2,75), où la dernière slide peut rester partiellement visible sans la classe active.
options voir Slider.defaults Objet natif SwiperOptions fusionné avec les défauts (dont a11y).

Accessibilité intégrée

  • Si les slides sont des <li>, slideRole est vidé pour ne pas imposer role="group" sur des éléments de liste (sémantique liste préservée pour les lecteurs d’écran). Surcharge possible via options.a11y.
  • Si la navigation reste exposée aux AT, la région live .swiper-notification est conservée pour les annonces première / précédente / suivante / dernière diapositive au clavier.
  • wrapperLiveRegion : laissé au comportement Swiper par défaut (polite sans autoplay, off avec autoplay), surcharge possible via options.a11y.

Initialisation

  • Slider.init('.selector', { … }) (pattern AbstractDomElement) ou new Slider(element, { … }).
  • getInstance() renvoie l’instance Swiper native pour les API avancées.

components/parts/common/swiper-controls.php

Partial PHP pour les contrôles de navigation :

  • Structure BEM : .swiper__controls > .swiper__buttons > boutons .swiper-button-prev / .swiper-button-next avec classe thème .swiper__button.
  • Libellés aria-label traduits via esc_attr_e() (Previous slide / Next slide, même msgid que le JS) ; Swiper peut les ajuster au runtime selon sa config A11y.

À inclure dans le conteneur .swiper :

get_template_part( 'components/parts/common/swiper', 'controls' );

Markup minimal attendu côté slide :

<div class="swiper">
  <div class="swiper-wrapper">
    <div class="swiper-slide">…</div>
  </div>
  <!-- partial swiper-controls -->
</div>

La navigation Swiper doit pointer vers les sélecteurs des boutons (ex. navigation: { prevEl: '.swiper-button-prev', nextEl: '.swiper-button-next' }), en général dans le scope du carrousel concerné.

src/scss/10-vendor/_swiper.scss

Couche de style projet par-dessus Swiper :

  • Couleur thème via --swiper-theme-color (variable SCSS primaire).
  • Zone contrôles centrée, masquée si Swiper verrouille la navigation (:has(.swiper-button-lock)).
  • Boutons 44×44 px (cible tactile confortable), fond circulaire, état désactivé (opacité + cursor: not-allowed).
  • Flèche précédente retournée en scaleX(-1).
  • Modificateur .swiper-overflow-visible pour déborder le viewport si besoin.
  • Reset liste sur .swiper-wrapper (padding, margin, list-style) pour usage avec <ul> / <li>.

Import ajouté dans style.scss et editor.scss pour cohérence front et éditeur.

inc/Services/Assets.php

  • Dépendance wp-i18n ajoutée au script principal scripts (en plus de jQuery).
  • wp_set_script_translations sur scripts avec le domaine beapi-frontend-framework et le dossier languages/, pour que les chaînes __() du bundle JS soient servies en .json (format Jed) côté WordPress.

Fichiers de traduction

  • Entrées ajoutées dans beapi-frontend-framework.pot et fr_FR.po pour les six messages A11y du slider.
  • Fichier JSON généré beapi-frontend-framework-fr_FR-*.json (hash lié au fichier dist/app.js après build).

Workflow traduction : après modification des chaînes dans Slider.js, rebuild du JS puis régénération / mise à jour des fichiers .pot, .po et JSON (WP-CLI ou outil du projet).

Exemple d’utilisation côté JavaScript

import Slider from './classes/Slider'
import { Pagination } from 'swiper/modules'

Slider.init('.my-slider', {
  hideNavigationFromA11y: true,
  fixLastSlideActiveOnEnd: true,
  onChange() {
    // Réagir au changement de slide (this = instance Slider)
  },
  options: {
    slidesPerView: 'auto',
    modules: [Pagination],
    navigation: {
      prevEl: '.my-slider .swiper-button-prev',
      nextEl: '.my-slider .swiper-button-next',
    },
    a11y: {
      // Optionnel : message spécifique à un contexte métier
      nextSlideMessage: 'Actualité suivante',
    },
  },
})

Les modules optionnels (Pagination, Autoplay, etc.) s’importent depuis swiper/modules et se déclarent dans options.modules ; A11y et Navigation restent présents sauf configuration Swiper explicite qui les désactiverait.

Points d’attention pour les intégrateurs

  1. Build : exécuter le build front (npm run build ou équivalent) pour que dist/app.js et le hash du fichier JSON de traduction restent alignés.
  2. Sélecteurs de navigation : en cas de plusieurs carrousels sur une page, cibler les boutons dans chaque instance (sélecteur scoped) pour éviter que Swiper ne lie tous les carrousels aux mêmes contrôles.
  3. Slides en liste : pour un carrousel sémantique <ul class="swiper-wrapper"> / <li class="swiper-slide">, le wrapper gère déjà slideRole ; conserver une structure HTML valide.
  4. Choix hideNavigationFromA11y : à activer lorsque la navigation prev/next est purement visuelle et que l’usage clavier se fait dans le contenu des slides ; à laisser à false si les boutons doivent rester utilisables et annoncés par les AT.
  5. Partial PHP : les aria-label partagent les mêmes chaînes que Slider.defaults ; recompiler le .mo après mise à jour du .po si besoin.

Synthèse

Cette PR pose les fondations Swiper + a11y + i18n + styles thème sans imposer un composant métier unique. Les prochaines étapes typiques sur un projet : brancher Slider.init depuis le point d’entrée JS du composant concerné, fournir le markup slide + partial contrôles, et étendre les options Swiper (pagination, breakpoints, loop, etc.) au cas par cas.


Note

Low Risk
New optional UI building blocks and asset i18n wiring; no changes to auth, data, or existing carousel behavior until adopted by callers.

Overview
Adds a reusable Swiper-based carousel foundation for the theme: Slider.js wraps Swiper 14 with default A11y and Navigation modules, translated screen-reader messages via @wordpress/i18n, and optional behaviors (hideNavigationFromA11y, fixLastSlideActiveOnEnd for slidesPerView: 'auto').

Also ships a swiper-controls PHP partial (prev/next with translated aria-labels), theme SCSS over Swiper (front + editor), and wires wp-i18n + wp_set_script_translations on the main script so JS strings load from languages/. French strings and POT entries cover the six slider A11y messages.

Nothing in this PR auto-instantiates sliders; consumers import Slider and include the partial when they add markup.

Reviewed by Cursor Bugbot for commit beedf40. Bugbot is set up for automated code reviews on this repo. Configure here.

…on and accessibility

- Added Swiper library for improved slider functionality.
- Created a new Slider class to manage Swiper instances with accessibility features.
- Implemented custom controls for previous and next slide navigation.
- Updated package dependencies to include Swiper and WordPress i18n for translations.
- Added French translations for slider navigation messages.
- Introduced SCSS styles for Swiper controls and integrated them into the main stylesheets.
- Replaced static French labels for previous and next slide buttons with translatable strings using WordPress i18n functions.
- Updated language files to include the new translations for accessibility.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant