diff --git a/src/components/Dialog.tsx b/src/components/Dialog.tsx index e2820380..f1b83b4e 100644 --- a/src/components/Dialog.tsx +++ b/src/components/Dialog.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import clsx from "clsx"; import { Modal } from "./Modal"; import { Island } from "./Island"; @@ -9,6 +9,14 @@ import { KEYS } from "../keys"; import "./Dialog.scss"; +const useRefState = () => { + const [refValue, setRefValue] = useState(null); + const refCallback = useCallback((value: T) => { + setRefValue(value); + }, []); + return [refValue, refCallback] as const; +}; + export const Dialog = (props: { children: React.ReactNode; className?: string; @@ -16,25 +24,23 @@ export const Dialog = (props: { onCloseRequest(): void; title: React.ReactNode; }) => { - const islandRef = useRef(null); + const [islandNode, setIslandNode] = useRefState(); useEffect(() => { - const focusableElements = queryFocusableElements(); + if (!islandNode) { + return; + } + + const focusableElements = queryFocusableElements(islandNode); if (focusableElements.length > 0) { // If there's an element other than close, focus it. (focusableElements[1] || focusableElements[0]).focus(); } - }, []); - - useEffect(() => { - if (!islandRef.current) { - return; - } const handleKeyDown = (event: KeyboardEvent) => { if (event.key === KEYS.TAB) { - const focusableElements = queryFocusableElements(); + const focusableElements = queryFocusableElements(islandNode); const { activeElement } = document; const currentIndex = focusableElements.findIndex( (element) => element === activeElement, @@ -53,14 +59,13 @@ export const Dialog = (props: { } }; - const node = islandRef.current; - node.addEventListener("keydown", handleKeyDown); + islandNode.addEventListener("keydown", handleKeyDown); - return () => node.removeEventListener("keydown", handleKeyDown); - }, []); + return () => islandNode.removeEventListener("keydown", handleKeyDown); + }, [islandNode]); - const queryFocusableElements = () => { - const focusableElements = islandRef.current?.querySelectorAll( + const queryFocusableElements = (node: HTMLElement) => { + const focusableElements = node.querySelectorAll( "button, a, input, select, textarea, div[tabindex]", ); @@ -74,7 +79,7 @@ export const Dialog = (props: { maxWidth={props.maxWidth} onCloseRequest={props.onCloseRequest} > - +

{props.title}