interface BottomSheetAccessibilityManagerProps {
isOpen: boolean;
bottomSheetId: string;
children: React.ReactNode;
initialFocusElementId?: string;
}
const BottomSheetAccessibilityManager = ({
isOpen,
bottomSheetId,
children,
initialFocusElementId
}: BottomSheetAccessibilityManagerProps) => {
const previousFocusRef = useRef<HTMLElement | null>(null);
useEffect(() => {
const bottomSheet = document.getElementById(bottomSheetId);
if (isOpen && bottomSheet) {
// 현재 포커스 저장
previousFocusRef.current = document.activeElement as HTMLElement;
// 형제 요소들 inert 처리
const siblings = Array.from(bottomSheet.parentElement?.children || [])
.filter(child => child !== bottomSheet);
siblings.forEach(sibling => {
sibling.setAttribute('inert', '');
});
// 포커스 이동 처리
setTimeout(() => {
// 페이지 로딩 시 자동 오픈이거나 이전 포커스가 없는 경우
if (!previousFocusRef.current || previousFocusRef.current === document.body) {
if (initialFocusElementId) {
const initialFocusElement = document.getElementById(initialFocusElementId);
if (initialFocusElement) {
initialFocusElement.focus();
return;
}
}
}
// 일반적인 포커스 이동 처리
const focusableElement = bottomSheet.querySelector(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
) as HTMLElement;
if (focusableElement) {
focusableElement.focus();
} else {
bottomSheet.setAttribute('tabindex', '-1');
bottomSheet.focus();
}
}, 500);
} else if (!isOpen && bottomSheet) {
// inert 속성 제거
const siblings = Array.from(bottomSheet.parentElement?.children || [])
.filter(child => child !== bottomSheet);
siblings.forEach(sibling => {
sibling.removeAttribute('inert');
});
// 이전 포커스로 복귀
// 이전 포커스가 유효한 경우에만 포커스 이동
setTimeout(() => {
if (previousFocusRef.current && previousFocusRef.current !== document.body) {
previousFocusRef.current.focus();
}
}, 500);
}
}, [isOpen, bottomSheetId, initialFocusElementId]);
return <>{children}</>;
};
export default BottomSheetAccessibilityManager;
답글 남기기
댓글을 달기 위해서는 로그인해야합니다.