From e249428b3d46553cb975177eb6aa5216f1b96981 Mon Sep 17 00:00:00 2001 From: Eldar <61377022+EldarMuhamethanov@users.noreply.github.com> Date: Sat, 28 Dec 2024 17:37:45 +0300 Subject: [PATCH] feat(ModalCard,ModalPage): add prop restoreFocus (#8120) --- .../components/ModalCard/ModalCard.test.tsx | 56 +++++++++++++++++++ .../ModalCard/ModalCardInternal.tsx | 7 ++- .../vkui/src/components/ModalCard/types.ts | 4 +- .../components/ModalPage/ModalPage.test.tsx | 56 +++++++++++++++++++ .../ModalPage/ModalPageInternal.tsx | 2 + .../vkui/src/components/ModalPage/types.ts | 2 + 6 files changed, 125 insertions(+), 2 deletions(-) diff --git a/packages/vkui/src/components/ModalCard/ModalCard.test.tsx b/packages/vkui/src/components/ModalCard/ModalCard.test.tsx index 9790780919..82a3db5419 100644 --- a/packages/vkui/src/components/ModalCard/ModalCard.test.tsx +++ b/packages/vkui/src/components/ModalCard/ModalCard.test.tsx @@ -1,7 +1,11 @@ +import { act } from 'react'; +import * as React from 'react'; import { fireEvent, render, screen } from '@testing-library/react'; import { baselineComponent, waitCSSTransitionEnd } from '../../testing/utils'; +import { Button } from '../Button/Button'; import { ConfigProvider } from '../ConfigProvider/ConfigProvider'; import { ModalCard } from './ModalCard'; +import { type ModalCardProps } from './types'; export const waitModalCardCSSTransitionEnd = async (el: HTMLElement) => await waitCSSTransitionEnd(el); @@ -126,4 +130,56 @@ describe(ModalCard, () => { expect(onClose).toHaveBeenCalledTimes(1); expect(onClose).toHaveBeenCalledWith('click-close-button'); }); + + describe('check restoreFocus prop', () => { + const Fixture: React.FC> = ({ restoreFocus = true }) => { + const [open, setOpen] = React.useState(false); + return ( + <> + + + + + + ); + }; + + it.each([true, false])('check restoreFocus=%s', async (restoreFocus) => { + jest.useFakeTimers(); + const h = render(); + expect(h.queryByTestId('host')).toBeFalsy(); + + const openButton = h.getByTestId('open-modal'); + await act(async () => { + openButton.focus(); + }); + fireEvent.click(openButton); + expect(openButton).toHaveFocus(); + + await waitModalCardCSSTransitionEnd(h.getByTestId('host')); + expect(h.queryByTestId('host')).toBeTruthy(); + jest.runAllTimers(); + expect(h.getByTestId('dismiss-button')).toHaveFocus(); + + fireEvent.click(openButton); + await waitModalCardCSSTransitionEnd(h.getByTestId('host')); + expect(h.queryByTestId('host')).toBeFalsy(); + jest.runAllTimers(); + + if (restoreFocus) { + expect(openButton).toHaveFocus(); + } else { + expect(openButton).not.toHaveFocus(); + } + }); + }); }); diff --git a/packages/vkui/src/components/ModalCard/ModalCardInternal.tsx b/packages/vkui/src/components/ModalCard/ModalCardInternal.tsx index 835966a2a2..34e2e2cf98 100644 --- a/packages/vkui/src/components/ModalCard/ModalCardInternal.tsx +++ b/packages/vkui/src/components/ModalCard/ModalCardInternal.tsx @@ -66,6 +66,7 @@ export const ModalCardInternal = ({ dismissButtonMode, dismissLabel, noFocusToDialog, + restoreFocus, onOpen, onOpened, onClose = noop, @@ -136,7 +137,11 @@ export const ModalCardInternal = ({ ); useScrollLock(!hidden); - useFocusTrap(ref, { autoFocus: !noFocusToDialog, disabled: !opened || hidden }); + useFocusTrap(ref, { + autoFocus: !noFocusToDialog, + disabled: !opened || hidden, + restoreFocus, + }); return (