diff --git a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx index 5e2b48217f..c7e0809c97 100644 --- a/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx +++ b/packages/ibm-products/src/components/APIKeyModal/APIKeyModal.tsx @@ -36,7 +36,7 @@ import { isRequiredIf } from '../../global/js/utils/props-helper'; import uuidv4 from '../../global/js/utils/uuidv4'; import { APIKeyModalProps } from './APIKeyModal.types'; import { useFocus, usePreviousValue } from '../../global/js/hooks'; -import { getSpecificElement } from '../../global/js/hooks/useFocus'; +import { claimFocus } from '../../global/js/hooks/useFocus'; const componentName = 'APIKeyModal'; @@ -137,27 +137,7 @@ export let APIKeyModal: React.FC = forwardRef( useEffect(() => { if (open) { // Focusing the first element or selectorPrimaryFocus element - if ( - selectorPrimaryFocus && - getSpecificElement(modalRef?.current, selectorPrimaryFocus) - ) { - const specifiedEl = getSpecificElement( - modalRef?.current, - selectorPrimaryFocus - ); - - if ( - specifiedEl && - window?.getComputedStyle(specifiedEl)?.display !== 'none' - ) { - setTimeout(() => specifiedEl.focus(), 0); - return; - } - } - - setTimeout(() => { - firstElement?.focus(); - }, 0); + claimFocus(firstElement, modalRef, selectorPrimaryFocus); } }, [firstElement, modalRef, open, selectorPrimaryFocus]); diff --git a/packages/ibm-products/src/components/AboutModal/AboutModal.tsx b/packages/ibm-products/src/components/AboutModal/AboutModal.tsx index ced6f6b517..afaea2a06b 100644 --- a/packages/ibm-products/src/components/AboutModal/AboutModal.tsx +++ b/packages/ibm-products/src/components/AboutModal/AboutModal.tsx @@ -21,7 +21,7 @@ import React, { MutableRefObject, ReactNode, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { getDevtoolsProps } from '../../global/js/utils/devtools'; -import { useFocus } from '../../global/js/hooks/useFocus'; +import { claimFocus, useFocus } from '../../global/js/hooks/useFocus'; import { pkg } from '../../settings'; import { usePortalTarget } from '../../global/js/hooks/usePortalTarget'; import uuidv4 from '../../global/js/utils/uuidv4'; @@ -153,10 +153,9 @@ export let AboutModal = React.forwardRef( useEffect(() => { if (open) { - setTimeout(() => firstElement?.focus(), 0); + claimFocus(firstElement, modalRef); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [open]); + }, [firstElement, modalRef, open]); return renderPortalUse( diff --git a/packages/ibm-products/src/components/Tearsheet/TearsheetShell.tsx b/packages/ibm-products/src/components/Tearsheet/TearsheetShell.tsx index bebe1617c8..74dd3e7376 100644 --- a/packages/ibm-products/src/components/Tearsheet/TearsheetShell.tsx +++ b/packages/ibm-products/src/components/Tearsheet/TearsheetShell.tsx @@ -39,7 +39,7 @@ import { import { ActionSet } from '../ActionSet'; import { Wrap } from '../../global/js/utils/Wrap'; import { usePortalTarget } from '../../global/js/hooks/usePortalTarget'; -import { getSpecificElement, useFocus } from '../../global/js/hooks/useFocus'; +import { claimFocus, useFocus } from '../../global/js/hooks/useFocus'; import { usePreviousValue } from '../../global/js/hooks'; import { TearsheetAction } from './Tearsheet'; @@ -323,48 +323,13 @@ export const TearsheetShell = React.forwardRef( // Callback to give the tearsheet the opportunity to claim focus handleStackChange.claimFocus = function () { - if ( - selectorPrimaryFocus && - getSpecificElement(modalRef?.current, selectorPrimaryFocus) - ) { - const specifiedEl = getSpecificElement( - modalRef?.current, - selectorPrimaryFocus - ); - - if ( - specifiedEl && - window?.getComputedStyle(specifiedEl)?.display !== 'none' - ) { - return specifiedEl.focus(); - } - } - - setTimeout(() => firstElement?.focus(), 0); + claimFocus(firstElement, modalRef, selectorPrimaryFocus); }; useEffect(() => { if (open) { // Focusing the first element or selectorPrimaryFocus element - if ( - selectorPrimaryFocus && - getSpecificElement(modalRef?.current, selectorPrimaryFocus) - ) { - const specifiedEl = getSpecificElement( - modalRef?.current, - selectorPrimaryFocus - ); - - if ( - specifiedEl && - window?.getComputedStyle(specifiedEl)?.display !== 'none' - ) { - setTimeout(() => specifiedEl.focus(), 0); - return; - } - } - - setTimeout(() => firstElement?.focus(), 0); + claimFocus(firstElement, modalRef, selectorPrimaryFocus); } }, [firstElement, modalRef, open, selectorPrimaryFocus]); diff --git a/packages/ibm-products/src/global/js/hooks/useFocus.js b/packages/ibm-products/src/global/js/hooks/useFocus.js index f82bb9b613..e6a7dd052a 100644 --- a/packages/ibm-products/src/global/js/hooks/useFocus.js +++ b/packages/ibm-products/src/global/js/hooks/useFocus.js @@ -97,3 +97,34 @@ export const useFocus = (modalRef, selectorPrimaryFocus) => { getFocusable: getFocusable, }; }; + +/** + * + * @param {*} firstElement + * @param {*} modalRef + * @param {string | undefined} selectorPrimaryFocus + */ +export const claimFocus = ( + firstElement, + modalRef, + selectorPrimaryFocus = undefined +) => { + if ( + selectorPrimaryFocus && + getSpecificElement(modalRef?.current, selectorPrimaryFocus) + ) { + const specifiedEl = getSpecificElement( + modalRef?.current, + selectorPrimaryFocus + ); + + if ( + specifiedEl && + window?.getComputedStyle(specifiedEl)?.display !== 'none' + ) { + return specifiedEl.focus(); + } + } + + setTimeout(() => firstElement?.focus(), 0); +};