UNPKG

@redocly/theme

Version:

Shared UI components lib

49 lines (41 loc) 1.51 kB
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(); }); }