|
1 |
| -import { useRef, useState } from 'react'; |
2 |
| -import { useLayoutEffect } from './useLayoutEffect'; |
| 1 | +import { useCallback, useState } from 'react'; |
3 | 2 |
|
4 | 3 | // https://www.w3.org/TR/wai-aria-practices-1.1/#kbd_roving_tabindex
|
5 | 4 | export function useRovingCellRef(isSelected: boolean) {
|
6 |
| - const ref = useRef<HTMLDivElement>(null); |
7 | 5 | // https://www.w3.org/TR/wai-aria-practices-1.1/#gridNav_focus
|
8 |
| - const isChildFocused = useRef(false); |
9 |
| - const [, forceRender] = useState<unknown>({}); |
| 6 | + const [isChildFocused, setIsChildFocused] = useState(false); |
10 | 7 |
|
11 |
| - useLayoutEffect(() => { |
12 |
| - if (!isSelected) { |
13 |
| - isChildFocused.current = false; |
14 |
| - return; |
15 |
| - } |
| 8 | + if (isChildFocused && !isSelected) { |
| 9 | + setIsChildFocused(false); |
| 10 | + } |
16 | 11 |
|
17 |
| - if (isChildFocused.current) { |
18 |
| - // When the child is focused, we need to rerender |
19 |
| - // the cell again so tabIndex is updated to -1 |
20 |
| - forceRender({}); |
21 |
| - return; |
22 |
| - } |
23 |
| - ref.current?.focus({ preventScroll: true }); |
24 |
| - }, [isSelected]); |
| 12 | + const ref = useCallback((cell: HTMLDivElement | null) => { |
| 13 | + if (cell === null || cell.contains(document.activeElement)) return; |
| 14 | + |
| 15 | + cell.focus({ preventScroll: true }); |
| 16 | + }, []); |
25 | 17 |
|
26 | 18 | function onFocus(event: React.FocusEvent<HTMLDivElement>) {
|
27 |
| - if (event.target !== ref.current) { |
28 |
| - isChildFocused.current = true; |
| 19 | + if (event.target !== event.currentTarget) { |
| 20 | + setIsChildFocused(true); |
29 | 21 | }
|
30 | 22 | }
|
31 | 23 |
|
32 |
| - const isFocused = isSelected && !isChildFocused.current; |
| 24 | + const isFocused = isSelected && !isChildFocused; |
33 | 25 |
|
34 | 26 | return {
|
35 |
| - ref, |
| 27 | + ref: isSelected ? ref : undefined, |
36 | 28 | tabIndex: isFocused ? 0 : -1,
|
37 |
| - onFocus |
| 29 | + onFocus: isSelected ? onFocus : undefined |
38 | 30 | };
|
39 | 31 | }
|
0 commit comments