Skip to content

Conversation

@simon-eller
Copy link

Added option on card swipers to control with keyboard for better accessibility.
Resolves #78.

Added option on card swipers to control via keyboard for better accessibility.
@crftwrk
Copy link
Member

crftwrk commented Aug 15, 2024

Thank you for this PR! Figured out that this seems not to be enough because keyboard: {enabled: true,},catches all swiper instances on a page, check https://dev.bootscore.me/plugins/bs-swiper/

Here is a rough idea:

First we have to add tabindex="0" attribute to all swiper-container templates. For example the cards:

<div class="cards swiper-container swiper position-static">

And then replace the minified js in assets/js/swiper-init.min.js with following source to test:

/**
 * Cards
 */
const bsSwiper = document.querySelectorAll('.cards');

for (let i = 0; i < bsSwiper.length; i++) {

  bsSwiper[i].classList.add('cards-' + i);

  // Create unique classes for navigation elements
  const nextEl = bsSwiper[i].querySelector('.swiper-button-next');
  const prevEl = bsSwiper[i].querySelector('.swiper-button-prev');
  nextEl.classList.add('swiper-button-next-' + i);
  prevEl.classList.add('swiper-button-prev-' + i);

  const slider = new Swiper('.cards-' + i, {
    slidesPerView: 1,
    spaceBetween: 20,
    loop: true,
    grabCursor: true,
    pagination: {
      el: '.swiper-pagination',
      clickable: true,
    },
    navigation: {
      nextEl: '.swiper-button-next-' + i,
      prevEl: '.swiper-button-prev-' + i,
    },
    breakpoints: {
      768: {
        slidesPerView: 2,
      },
      992: {
        slidesPerView: 3,
      },
      1400: {
        slidesPerView: 4,
      },
    }
  });

  // Manually handle keyboard events for this instance
  bsSwiper[i].addEventListener('keydown', (event) => {
    if (event.key === 'ArrowRight') {
      slider.slideNext();
    } else if (event.key === 'ArrowLeft') {
      slider.slidePrev();
    }
  });
}


/**
 * Cards Autoplay
 */
const bsSwiperAutoplay = document.querySelectorAll('.cards-autoplay');

for (let i = 0; i < bsSwiperAutoplay.length; i++) {

  bsSwiperAutoplay[i].classList.add('cards-autoplay-' + i);

  // Create unique classes for navigation elements
  const nextEl = bsSwiperAutoplay[i].querySelector('.swiper-button-next');
  const prevEl = bsSwiperAutoplay[i].querySelector('.swiper-button-prev');
  nextEl.classList.add('swiper-button-next-' + i);
  prevEl.classList.add('swiper-button-prev-' + i);

  const slider = new Swiper('.cards-autoplay-' + i, {
    slidesPerView: 1,
    spaceBetween: 20,
    loop: true,
    grabCursor: true,
    autoplay: {
      delay: 3000,
    },
    disableOnInteraction: false,
    pagination: {
      el: '.swiper-pagination',
      clickable: true,
    },
    navigation: {
      nextEl: '.swiper-button-next-' + i,
      prevEl: '.swiper-button-prev-' + i,
    },
    breakpoints: {
      768: {
        slidesPerView: 2,
      },
      992: {
        slidesPerView: 3,
      },
      1400: {
        slidesPerView: 4,
      },
    }
  });

  // Manually handle keyboard events for this instance
  bsSwiperAutoplay[i].addEventListener('keydown', (event) => {
    if (event.key === 'ArrowRight') {
      slider.slideNext();
    } else if (event.key === 'ArrowLeft') {
      slider.slidePrev();
    }
  });
}


/**
 * Hero
 */
const bsSwiperHero = document.querySelectorAll('.heroes');

for (let i = 0; i < bsSwiperHero.length; i++) {

  bsSwiperHero[i].classList.add('heroes-' + i);

  // Create unique classes for navigation elements
  const nextEl = bsSwiperHero[i].querySelector('.swiper-button-next');
  const prevEl = bsSwiperHero[i].querySelector('.swiper-button-prev');
  nextEl.classList.add('swiper-button-next-' + i);
  prevEl.classList.add('swiper-button-prev-' + i);

  const slider = new Swiper('.heroes-' + i, {
    slidesPerView: 1,
    loop: true,
    grabCursor: true,
    autoplay: {
      delay: 4000,
    },
    pagination: {
      el: '.swiper-pagination',
      clickable: true,
    },
    navigation: {
      nextEl: '.swiper-button-next-' + i,
      prevEl: '.swiper-button-prev-' + i,
    },
  });

  // Manually handle keyboard events for this instance
  bsSwiperHero[i].addEventListener('keydown', (event) => {
    if (event.key === 'ArrowRight') {
      slider.slideNext();
    } else if (event.key === 'ArrowLeft') {
      slider.slidePrev();
    }
  });
}


/**
 * Hero Fade
 */
const bsSwiperHeroFade = document.querySelectorAll('.heroes-fade');

for (let i = 0; i < bsSwiperHeroFade.length; i++) {

  bsSwiperHeroFade[i].classList.add('heroes-fade-' + i);

  // Create unique classes for navigation elements
  const nextEl = bsSwiperHeroFade[i].querySelector('.swiper-button-next');
  const prevEl = bsSwiperHeroFade[i].querySelector('.swiper-button-prev');
  nextEl.classList.add('swiper-button-next-' + i);
  prevEl.classList.add('swiper-button-prev-' + i);

  const slider = new Swiper('.heroes-fade-' + i, {
    slidesPerView: 1,
    loop: true,
    grabCursor: true,
    speed: 1500,
    effect: 'fade',
    fadeEffect: {
      crossFade: true
    },
    autoplay: {
      delay: 4000,
    },
    pagination: {
      el: '.swiper-pagination',
      clickable: true,
    },
    navigation: {
      nextEl: '.swiper-button-next-' + i,
      prevEl: '.swiper-button-prev-' + i,
    },
  });

  // Manually handle keyboard events for this instance
  bsSwiperHeroFade[i].addEventListener('keydown', (event) => {
    if (event.key === 'ArrowRight') {
      slider.slideNext();
    } else if (event.key === 'ArrowLeft') {
      slider.slidePrev();
    }
  });
}

If that works with multiple instances, we can add it to the source. Agree?

Edit: we need this for the Hero templates as well.

@crftwrk crftwrk self-requested a review August 15, 2024 17:31
@simon-eller
Copy link
Author

Ok, would have been too easy. I will test your code in a few days. Thanks in the meantime. :)

@crftwrk crftwrk marked this pull request as draft August 28, 2024 08:07
@crftwrk
Copy link
Member

crftwrk commented Aug 28, 2024

Turned to draft to avoid accidentally merging.

@crftwrk crftwrk removed this from v7 Aug 5, 2025
@crftwrk crftwrk added this to v6.4.0 Aug 5, 2025
@crftwrk crftwrk moved this to Todo in v6.4.0 Aug 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

Improve accessibility of swiper (no keyboard trap)

2 participants