diff --git a/packages/dify-ui/src/toast/__tests__/index.spec.tsx b/packages/dify-ui/src/toast/__tests__/index.spec.tsx
index a53a9731a3b..36fc4d14f3b 100644
--- a/packages/dify-ui/src/toast/__tests__/index.spec.tsx
+++ b/packages/dify-ui/src/toast/__tests__/index.spec.tsx
@@ -88,6 +88,81 @@ describe('@langgenius/dify-ui/toast', () => {
)
})
+ it('should reject a downward swipe and dismiss upward from the top-right viewport', async () => {
+ const baseUIAnimationGlobal = globalThis as BaseUIAnimationGlobal
+ const animationState = baseUIAnimationGlobal.BASE_UI_ANIMATIONS_DISABLED
+ baseUIAnimationGlobal.BASE_UI_ANIMATIONS_DISABLED = false
+
+ try {
+ const screen = await render(
+ <>
+
+
+
+
+ >,
+ )
+
+ toast('Directional notification')
+
+ const toastDialog = screen.getByRole('dialog', { name: 'Directional notification' })
+ await expect.element(toastDialog).toBeInTheDocument()
+ const toastElement = toastDialog.element()
+ const initialBounds = toastElement.getBoundingClientRect()
+
+ await userEvent.dragAndDrop(toastElement, screen.getByLabelText('Swipe down destination'), {
+ steps: 10,
+ })
+
+ await expect.element(toastDialog).toBeInTheDocument()
+ expect(toastElement).not.toHaveAttribute('data-ending-style')
+ expect(toastElement.getBoundingClientRect().top).toBeCloseTo(initialBounds.top, 0)
+
+ await userEvent.dragAndDrop(toastElement, screen.getByLabelText('Swipe up destination'), {
+ steps: 10,
+ })
+
+ await vi.waitFor(() => {
+ expect(toastElement).toHaveAttribute('data-ending-style')
+ expect(toastElement).toHaveAttribute('data-swipe-direction', 'up')
+ })
+ expect(toastElement.getBoundingClientRect().bottom).toBeLessThan(initialBounds.top)
+ } finally {
+ baseUIAnimationGlobal.BASE_UI_ANIMATIONS_DISABLED = animationState
+ }
+ })
+
it('should dismiss an expanded background toast from its current row when swiped right', async () => {
const baseUIAnimationGlobal = globalThis as BaseUIAnimationGlobal
const animationState = baseUIAnimationGlobal.BASE_UI_ANIMATIONS_DISABLED
diff --git a/packages/dify-ui/src/toast/index.tsx b/packages/dify-ui/src/toast/index.tsx
index 76315e559fd..bcdbdd4ea0f 100644
--- a/packages/dify-ui/src/toast/index.tsx
+++ b/packages/dify-ui/src/toast/index.tsx
@@ -181,6 +181,7 @@ function ToastCard({ toast: toastItem }: { toast: ToastObject }) {
return (
}) {
'transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--toast-peek))+(var(--toast-shrink)*var(--toast-current-height))))_scale(var(--toast-scale))]',
'data-expanded:h-(--toast-height) data-expanded:transform-[translateX(var(--toast-swipe-movement-x))_translateY(var(--toast-expanded-offset-y))_scale(1)]',
'data-ending-style:pointer-events-none data-ending-style:transform-[translateY(-150%)] data-ending-style:opacity-0 data-ending-style:after:pointer-events-none',
- 'data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+150%))]',
+ 'data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(var(--toast-swipe-movement-y)-150%))]',
'data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+150%))_translateY(var(--toast-expanded-offset-y))]',
'data-limited:pointer-events-none data-limited:opacity-0 data-starting-style:transform-[translateY(-150%)] data-starting-style:opacity-0',
"after:pointer-events-auto after:absolute after:bottom-full after:left-0 after:h-[calc(var(--toast-gap)+1px)] after:w-full after:content-['']",