From 31467f2173806c64cd39f7d0fb86b0dc3f5f3c43 Mon Sep 17 00:00:00 2001
From: Abdul Rahman <81605929+abdulrahmancodes@users.noreply.github.com>
Date: Mon, 15 Dec 2025 23:06:24 +0530
Subject: [PATCH] Fix action menu modals rendering inside dropdown containers
(#16478)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #16363
- Updated modals to open in the full screen by default
---
.../modal/components/ConfirmationModal.tsx | 1 +
.../ui/layout/modal/components/Modal.tsx | 8 +++-
.../__stories__/ConfirmationModal.stories.tsx | 37 ++++++++++---------
3 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx
index 5f0a31a750..badaa50186 100644
--- a/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx
@@ -117,6 +117,7 @@ export const ConfirmationModal = ({
padding="large"
modalVariant={modalVariant}
dataGloballyPreventClickOutside
+ ignoreContainer
>
diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx
index 5857f1ff99..8877d4ab0e 100644
--- a/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx
@@ -230,8 +230,12 @@ export const Modal = ({
const isMobile = useIsMobile();
const modalRef = useRef(null);
const { container } = useModalContainer();
- const effectiveContainer = ignoreContainer ? null : container;
- const isInContainer = isDefined(effectiveContainer);
+ const effectiveContainer = ignoreContainer
+ ? isDefined(document)
+ ? document.body
+ : null
+ : container;
+ const isInContainer = isDefined(container) && !ignoreContainer;
const theme = useTheme();
diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/ConfirmationModal.stories.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/ConfirmationModal.stories.tsx
index 2a56c76390..5d58fc6e31 100644
--- a/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/ConfirmationModal.stories.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/modal/components/__stories__/ConfirmationModal.stories.tsx
@@ -56,6 +56,7 @@ export const Default: Story = {
title: 'Pariatur labore.',
subtitle: 'Velit dolore aliquip laborum occaecat fugiat.',
confirmButtonText: 'Delete',
+ onConfirmClick: fn(),
},
};
@@ -75,10 +76,10 @@ export const CloseOnEscape: Story = {
confirmButtonText: 'Confirm',
onClose: closeMock,
},
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
+ play: async () => {
+ const body = within(document.body);
- await canvas.findByText('Escape Key Test');
+ await body.findByText('Escape Key Test');
closeMock.mockClear();
@@ -98,12 +99,12 @@ export const CloseOnClickOutside: Story = {
confirmButtonText: 'Confirm',
onClose: closeMock,
},
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
+ play: async () => {
+ const body = within(document.body);
- await canvas.findByText('Click Outside Test');
+ await body.findByText('Click Outside Test');
- const backdrop = await canvas.findByTestId('modal-backdrop');
+ const backdrop = await body.findByTestId('modal-backdrop');
// We need to wait for the outside click listener to be registered
await sleep(100);
@@ -124,10 +125,10 @@ export const ConfirmWithEnterKey: Story = {
confirmButtonText: 'Confirm',
onConfirmClick: confirmMock,
},
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
+ play: async () => {
+ const body = within(document.body);
- await canvas.findByText('Enter Key Test');
+ await body.findByText('Enter Key Test');
await userEvent.keyboard('{Enter}');
@@ -145,12 +146,12 @@ export const CancelButtonClick: Story = {
confirmButtonText: 'Confirm',
onClose: closeMock,
},
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
+ play: async () => {
+ const body = within(document.body);
- await canvas.findByText('Cancel Button Test');
+ await body.findByText('Cancel Button Test');
- const cancelButton = await canvas.findByRole('button', {
+ const cancelButton = await body.findByRole('button', {
name: /Cancel/,
});
await userEvent.click(cancelButton);
@@ -169,12 +170,12 @@ export const ConfirmButtonClick: Story = {
confirmButtonText: 'Confirm',
onConfirmClick: confirmMock,
},
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
+ play: async () => {
+ const body = within(document.body);
- await canvas.findByText('Confirm Button Test');
+ await body.findByText('Confirm Button Test');
- const confirmButton = await canvas.findByRole('button', {
+ const confirmButton = await body.findByRole('button', {
name: /Confirm/,
});