JSFiddle - React, Tailwind, and code Playground

by seulbiLee

HTML

<link rel="stylesheet" href="https://unpkg.com/swiper@7/swiper-bundle.min.css" />
<script src="https://unpkg.com/swiper@7/swiper-bundle.min.js"></script>
<div class="wrap-slide-box">
  <div class="swiper-button-next"></div>
  <div class="swiper-container">
    <div class="swiper-wrapper">
      <div class="swiper-slide slide01" tabindex="-1">
        <h1>slide 1</h1>
        <ol>
          <li><a href="javascript:;">링크 1-1</a></li>
          <li><a href="javascript:;">링크 1-2</a></li>
          <li><a href="javascript:;">링크 1-3</a></li>
          <li><a href="javascript:;">링크 1-4</a></li>
        </ol>
      </div>
      <div class="swiper-slide slide02" tabindex="-1">
        <h1>slide 2</h1>
      </div>
      <div class="swiper-slide slide03" tabindex="-1">
        <h1>slide 3</h1>
        <ol>
          <li><a href="javascript:;">링크 3-1</a></li>
          <li><a href="javascript:;">링크 3-2</a></li>
          <li><a href="javascript:;">링크 3-3</a></li>
          <li><a href="javascript:;">링크 3-4</a></li>
        </ol>
      </div>
      <div class="swiper-slide slide04" tabindex="-1">
        <h1>slide 4</h1>
        <ol>
          <li><a href="javascript:;">링크 4-1</a></li>
          <li><a href="javascript:;">링크 4-2</a></li>
          <li><a href="javascript:;">링크 4-3</a></li>
          <li><a href="javascript:;">링크 4-4</a></li>
        </ol>
      </div>
      <div class="swiper-slide slide05" tabindex="-1">
        <h1>slide 5</h1>
        <ol>
          <li><a href="javascript:;">링크 5-1</a></li>
          <li><a href="javascript:;">링크 5-2</a></li>
          <li><a href="javascript:;">링크 5-3</a></li>
          <li><a href="javascript:;">링크 5-4</a></li>
        </ol>
      </div>
    </div>
    <div class="swiper-button-prev"></div>
    <div class="swiper-pagination"></div>
  </div>
</div>

CSS

.wrap-slide-box {position: relative; width: 100%; max-width: 700px; height: 400px; margin: 0 auto;}
.swiper-container {width: 80%; height: 100%; margin: 0 auto; overflow: hidden;}
.swiper-slide {display: flex; flex-wrap: wrap; align-content: center; justify-content: center; width: 100%;}
.swiper-slide h1 {width: 100%; text-align: center;}
.swiper-slide ol {width: auto; margin: 0 auto;}
.swiper-slide.slide01 {background-color: palegoldenrod;}
.swiper-slide.slide02 {background-color: paleturquoise;}
.swiper-slide.slide03 {background-color:palevioletred;}
.swiper-slide.slide04 {background-color:lightsteelblue;}
.swiper-slide.slide05 {background-color:yellowgreen;}

JavaScript

let thisSlide, // Swiper Slide
    focusOut, // 슬라이드 키보드 접근 확인
    slideFocus = {}, // 슬라이드 내부 탭 포커스 가능한 요소 저장
    swiperWrapper = document.querySelector('.swiper-wrapper'),
    slideAll, // 전체 슬라이드 저장
    realSlideAll, // loop 모드 일때 복사 된 슬라이드를 제외한 실제 슬라이드 저장
    slideLength, // 슬라이드 갯수 - 1
    onClickNavigation, // 슬라이드 이전/다음 버튼으로 슬라이드 전환 확인
    navigations = {}, // 슬라이드 이전 다음 버튼
    prevEnter; // 이전 버튼 키보드 엔터로 접근 확인
const slideKeyDownEvt = (e, idx) => {
  // back tab : 첫 번째 슬라이드 포커스 시
  if (e.key == 'Tab' && e.shiftKey && thisSlide.realIndex === 0) {
    focusOut = false;
    // back tab : 그 외 슬라이드 포커스 시
  } else if (e.key == 'Tab' && e.shiftKey && e.target === slideFocus[idx][0]) {
    e.preventDefault();
    focusOut = true;
    realSlideAll[thisSlide.realIndex - 1].setAttribute('tabindex', '0');
    thisSlide.slideTo(thisSlide.activeIndex - 1);
    removeSlideTabindex();
  } else if (e.key == 'Tab' && !e.shiftKey && e.target === slideFocus[idx][slideFocus[idx].length - 1]) {
    if (idx >= slideLength) {
      // tab : 마지막 슬라이드 내 마지막 요소 포커스 시
      focusOut = false;
    } else {
      // tab : 그 외 슬라이드 내 마지막 요소 포커스 시
      e.preventDefault();
      if (realSlideAll[thisSlide.realIndex + 1] <= slideLength) realSlideAll[thisSlide.realIndex + 1].setAttribute('tabindex', '0');
      focusOut = true;
      thisSlide.slideTo(thisSlide.activeIndex + 1);
      removeSlideTabindex();
    };
  };
};
// 슬라이드 내부 클릭 요소 tabindex 값 삭제
const removeSlideTabindex = () => {
  slideAll.forEach((element, i) => {
    let focusTarget = Array.prototype.slice.call(element.querySelectorAll('a, button, input, [role="button"], textarea, select, [tabindex="0"]'));
    focusTarget.forEach((el, idx) => {
      if (el.closest('.swiper-slide') === slideAll[thisSlide.activeIndex]) el.removeAttribute('tabindex');
    });
  });
};
const slideFocusAct = (e, idx, next) => {
  if (onClickNavigation) {
    if (e.key == 'Enter' && !next) prevEnter = true;
    else if (e.key == 'Tab') {
      if...