Guidelines
Accessibility
접근성 baseline — 터치 타겟, 대비, focus, a11y semantics.
Touch Target
- iOS: 최소 44 × 44px
- Android: 최소 48 × 48dp
- 리스트 행: 최소 48px 높이 (편안한 탭)
- 탭 타겟: 인접 탭 라벨 간 충분한 간격
Color Contrast
- WCAG AA 준수 필수
- 본문 텍스트 ≥ 4.5:1
- 큰 텍스트 (18px+ 또는 14px Bold) ≥ 3:1
- 상태를 컬러만으로 전달 금지 — 아이콘/텍스트 병행
Focus
- Focus ring: shadcn
focus-visible:ring-2 ring-offset-2 - Ring color:
brown-800(#3A2018) focus-visible(키보드)만 링 표시,:focus마우스 클릭엔 안 보이게
Disabled
disabled:pointer-events-none disabled:opacity-50Semantic Roles (per component)
- Button →
role="button", disabled state 전달 - IconButton →
accessibilityLabel필수 - Input → Label 연결 (
htmlFor/nativeID), error 텍스트 연결 (aria-describedby) - Dialog → Focus trap, Esc close, 첫 focus = title/primary input (destructive 금지)
- AlertDialog (destructive) → 초기 focus = Cancel
- Tabs →
role="tablist"+ roving tabindex - Tooltip → hover 전용 금지, focus/tap 접근 보장
- Toast →
aria-live="polite"(info/success),assertive(warning/error)
Keyboard Navigation
- Tab: 인터랙티브 요소 순환
- Shift+Tab: 역순
- Arrow keys: 그룹 내부 (RadioGroup, Tabs, DropdownMenu, Calendar)
- Enter / Space: 선택/실행
- Esc: Dialog, Sheet, Popover, DropdownMenu 닫기
Screen Reader Announcement
- Loading 상태 변경 →
aria-live또는role="status" - AI streaming text →
aria-busy="true"+aria-live="polite" - Destructive action 실행 후 → Toast로 결과 announcement
RTL Support
현재 미지원. v0.3 기준 RTL 레이아웃 작업 대상 아님. 필요 시 별도 결정.
A11y Test Pipeline
현재 미완. 최소 게이트 도입 예정:
eslint-plugin-jsx-a11ylint- axe-core smoke test (핵심 컴포넌트)
Do / Don't
- Do: 터치 타겟 ≥ 44px 항상 유지
- Do: 상태는 컬러 + 아이콘/텍스트 이중 전달
- Do: 모든 icon-only 버튼에
accessibilityLabel필수 - Do: Focus ring은 키보드 포커스에만 표시
- Don't: hover 전용 UI 금지 (모바일/키보드 접근 불가)
- Don't: 컬러만으로 상태 전달 금지
- Don't: Placeholder를 label 대용으로 사용 금지
