From 7ac96d46ee76c4f8c69f7b5393c02d6e6f8e36a7 Mon Sep 17 00:00:00 2001 From: Matthias Date: Thu, 13 Feb 2025 14:32:39 +0100 Subject: [PATCH] ci(Modal): add one more test for modal with select input --- .changeset/brave-guests-thank.md | 5 ++++ e2e/tests/componentsWithinModal/test.spec.ts | 18 +++++++++++++ .../components/Modal/components/Dialog.tsx | 27 +++++++++---------- 3 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 .changeset/brave-guests-thank.md diff --git a/.changeset/brave-guests-thank.md b/.changeset/brave-guests-thank.md new file mode 100644 index 0000000000..92b44ddda5 --- /dev/null +++ b/.changeset/brave-guests-thank.md @@ -0,0 +1,5 @@ +--- +"@ultraviolet/ui": patch +--- + +Fix `` within `` to correctly close when you click outside diff --git a/e2e/tests/componentsWithinModal/test.spec.ts b/e2e/tests/componentsWithinModal/test.spec.ts index 30e43aadfb..1ec1ca5e18 100644 --- a/e2e/tests/componentsWithinModal/test.spec.ts +++ b/e2e/tests/componentsWithinModal/test.spec.ts @@ -3,6 +3,8 @@ import { expect, test } from '@playwright/test' test('open modal, fill text inputs, close modal', async ({ page, baseURL }) => { await page.goto(`${baseURL}/componentsWithinModal`) await page.getByRole('button', { name: 'Open Modal' }).click() + await expect(page.locator('dialog')).toBeVisible() + await page.getByLabel('First name').click() await page.getByLabel('First name').fill('Test First Name') @@ -27,6 +29,7 @@ test('open modal, select an option, open nested modal through select input, clos }) => { await page.goto(`${baseURL}/componentsWithinModal`) await page.getByRole('button', { name: 'Open Modal' }).click() + await expect(page.locator('dialog')).toBeVisible() await page.getByTestId('select-input-color').click() await page.getByTestId('option-stack-red').locator('div').click() @@ -42,3 +45,18 @@ test('open modal, select an option, open nested modal through select input, clos await page.getByLabel('close').click() await expect(page.locator('dialog')).not.toBeVisible() }) + +test('open modal, click on select input, check that it opens, click outside, check that select input closes and modal is still open', async ({ + page, + baseURL, +}) => { + await page.goto(`${baseURL}/componentsWithinModal`) + await page.getByRole('button', { name: 'Open Modal' }).click() + await expect(page.locator('dialog')).toBeVisible() + + await page.getByTestId('select-input-color').click() + await page.getByTestId('option-stack-red').locator('div').isVisible() + await page.getByLabel('First name').click() + await page.getByTestId('option-stack-red').locator('div').isHidden() + await expect(page.locator('dialog')).toBeVisible() +}) diff --git a/packages/ui/src/components/Modal/components/Dialog.tsx b/packages/ui/src/components/Modal/components/Dialog.tsx index 4933b8e8fb..650903826e 100644 --- a/packages/ui/src/components/Modal/components/Dialog.tsx +++ b/packages/ui/src/components/Modal/components/Dialog.tsx @@ -182,6 +182,16 @@ export const Dialog = ({ event.stopPropagation() }, []) + // We need to reverse the array as the last opened modal should be the first to be with normal size + // while the first opened modal should shrink + const realPosition = [...openedModals].findIndex(object => object.id === id) + const position = [...openedModals] + .reverse() + .findIndex(object => object.id === id) // reverse method mutate array so we need to create a new array + const modalAbove = openedModals[realPosition + 1] + const currentModalHeight = dialogRef.current?.offsetHeight + let top = 0 + // handle key up : used when having inputs in modals - useful for hideOnEsc const handleKeyUp: KeyboardEventHandler = useCallback( event => { @@ -196,18 +206,17 @@ export const Dialog = ({ const handleClose: MouseEventHandler = useCallback( event => { - event.stopPropagation() - // if the user actually click outside of modal if ( hideOnClickOutside && dialogRef.current && - !dialogRef.current.contains(event.target as Node) + !dialogRef.current.contains(event.target as Node) && + position === 0 ) { onCloseRef.current() } }, - [hideOnClickOutside], + [hideOnClickOutside, position], ) // Enable focus trap inside the modal @@ -254,16 +263,6 @@ export const Dialog = ({ } }, []) - // We need to reverse the array as the last opened modal should be the first to be with normal size - // while the first opened modal should shrink - const realPosition = [...openedModals].findIndex(object => object.id === id) - const position = [...openedModals] - .reverse() - .findIndex(object => object.id === id) // reverse method mutate array so we need to create a new array - const modalAbove = openedModals[realPosition + 1] - const currentModalHeight = dialogRef.current?.offsetHeight - let top = 0 - if ( modalAbove?.ref && typeof modalAbove.ref === 'object' &&