배경
#87 (PR #105)에서 모바일 사이드바·드롭다운의 키보드/포커스 접근성을 보강했다. 다만 완전한 모달 배경 격리는 범위 밖으로 남겨두었다.
현황 / 문제
mobile-sidebar.tsx와 search-modal.tsx 모두 role="dialog"로 열리지만, 다이얼로그 바깥 콘텐츠(헤더·본문)를 inert로 만들지 않는다.
- 결과적으로 물리적 Tab 포커스 트랩은 동작하지만, 스크린리더 가상 커서/스와이프로는 배경 콘텐츠에 여전히 도달할 수 있다.
- 이 한계 때문에 사이드바에서는 잘못된 약속을 피하려고 PR #105에서
aria-modal="true"를 제거했다. 즉 현재 두 오버레이 모두 "진짜 모달"은 아니다.
제안
- 패널을
createPortal로 document.body 최상위에 렌더한다. (SSR/하이드레이션 대비 mounted 가드 필요)
- 열린 동안 다이얼로그를 제외한 다른
document.body 자식 요소에 inert를 적용하고, 닫을 때 복구한다.
- 적용 후
aria-modal="true"를 (재)부여한다.
- 사이드바·검색 모달이 동일 패턴을 공유하므로, 참조 카운트 기반
useBodyScrollLock처럼 공용 훅(예: useModalA11y)으로 일원화한다.
참고
🤖 PR #105 리뷰 후속으로 등록
배경
#87 (PR #105)에서 모바일 사이드바·드롭다운의 키보드/포커스 접근성을 보강했다. 다만 완전한 모달 배경 격리는 범위 밖으로 남겨두었다.
현황 / 문제
mobile-sidebar.tsx와search-modal.tsx모두role="dialog"로 열리지만, 다이얼로그 바깥 콘텐츠(헤더·본문)를inert로 만들지 않는다.aria-modal="true"를 제거했다. 즉 현재 두 오버레이 모두 "진짜 모달"은 아니다.제안
createPortal로document.body최상위에 렌더한다. (SSR/하이드레이션 대비mounted가드 필요)document.body자식 요소에inert를 적용하고, 닫을 때 복구한다.aria-modal="true"를 (재)부여한다.useBodyScrollLock처럼 공용 훅(예:useModalA11y)으로 일원화한다.참고
apps/blog/src/components/search/search-modal.tsx,apps/blog/src/components/mobile-sidebar.tsx