[FEATURE] 캐로셀 2차 리팩토링
ssw6750 opened this issue · comments
📝 TASK 개요
💬 접근성 준수의 대전제는 “차별 없는 적절한 대체 수단 제공”이다. 현재까지 구현한 캐러셀 접근성은 4원칙 중 “운용의 용이성” 문제 해결만 신경쓴 것으로, “인식”, “이해” 등의 문제는 해결되지 않았다. (접근성 4원칙 = 인식, 운용, 이해, 견고)
동등하지 않은 정보를 제공하는 것은 제공하지 않는 것만 못하다. 정보는 누구에게나 동등하게 제공해야 한다.
캐로셀 접근성 향상
자동 넘김 제어도 안될 뿐더러 화면에 보이지 않는 슬라이드도 모두 접근하고 심지어 내용조차 제대로 알 수 없다..!!
1. 현재 접근중인 컨텐츠가 캐로셀이라는 걸 알 수 있도록 정보 제공
- 의미론적 관점에서 접근
- 캐로셀이란 용어는 데이터에 대한 정보가 아닌 유저 인터페이스에 대한 정보이다.
- 즉 캐로셀은 영역의 이름이 아닌 영역에 대한 부가 설명적인 정보이다.
aria-label='메인 캐로셀'
aria-roledescription='carousel'
role='region'
2. 포커스 표시기가 눈에 보이도록 유지
outline-offset: -2px;
추가하여 기존에 흐릿하던 포커싱을 잘 보이도록 개선
3. 자동 넘김을 일시 정지 할 수 있는 기능 제공
스와이퍼 속성에 autoplay={{ delay: 4000 }}
를 추가하여 자동 넘김 기능 추가
const stop = (e) => {
e.preventDefault();
swiperRef.current.swiper.autoplay.stop();
};
const start = (e) => {
e.preventDefault();
swiperRef.current.swiper.autoplay.start();
};
해당 event함수
를 button
에 부여하여 자동 넘김을 제어할 수 있도록 함
4. 보이지 않는 슬라이드는 접근 불가능 해야함
- 메인 캐로셀 개선
swiper의 isActive 속성을 활용하여 보이지 않는 슬라이더의 접근을 제어함
aria-hidden={isActive ? false : true}
tabIndex={isActive ? 'none' : -1}
해당 코드로 인해 스와이퍼에 활성화된 슬라이드(캐로셀에 보이는 하나의 슬라이드)만 접근 가능하다.
- 상품 캐로셀 개선
상품 캐로셀은 아이템이 4개씩 보여지기 때문에 swiper에서 제공하는 isActive 속성으로는 구현하기 어렵다고 판단함
const [focusableIndex, setFocusableIndex] = useState(0);
<div>
...
<button
ref={navigationPrevRef}
aria-label="이전 항목 보기"
className={classnames(classes.swiperPrevBtn, classes.swiperButton)}
onClick={() => {
setFocusableIndex((prev) => prev - 4);
}}
/>
<button
ref={navigationNextRef}
aria-label="다음 항목 보기"
className={classnames(classes.swiperNextBtn, classes.swiperButton)}
onClick={() => {
setFocusableIndex((prev) => prev + 4);
}}
/>
...
</div>
위 코드를 통하여 포커싱되는 슬라이드의 인덱싱을 저장함
const productCards = productList.slice(0, 12).map((product, index) => (
<SwiperSlide key={index}>
<ProductCard
product={product}
isActive={focusableIndex <= index && index < focusableIndex + 4}
/>
</SwiperSlide>
));
위 코드에서 isActive={focusableIndex <= index && index < focusableIndex + 4}
으로 인해 상품 캐로셀에 보여지는 4개의 상품 카드만 isActive
를 true
로 받아옴, 이후 받아온 isActive
를 swiper의 isActive
속성 처럼 사용
forwardRef 사용해서 해결하려고 시도했으나 그러면 상품카드 내부의 장바구니 담기 버튼에는 여전히 접근이 가능하기 때문에 문제가 발생했음
5. 캐로셀 슬라이드가 넘어갔다면 사용자에게 알려줘야함
- 메인캐로셀
<div ref={notifyRef} aria-live="assertive" className="a11yHidden" />
메시지를 알려주는 요소를 추가하고 숨김처리함
const [slideInfo, setSlideInfo] = useState(null);
useEffect(() => {
if (slideInfo !== null) notifyRef.current.textContent = slideInfo;
}, [slideInfo]);
...
if (isActive) {
setSlideInfo(banner.title);
}
swiper
의 active 요소
가 바뀔때 slideInfo
의 상태가 변경이 되고, useEffect
가 이를 감지하여 notifyRef
의 textContent
를 변경하고 aria-live="assertive"
가 이를 감지하여 textContent
를 읽어주는 로직이다.
6. 실행화면
7. 레이아웃 버그 수정
뷰포트
를 줄이면 메인 캐로셀
때문에 레이아웃이 무너지는 현상이 발생함.
✅ To Do 및 진행상황
- 현재 접근중인 컨텐츠가 캐로셀이라는 걸 알 수 있도록 정보 제공
- 포커스 표시기가 눈에 보이도록 유지
- 자동 넘김을 일시 정지 할 수 있는 기능 제공
- 보이지 않는 슬라이드는 접근 불가능 해야함
- 캐로셀 슬라이드가 넘어갔다면 사용자에게 알려줘야함
- 레이아웃 버그 수정