From 448e378fc03de2b556f819e867297230a73bb1c4 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Sun, 26 Jul 2026 15:08:27 +0800 Subject: [PATCH] fix(dify-ui): honor instant popup transitions (#39572) --- packages/dify-ui/src/overlay-shared.ts | 2 +- .../src/popover/__tests__/index.spec.tsx | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/dify-ui/src/overlay-shared.ts b/packages/dify-ui/src/overlay-shared.ts index fbeeef80e43..fcd4abc9236 100644 --- a/packages/dify-ui/src/overlay-shared.ts +++ b/packages/dify-ui/src/overlay-shared.ts @@ -11,7 +11,7 @@ export const floatingSeparatorClassName = 'my-1 h-px bg-divider-subtle' export const menuPopupClassName = 'max-h-(--available-height) overflow-y-auto overflow-x-hidden rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur py-1 text-sm text-text-secondary shadow-lg outline-hidden focus:outline-hidden focus-visible:outline-hidden backdrop-blur-[5px]' export const floatingPopupAnimationClassName = - 'origin-(--transform-origin) transition-[transform,scale,opacity] data-ending-style:scale-95 data-starting-style:scale-95 data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:transition-none' + 'origin-(--transform-origin) transition-[transform,scale,opacity] data-ending-style:scale-95 data-starting-style:scale-95 data-ending-style:opacity-0 data-starting-style:opacity-0 data-instant:transition-none motion-reduce:transition-none' export const modalBackdropClassName = 'absolute inset-0 z-50 bg-background-overlay transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:transition-none' export const modalPopupAnimationClassName = diff --git a/packages/dify-ui/src/popover/__tests__/index.spec.tsx b/packages/dify-ui/src/popover/__tests__/index.spec.tsx index 23351eb667e..19593668878 100644 --- a/packages/dify-ui/src/popover/__tests__/index.spec.tsx +++ b/packages/dify-ui/src/popover/__tests__/index.spec.tsx @@ -1,4 +1,5 @@ import type * as React from 'react' +import { userEvent } from 'vite-plus/test/browser' import { render } from 'vitest-browser-react' import { Popover, PopoverContent, PopoverTrigger } from '..' @@ -6,6 +7,43 @@ const renderWithSafeViewport = (ui: React.ReactNode) => render(
{ui}
) describe('PopoverContent', () => { + describe('Animation', () => { + it('should restore focus without waiting for an instant close transition', async () => { + const animationSettings = globalThis as typeof globalThis & { + BASE_UI_ANIMATIONS_DISABLED: boolean + } + const animationsDisabled = animationSettings.BASE_UI_ANIMATIONS_DISABLED + animationSettings.BASE_UI_ANIMATIONS_DISABLED = false + + try { + const screen = await renderWithSafeViewport( + + Open + + + + , + ) + + const trigger = screen.getByRole('button', { name: 'Open' }) + await trigger.click() + + const focusableContent = screen.getByRole('button', { name: 'Focusable content' }) + focusableContent.element().focus() + await expect.element(focusableContent).toHaveFocus() + + await userEvent.keyboard('{Escape}') + + await expect.element(trigger).toHaveFocus() + } finally { + animationSettings.BASE_UI_ANIMATIONS_DISABLED = animationsDisabled + } + }) + }) + describe('Placement', () => { it('should use bottom placement and default offsets when placement props are not provided', async () => { const screen = await renderWithSafeViewport(