/
use-focus-return.ts
46 lines (38 loc) · 1.23 KB
/
use-focus-return.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { useRef } from 'react';
import { useDidUpdate } from '../use-did-update/use-did-update';
interface UseFocusReturn {
opened: boolean;
shouldReturnFocus?: boolean;
}
/** Returns focus to last active element, used in Modal and Drawer */
export function useFocusReturn({ opened, shouldReturnFocus = true }: UseFocusReturn) {
const lastActiveElement = useRef<HTMLElement>();
const returnFocus = () => {
if (
lastActiveElement.current &&
'focus' in lastActiveElement.current &&
typeof lastActiveElement.current.focus === 'function'
) {
lastActiveElement.current?.focus();
}
};
useDidUpdate(() => {
let timeout = -1;
const clearFocusTimeout = (event: KeyboardEvent) => {
if (event.key === 'Tab') {
window.clearTimeout(timeout);
}
};
document.addEventListener('keydown', clearFocusTimeout);
if (opened) {
lastActiveElement.current = document.activeElement as HTMLElement;
} else if (shouldReturnFocus) {
timeout = window.setTimeout(returnFocus, 10);
}
return () => {
window.clearTimeout(timeout);
document.removeEventListener('keydown', clearFocusTimeout);
};
}, [opened, shouldReturnFocus]);
return returnFocus;
}