홈으로 돌아가기

접근 가능한 DatePicker React WCAG 2.2

이 기사는 React에서 WCAG 2.2 AA DatePicker를 AI 생성 수정으로 만드는 방법을 설명합니다. APG에서 벗어난 점, focus 관리, aria-live assertive를 다룹니다. 시니어 개발자를 위한.

React WCAG DatePicker: AI에서 이상적 구현까지
Advertisement 728x90

WCAG 2.2 AA 준수 React DatePicker 제작 가이드

개발팀은 Claude가 생성한 WAI-ARIA APG의 "Date Picker Dialog" 패턴 기반 DatePicker 코드를 시작점으로 삼았습니다. 초기 프롬프트는 WCAG 2.1/2.2 AA 수준 요구사항을 명시했습니다: aria-describedby이 포함된 입력 필드, 트리거 버튼, role="dialog" 모달 대화상자, 그리드 기반 달력 테이블. 하지만 원본 버전에서 포커스, 탐색, 접근성에 치명적인 문제가 드러났습니다.

AI는 기본 키보드 탐색(화살표 키, Home/End, PageUp/Down, Enter/Space, Escape), 그리드셀 요소의 roving tabindex, 월 변경 시 aria-live="polite"를 구현했습니다. 그러나 VoiceOver와 NVDA 테스트에서 문제점이 확인됐습니다: 열 때 선택된 날짜에 포커스가 가지 않고, aria-live 발표가 대기열에 쌓이며, 반복 클릭 시 대화상자가 깜빡였습니다.

실전 접근성을 위한 APG 패턴 변형

APG 명세는 중첩 버튼 없이 <td role="gridcell">을 권장하며, 수동 onClick/onKeyDown과 tabindex에 의존합니다. 하지만 실제 테스트에서 <td> 내부 <button> 사용의 명확한 장점이 확인됐습니다:

Google AdInline article slot
  • 추가 코드 없이 네이티브 포커스 처리와 Enter/Space 지원.
  • 스크린 리더를 위한 자동 의미 전달.
  • aria-disabled나 preventDefault 없이 내장된 비활성화 상태.
  • 마우스나 키보드에서 안정적인 클릭 이벤트.

이는 의도된 선택입니다: APG는 가이드일 뿐, 실제 디바이스 테스트가 우선입니다. 우리는 4.5:1 이상 대비, CSS Modules, Date/Intl API 포맷팅을 사용해 React/TypeScript 외 외부 의존성을 없앴습니다.

기능 및 UX 문제 수정

원본 코드는 index.html 누락과 TypeScript 오류로 컴파일되지 않았습니다. 수정 후 추가 문제가 드러났습니다:

기능 버그:

Google AdInline article slot
  • minDate/maxDate 범위 외 날짜가 비활성화 셀 대신 다른 달로 점프.
  • 입력 필드 지우기 불가.

시각 문제:

  • 셀 포커스 스타일 누락.
  • td 크기 불균일.

접근성:

  • 열 때 선택 날짜 포커스 없음—스크린 리더 침묵.
  • 월 헤더 aria-live="polite"로 빠른 탐색 시 발표 대기.
  • 트리거 블러 + 클릭 시 대화상자 깜빡임.

수정 사항:

Google AdInline article slot
  • 열 때 값 또는 오늘에 포커스; 스크린 리더가 맥락(요일, 날짜, 월, 년) 발표.
  • 즉시 월 발표를 위한 별도 숨김 영역 aria-live="assertive".
  • 선택 후 포커스 트리거로 복귀, 업데이트된 aria-label.
  • 비활성화 일 있더라도 값의 월 표시.
  • OK/Cancel 제거: Enter 확인, Esc 닫기.

컴포넌트 구조와 키보드 탐색

Props: value (Date | null), onChange, minDate?, maxDate?, disabledDates?, locale?.

주요 ARIA:

  • 입력: 형식 설명 aria-describedby, readonly.
  • 트리거: 동적 aria-label ("선택됨: MM/DD/YYYY" 또는 "날짜 선택").
  • 대화상자: role="dialog", aria-modal="true", 포커스 트랩.
  • 그리드: table role="grid", button role="gridcell" td, 값에 aria-selected, 사용 불가 날짜에 aria-disabled.
  • 월 헤더: polite 영역 aria-live="assertive".

탐색:

  • 화살표 키: 인접 일.
  • Home/End: 월 첫/마지막 일.
  • PageUp/Down: ±1개월.
  • Shift+PageUp/Down: ±1년.
  • Enter/Space: 선택.
  • Escape: 닫기.

주요 교훈

  • AI는 뼈대(ARIA, 탐색)를 빠르게 만들지만, 스크린 리더 테스트 필수.
  • <td> 내 <button>이 브라우저 + 스크린 리더에서 순수 gridcell보다 안정적.
  • 월 탐색 중 대기 방지 aria-live="assertive".
  • 포커스 관리: 열 때 값/오늘, 트리거 복귀.
  • 최소 스택: React + TS, 라이브러리 없음.

이 컴포넌트는 단일 날짜 선택기로 프로덕션 준비 완료이며, 연도/범위 확장을 위한 오픈 코드입니다.

— Editorial Team

Advertisement 728x90

다음 읽기