Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Control card swipers with keyboard #79

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

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.

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