리팩토링-웹 접근성- 키보드 사용 유저를 위한 모달 버튼에 tab focusing

김철준·5일 전
0

리팩토링

목록 보기
8/9

Lighthouse로 접근성을 측정하면 아래와 같이 직접 확인을 해야할 목록들을 보여줍니다.

그중에서 위에서 펼쳐진 부분에 대해서 멈칫했는데요.

모달 같은 컨텐츠가 있을시, 유저가 포커스할 때, 모달 내부 인터렉션이 포커스가 되어야한다고 말해주고 있습니다.

이제 저의 문제 상황을 말해보도록 하겠습니다.

문제 상황

저의 경우, 정답을 체크하고 채점을 누르면 퀴즈에 대한 결과를 모달로 보여주고 있습니다.

하지만 위 상태에서 tab을 누르면 바로 모달 내부의 해설 버튼에 포커싱이 가지 않습니다.

tab을 누르면서 본 페이지의 인터렉티브 UI를 다 거치고 나서야 모달의 버튼에 포커싱이 되죠.

포커싱된 상태

다시 한번, Lighthouse에서 제안한 항목을 살펴보겠습니다.

모달 같은 컨텐츠가 있을시, 유저가 포커스할 때, 모달 내부 인터렉션이 포커스가 되어야한다고 말해주고 있습니다.

지금 저의 모달 상태는 위 권장사항을 따르지 못하고 있죠.

따라서 저는 모달이 열릴 때, 해설 버튼에 포커싱을 잡아보도록 하겠습니다.

How about tabIndex?

tabIndex는 주로 Tab 키를 사용하는 연속적인 키보드 탐색에서 어느 순서에 위치할지 지정합니다.

인터렉션한 UI들을 키보드로 탐색할 때, tab을 통해 탐색할 수 있죠.

이는 마우스 사용이 불가하거나 신체적으로 불편한 경우(마우스를 못 잡는 경우가 있을 수도 있으실 수 있겠죠)를 대비하여 웹 접근성을 높이기위해 필요한 기능이죠.

어쨋든 tabIndex값 설정을 통해 tab을 누를 때, 인터렉션 요소 탐색 우선 순위를 설정할 수 있습니다.

양의 정숫값은 요소를 연속 키보드 탐색으로 접근할 수 있으며, 그 순서는 해당 값으로 지정하겠다는 것을 뜻합니다.

즉, tabindex="4"인 요소는 tabindex="5"와 tabindex="0"인 요소 이전에, 그러나 tabindex="3"인 요소 이후에 접근할 수 있습니다.

다수의 요소가 하나의 값을 공유할 경우 그 안에서 문서 소스 코드의 순서를 따릅니다. 최댓값은 32767입니다.


	// 체크박스
   <input
                tabIndex={0}
                className={"accent-orange-600 w-5 h-5"}
                type={"checkbox"}
              
            />

	// 일반 인풋
  <input
                tabIndex={1}
                className={"accent-orange-600 w-5 h-5"}
                type={"text"}
              
            />

	// 숫자 인풋
  <input
                tabIndex={2}
                className={"accent-orange-600 w-5 h-5"}
                type={"text"}
              
            />

위처럼 체크박스와 인풋이 있다고 했을 때, tab으로 포커싱을 잡을시, 체크박스가 앞쪽에 위치했음에도 불구하고 일반 텍스트 인풋이 먼저 잡히고 그 다음으로 숫자 인풋이 잡히고 그 다음으로 체크박스가 잡히게 되죠.

tabIndex는 적용 안됨.

그래서 저는 모달 버튼들에 tabIndex를 엄청 높게 주면 어떨까?라는 생각을 하여 버튼들에 tabIndex값을 높히 설정해보았습니다.

        <PrimaryLink
                key={index}
                href={link.href}
                color={link.color}
          		tabIndex={1000}
             
            >
                {link.text}
            </PrimaryLink>

하지만 위와 같이 하여도 모달이 떠있는 경우,tab으로 하여도 focusing이 안되더군요.

그래서 다른 방법을 생각해봤습니다.

모달 띄울시, 첫번째 링크 포커싱

프로그램적으로 접근해보았습니다.
모달이 처음 띄워질 때, 첫번째 링크가 포커싱되게 말이죠.

따라서 다음과 같이 코드를 구성해보았습니다.

import PrimaryLink from "@/app/_components/link/primaryLink";
import { ModalContext } from "@/app/_components/modal/_context/modalContext";
import React, {
    useContext,
    useEffect,
    useRef,
} from "react";

// 모달 링크
function ModalLinks() {
    const modal = useContext(ModalContext);

    const firstLinkRef = useRef<null | HTMLAnchorElement>(
        null,
    ); // 첫 번째 링크를 참조하기 위한 ref

    useEffect(() => {
        // 모달 링크가 열릴 때 첫 번째 링크에 포커스 설정
        if (firstLinkRef.current) {
            firstLinkRef.current.focus();
        }
    }, [modal.links]); // 링크 배열이 변경될 때마다 실행

    return (
        modal.links &&
        modal.links.map((link, index) => (
            <PrimaryLink
                key={index}
                href={link.href}
                color={link.color}
                ref={index === 0 ? firstLinkRef : null} // 첫 번째 링크에만 ref 연결
            >
                {link.text}
            </PrimaryLink>
        ))
    );
}

export default ModalLinks;

여러 개의 링크들 중 첫번째 링크 UI에 ref 속성을 부여하여 처음 Mount될시, foucs를 잡게 하였습니다.

위와 같은 방법뿐만 포커스 트랩이라는 방법도 사용할 수 있습니다.

포커스 트랩은 모달이 열려 있는 동안 포커스가 모달 내부의 요소에서만 이동할 수 있도록 ,모달 외부 인터렉션 UI에 포커싱 제한을 두는 방법입니다.

여하튼 위와 같은 작업을 통해 웹 접근성을 한층 높일 수 있게 되었습니다.

profile
FE DEVELOPER

0개의 댓글