diff --git a/.changeset/warm-pans-kiss.md b/.changeset/warm-pans-kiss.md new file mode 100644 index 0000000000..cc14d3155f --- /dev/null +++ b/.changeset/warm-pans-kiss.md @@ -0,0 +1,5 @@ +--- +"@ultraviolet/ui": patch +--- + +`Modal`, `Dialog`, `Drawer`: improve opening/closing animations diff --git a/e2e/tests/componentsWithinModal/test.spec.ts b/e2e/tests/componentsWithinModal/test.spec.ts index 95bf672f57..3d660b64ee 100644 --- a/e2e/tests/componentsWithinModal/test.spec.ts +++ b/e2e/tests/componentsWithinModal/test.spec.ts @@ -29,7 +29,9 @@ test('open modal, select an option, open nested modal through select input, clos await page.getByTestId('select-input-color').click() await page.getByRole('button', { name: 'Open Nested Modal' }).click() - await page.locator('dialog').filter({ hasText: 'This is the nested modal' }).getByLabel('close').click() + const nestedModal = page.locator('dialog').filter({ hasText: 'This is the nested modal' }) + await nestedModal.getByLabel('close').click() + await expect(nestedModal).not.toBeAttached() await page.getByLabel('close').click() await expect(page.locator('dialog')).not.toBeVisible() diff --git a/packages/ui/src/components/Dialog/__tests__/index.test.tsx b/packages/ui/src/components/Dialog/__tests__/index.test.tsx index bdfa627b69..98e6e7b2d6 100644 --- a/packages/ui/src/components/Dialog/__tests__/index.test.tsx +++ b/packages/ui/src/components/Dialog/__tests__/index.test.tsx @@ -1,4 +1,4 @@ -import { screen } from '@testing-library/react' +import { screen, waitFor } from '@testing-library/react' import { userEvent } from '@testing-library/user-event' import { renderWithTheme } from '@utils/test' import { describe, expect, it, vi } from 'vitest' @@ -45,7 +45,9 @@ describe('dialog', () => { const cancelButton = screen.getByRole('button', { name: 'Cancel' }) await userEvent.click(cancelButton) - expect(screen.queryByRole('heading', { name: 'Title Test' })).not.toBeInTheDocument() + await waitFor(() => { + expect(screen.queryByRole('heading', { name: 'Title Test' })).not.toBeInTheDocument() + }) }) it('[CancelButton] : should handle click', async () => { diff --git a/packages/ui/src/components/Dialog/components/Button.tsx b/packages/ui/src/components/Dialog/components/Button.tsx index b2620f5051..b697fe87a4 100644 --- a/packages/ui/src/components/Dialog/components/Button.tsx +++ b/packages/ui/src/components/Dialog/components/Button.tsx @@ -1,6 +1,6 @@ 'use client' -import type { ComponentProps, ReactNode } from 'react' +import type { ComponentProps, MouseEvent, ReactNode } from 'react' import { Button } from '../../Button' import { useDialogContext } from '../Context' @@ -11,8 +11,16 @@ type DialogButtonProps = { export const DialogButton = ({ children, onClick, disabled, tooltip, style }: DialogButtonProps) => { const context = useDialogContext() + function onButtonClick(e: MouseEvent) { + const dialog = (e.target as HTMLElement).closest('dialog') + if (dialog) { + dialog.dataset['closeAction'] = 'confirm' + } + onClick?.(e) + } + return ( - ) diff --git a/packages/ui/src/components/Drawer/__tests__/__snapshots__/index.test.tsx.snap b/packages/ui/src/components/Drawer/__tests__/__snapshots__/index.test.tsx.snap index 2006555b4a..bb3b021783 100644 --- a/packages/ui/src/components/Drawer/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/ui/src/components/Drawer/__tests__/__snapshots__/index.test.tsx.snap @@ -175,26 +175,25 @@ exports[`drawer > renders with disclosure and onClose 1`] = `

header

@@ -204,10 +203,10 @@ exports[`drawer > renders with disclosure and onClose 1`] = ` style="--bu43fb0: 1px;" />
drawer @@ -216,7 +215,7 @@ exports[`drawer > renders with disclosure and onClose 1`] = `
- ) : null + ) +} + +function useDelayUnmount(open?: boolean, delayTime?: number) { + const [shouldRender, setShouldRender] = useState(open) + + useEffect(() => { + let timeoutId: ReturnType + if (open && !shouldRender) { + setShouldRender(true) + } else if (!open && shouldRender) { + timeoutId = setTimeout(() => setShouldRender(false), delayTime) + } + return () => clearTimeout(timeoutId) + }, [open, delayTime, shouldRender]) + + return shouldRender +} diff --git a/packages/ui/src/components/Modal/__stories__/Placement.stories.tsx b/packages/ui/src/components/Modal/__stories__/Placement.stories.tsx index bc8849d78b..d5d5e8e25e 100644 --- a/packages/ui/src/components/Modal/__stories__/Placement.stories.tsx +++ b/packages/ui/src/components/Modal/__stories__/Placement.stories.tsx @@ -1,7 +1,7 @@ import type { StoryFn } from '@storybook/react-vite' import { Modal } from '..' import { Button } from '../../Button' -import { MODAL_PLACEMENT } from '../constants' +import { MODAL_PLACEMENT } from '../constants.css' export const Placement: StoryFn = props => ( <> diff --git a/packages/ui/src/components/Modal/__stories__/Size.stories.tsx b/packages/ui/src/components/Modal/__stories__/Size.stories.tsx index 6314f40537..d45888a45a 100644 --- a/packages/ui/src/components/Modal/__stories__/Size.stories.tsx +++ b/packages/ui/src/components/Modal/__stories__/Size.stories.tsx @@ -1,7 +1,7 @@ import type { StoryFn } from '@storybook/react-vite' import { Modal } from '..' import { Button } from '../../Button' -import { MODAL_WIDTH } from '../constants' +import { MODAL_WIDTH } from '../constants.css' export const Size: StoryFn = props => ( <> diff --git a/packages/ui/src/components/Modal/__tests__/__snapshots__/index.test.tsx.snap b/packages/ui/src/components/Modal/__tests__/__snapshots__/index.test.tsx.snap index b99e2ce871..acf9d52c74 100644 --- a/packages/ui/src/components/Modal/__tests__/__snapshots__/index.test.tsx.snap +++ b/packages/ui/src/components/Modal/__tests__/__snapshots__/index.test.tsx.snap @@ -95,26 +95,25 @@ exports[`modal > renders with disclosure and onClose 1`] = `
modal