접근성
모든 피커 컴포넌트는 내장된 접근성 지원과 함께 제공됩니다. 키보드 탐색, ARIA 속성 및 포커스 관리는 Styled, Tailwind v3/v4 및 Headless와 같은 모든 변형에서 기본적으로 작동합니다.
표준적인 사용을 위해서는 추가 설정이 필요하지 않습니다. 이 페이지는 사용자 정의 UI에서 패턴을 감사하거나, 확장하거나, 복제할 수 있도록 포함된 내용을 문서화합니다.
키보드 탐색
달력 피커
| 키 | 동작 |
|---|---|
ArrowLeft | 이전 날짜로 포커스 이동 |
ArrowRight | 다음 날짜로 포커스 이동 |
ArrowUp | 이전 주(같은 요일)로 포커스 이동 |
ArrowDown | 다음 주(같은 요일)로 포커스 이동 |
Enter / Space | 포커스된 날짜 선택 |
Escape | 변경 사항 취소 및 팝업 닫기 |
Tab | 다음 포커스 가능한 요소로 이동 (브라우저 기본값) |
비활성화된 날짜 건너뛰기: 화살표 키로 탐색할 때 비활성화된 날짜는 자동으로 건너뜁니다. 피커는 다음 활성화된 날짜를 찾기 위해 이동 방향으로 최대 365일까지 검색합니다.
자동 월 스크롤: 키보드 포커스가 다른 월의 날짜로 이동하면 해당 월을 표시하도록 달력 보기가 업데이트됩니다.
시간 피커
| 키 | 동작 |
|---|---|
Escape | 변경 사항 취소 및 팝업 닫기 |
시간 선택은 클릭/터치 상호작용이 있는 스크롤 휠 UI를 사용합니다. 스크롤 열은 정확한 값 선택을 위해 scroll-snap을 사용합니다.
ARIA 속성
모든 대화형 요소에는 적절한 ARIA 역할과 속성이 있습니다:
팝업 및 컨테이너
| 요소 | 속성 | 값 |
|---|---|---|
| 팝업 컨테이너 | role | "dialog" |
| 인라인 컨테이너 | role | "group" |
| 컨테이너 | aria-label | 로케일의 플레이스홀더 텍스트 |
| 컨테이너 | aria-activedescendant | 현재 포커스된 날짜 셀의 ID |
트리거 버튼
| 속성 | 값 |
|---|---|
aria-expanded | 팝업이 열려 있을 때 true |
aria-haspopup | "dialog" |
달력 그리드
| 요소 | 속성 | 값 |
|---|---|---|
| 그리드 래퍼 | role | "grid" |
| 주(Week) 행 | role | "row" |
| 요일 헤더 셀 | role | "columnheader" |
| 날짜 셀 | role | "gridcell" |
| 날짜 셀 | aria-selected | 선택되었을 때 true |
| 날짜 셀 | aria-current | 셀이 오늘일 때 "date" |
| 날짜 셀 | aria-label | 포맷된 날짜 문자열 (예: "2026-03-04") |
| 날짜 셀 | disabled | 비활성화된 날짜에 설정됨 (네이티브 HTML 속성) |
탐색 및 드롭다운
| 요소 | 속성 | 값 |
|---|---|---|
| 이전 월 버튼 | aria-label | "Previous month" (locale.prevMonthLabel에서 옴) |
| 다음 월 버튼 | aria-label | "Next month" (locale.nextMonthLabel에서 옴) |
| 월 드롭다운 | aria-label | "Select month" (locale.selectMonthLabel에서 옴) |
| 연도 드롭다운 | aria-label | "Select year" (locale.selectYearLabel에서 옴) |
시간 열
| 요소 | 속성 | 값 |
|---|---|---|
| 시간 열 | role | "listbox" |
| 시간 열 | aria-orientation | "vertical" |
| 시간 열 | aria-label | "Hours" (locale.hourLabel에서 옴) |
| 분 열 | role | "listbox" |
| 분 열 | aria-orientation | "vertical" |
| 분 열 | aria-label | "Minutes" (locale.minuteLabel에서 옴) |
| 초 열 | role | "listbox" |
| 초 열 | aria-orientation | "vertical" |
| 초 열 | aria-label | "Seconds" (locale.secondLabel에서 옴) |
| 시간 항목 | role | "option" (패딩 항목: "presentation") |
| 시간 항목 | aria-selected | 항목이 현재 값일 때 true |
| 오전/오후 토글 | aria-label | 현재 시간대 + ”, toggle AM/PM” |
| 지우기 버튼 | aria-label | "Clear" (locale.clear에서 옴) |
모든 레이블 문자열은 로케일 시스템을 통해 사용자 정의할 수 있습니다.
포커스 관리
로빙 탭인덱스
달력 그리드는 로빙 탭인덱스(roving tabindex) 패턴을 사용합니다:
- 현재 포커스된 날짜 셀만
tabIndex={0}(탭 가능)을 가집니다. - 다른 모든 날짜 셀은
tabIndex={-1}(탭 불가능하지만 화살표 키로 포커스 가능)을 가집니다. - 즉,
Tab은 포커스를 달력 그리드 밖으로(다음 컨트롤로) 이동시키고, 화살표 키는 그리드 내에서 포커스를 이동시킵니다.
팝업 포커스 트래핑
팝업 모드는 @floating-ui/react의 FloatingFocusManager를 사용하여 다음을 수행합니다:
- 열려 있는 동안 팝업 내에 포커스를 가둡니다.
- 팝업이 닫힐 때 트리거 버튼으로 포커스를 반환합니다.
- 탭 키를 사용하여 팝업을 벗어나 배경 콘텐츠로 이동하는 것을 방지합니다.
네이티브 요소
월 및 연도 선택은 기본적으로 키보드 접근이 가능한 네이티브 <select> 요소를 사용합니다. 날짜 셀은 적절한 비활성화 상태가 있는 네이티브 <button> 요소를 사용합니다.
WCAG 2.1 준수
다음 WCAG 2.1 성공 기준이