@redocly/theme
Version:
Shared UI components lib
49 lines (41 loc) • 1.51 kB
text/typescript
import { useEffect, useRef } from 'react';
import type { MutableRefObject } from 'react';
export function useDialogHotKeys(
ref: MutableRefObject<HTMLElement | null>,
onClose: () => void,
): void {
const firstFocusableRef = useRef<HTMLElement>();
const lastFocusableRef = useRef<HTMLElement>();
const onKeyDownHandler = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
onClose();
} else if (event.key === 'Tab') {
if (!event.shiftKey && document.activeElement === lastFocusableRef.current) {
event.preventDefault();
firstFocusableRef.current?.focus();
} else if (event.shiftKey && document.activeElement === firstFocusableRef.current) {
event.preventDefault();
lastFocusableRef.current?.focus();
}
}
};
const onFocusableElementsHandler = () => {
const focusableElements = ref.current?.querySelectorAll(
'input, [href], [tabindex]:not([tabindex="-1"])',
);
if (focusableElements && focusableElements.length > 0) {
firstFocusableRef.current = focusableElements[0] as HTMLElement;
lastFocusableRef.current = focusableElements[focusableElements.length - 1] as HTMLElement;
}
};
useEffect(() => {
document.addEventListener('keydown', onKeyDownHandler);
return () => {
document.removeEventListener('keydown', onKeyDownHandler);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
onFocusableElementsHandler();
});
}