Ловушка Фокуса React и переиспользование компонентов в 2 модальных окнах

У меня есть 2 модальных окна(я переиспользую в обоих CloseButton(компонент) and Modal(компонент) в обоих) мне нужно сделать ловушки фокуса в обоих. Ищу варианты наилучшего подхода + другие варианты + не могу понять в чем сам ошибаюсь = хочу разобраться.

1 popup [наглядно показал его структуру], компоненты: ModalLogin-Modal-CloseButton. Читал по поводу 2 хуков: useRef() and forwardRef(props, ref) пробую их юзнуть и ошибки. Я ищу ответ как их правильно применить (если это возможно) или как поступить лучше будет + почему :)

В ModalLogin я пробую сделать ловушку фокуса. Для этого я размечаю что должно происходить с фокусом при переходе на 1 и последний элемент. Мне нужно передать мой ref-хук получается через Modal-CloseButton. Читал что нельзя передавать просто в функциональные компоненты рефы. Пробую юзать форвардреф-хук в необходимых компонентах куда передаю, вот что делаю:

Все линки дают полное представление о всем происходящем в компоненте до ловушки фокуса (стараюсь не засорять сильно пост).

https://github.com/j3n4r3v/ligabank-credit/blob/master/src/components/form-login/modal-login.jsx [Modal-login full]

    const ModalLogin = () => {
    const topTabTrap* = useRef();
    const bottomTabTrap* = useRef();
    const firstFocusableElement = useRef();
    const lastFocusableElement = useRef();

useEffect(() => {
     const trapFocus = (event) => {
        if (event.target === topTabTrap.current) {
            lastFocusableElement.current.focus()
        }
        if (event.target === bottomTabTrap.current) {
            firstFocusableElement.current.focus()
        }
    }
    document.addEventListener('focusin', trapFocus)
    return () => document.removeEventListener('focusin', trapFocus)
  }, [firstFocusableElement, lastFocusableElement])

  return ( 
        <Modal onCloseModal={() => onCloseForm()} ref={lastFocusableElement}>

        <form >
            <span ref={topTabTrap} tabIndex="0" />
                <Logo />
                <Input id="email" ref={firstFocusableElement} />
                <Input id="password" />
                <Button type="submit" />
            <span ref={bottomTabTrap} tabIndex="0"/>
        </form>

    </Modal>

https://github.com/j3n4r3v/ligabank-credit/blob/master/src/components/modal/modal.jsx [Modal full]

const Modal = forwardRef(({ props, ref }) => {
  const { children, onCloseModal, ...props } = props;
  const overlayRef = useRef();
  useEffect(() => {
    const preventWheelScroll = (evt) => evt.preventDefault();
        document.addEventListener('keydown', onEscClick);
        window.addEventListener('wheel', preventWheelScroll, { passive: false });
    return () => {
        document.removeEventListener('keydown', onEscClick);
        window.removeEventListener('wheel', preventWheelScroll);
    };
});
const onCloseModalButtonClick = () => {
    onCloseModal();
};

return (
    <div className="overlay" ref={overlayRef}
        onClick={(evt) => onOverlayClick(evt)}>
        <div className="modal">
            <CloseButton
                ref={ref}
                onClick={() => onCloseModalButtonClick()}
                {...props}
            />
                {children}
        </div>
    </div>
);
});

https://github.com/j3n4r3v/ligabank-credit/blob/master/src/components/close-button/close-button.jsx [CloseButton full]

const CloseButton = forwardRef(({ props, ref }) => {
    const {className, onClick, ...props} = props;
 return (
    <button className={`${className} close-button`}
        onClick={(evt) => onClick(evt)}
        tabIndex="0"
        ref={ref}
            {...props}
        >Close</button>
);
});

При таком подходе у меня много ошибок: 1 - Cannot read properties of undefined (reading 'children') - Modal, 2 - ... className undefined in CloseButton etc. Ощущение что нельзя деструктурировать(непонятно почему). До форвард-реф хук и деструктуризации - все работало!

2 popup [наглядно показал его структуру], компоненты: Modal(переиспользую его в 1 popup) - InfoSuccess- CloseButton(переиспользую его в 1 popup) Во 2 у меня лишь 1 интерактивный элемент - button (tabindex) и все. Сейчас нет ни 1 идеи что делать с ним + ловушкой фокуса (focus-trap). :(

https://github.com/j3n4r3v/ligabank-credit/blob/master/src/components/success-modal/success-modal.jsx [SuccessModal full]

    const SuccessModal = ({ className, onChangeVisibleSuccess }) => {
return (
    <Modal onCloseModal={() => onChangeVisibleSuccess(false)}>
        <InfoSuccess className={className} />
     </Modal>
);

};

https://github.com/j3n4r3v/ligabank-credit/blob/master/src/components/info-block/info-block.jsx [Infoblock full]

    const InfoBlock = ({ className, title, desc, type }) => {
return (
    <section className={`info-block ${className} info-block--${type}`}>
        <h3 className="info-block__title">{title}</h3>
        <p className="info-block__desc">{desc}</p>
    </section>
);

};

 const InfoSuccess = ({ className }) => (
   <InfoBlock
     title="Спасибо за обращение в наш банк."
     desc="Наш менеджер скоро свяжется с вами по указанному номеру телефона."
     type="center"
     className={className}
/>

);

Я знаю о подходе в моем случае: 3 компонента просто делаешь 1 = 1 компонент и никаких проблем с ловушкой фокуса (focus-trap). Но мне нужно переиспользовать компоненты чтобы не повторяться. Интересно понять что будет лучше в моем случае и почему (какие варианты), какая практика лучше - best practice. Прошу Вашей помощи, люди добрые ))


Ответы (0 шт):