Repository: Sage/carbon (ts)

Issue:
Return focus on the button which opened Confirm modal
### Description

I using this Confirm modal component https://carbon.sage.com/?path=/docs/confirm--docs.
When I open the modal and clicked the cancel or confirm buttons returns focus to the document body, not on the button which opening this modal.
So, when I closing the Confirm modal, I expecting that focus will be on the button which openning this modal. 
[This contradicts the guidelines recommended for Modals](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)

### Reproduction

https://stackblitz.com/edit/confirm-focus-on-close?file=src%2FApp.tsx

### Steps to reproduce

Better to use Tab and Space for reproducing.

1) Click to "Open Confirm" button.
2) In the Confirm modal click Cancel button.
3) Use Tab on the keyboard to focus on the "Open Confirm" button.

### JIRA ticket numbers (Sage only)

SBS-103263

### Suggested solution

_No response_

### Carbon version

138.1.0

### Design tokens version

4.34.0

### Relevant browsers

Chrome

### Relevant OSs

Windows

### Additional context

_No response_

### Confidentiality

- [X] I confirm there is no confidential or commercially sensitive information included.

Pull request:
fix(menu-full-screen, modal): ensure the call to action element is focused on close
fix #6870

### Proposed behaviour

<!--
A clear and concise description of what changes this PR makes. If applicable, include any UI screenshots to help explain your request. If you are a Sage contributor, please DO NOT share any commercially sensitive information, such as UI screenshots or code from Sage products.
-->

Ensures focus is moved back onto the active element before a modal/fullscreen menu is opened. 

### Current behaviour

<!--
A clear and concise description of the behaviour before this change. If applicable, include any UI screenshots to help explain your request. If you are a Sage contributor, please DO NOT share any commercially sensitive information, such as UI screenshots or code from Sage products.
-->

Currently, once a modal is closed, focus is typically returned to the document, which can be disorientating for users. 

### Checklist

<!-- Each PR should include the following -->

- [x] Commits follow our style guide
- [ ] Related issues linked in commit messages if required
- [ ] Screenshots are included in the PR if useful
- [ ] All themes are supported if required
- [x] Unit tests added or updated if required
- [x] Playwright automation tests added or updated if required
- [ ] Storybook added or updated if required
- [ ] Translations added or updated (including creating or amending translation keys table in storybook) if required
- [ ] Typescript `d.ts` file added or updated if required
- [ ] Related docs have been updated if required

#### QA

- [ ] Tested in provided StackBlitz sandbox/Storybook
- [ ] Add new Playwright test coverage if required
- [ ] Carbon implementation matches Design System/designs
- [ ] UI Tests GitHub check reviewed if required

### Additional context

<!-- Add any other context or links about the pull request here. -->

### Testing instructions

<!--
How can a reviewer test this PR?

If this PR addresses a pre-existing bug, please include a link to a sandbox that reproduces the original bug. A starter template has been provided to help you do this:
<https://stackblitz.com/fork/github/Parsium/carbon-starter>
-->


Patch:
diff --git a/src/components/dialog-full-screen/dialog-full-screen.mdx b/src/components/dialog-full-screen/dialog-full-screen.mdx
index 502c03472..92012b881 100644
--- a/src/components/dialog-full-screen/dialog-full-screen.mdx
+++ b/src/components/dialog-full-screen/dialog-full-screen.mdx
@@ -32,6 +32,10 @@ import DialogFullScreen from "carbon-react/lib/components/dialog-full-screen";
 
 ### Default
 
+The call-to-action element should always be focused when the `DialogFullScreen` is closed. However, in some instances it may not receive focus
+due to specific browser design choices. The below example shows how to programmatically focus the call-to-action element when the `DialogFullScreen` is closed
+to ensure behaviour is consistent across all browsers.
+
 <Canvas of={DialogFullScreenStories.Default} />
 
 ### With complex example
diff --git a/src/components/dialog-full-screen/dialog-full-screen.pw.tsx b/src/components/dialog-full-screen/dialog-full-screen.pw.tsx
index 8a9afff89..2080fcebc 100644
--- a/src/components/dialog-full-screen/dialog-full-screen.pw.tsx
+++ b/src/components/dialog-full-screen/dialog-full-screen.pw.tsx
@@ -303,6 +303,82 @@ test.describe("render DialogFullScreen component and check properties", () => {
     );
   });
 
+  test("when Dialog Full Screen is opened and then closed, the call to action element should be focused", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<DialogFullScreenComponent open={false} />);
+
+    const button = page
+      .getByRole("button")
+      .filter({ hasText: "Open Dialog Full Screen" });
+    const dialogFullScreen = page.getByRole("dialog");
+    await expect(button).not.toBeFocused();
+    await expect(dialogFullScreen).not.toBeVisible();
+
+    await button.click();
+    await expect(dialogFullScreen).toBeVisible();
+    const closeButton = page.getByLabel("Close");
+    await closeButton.click();
+    await expect(button).toBeFocused();
+    await expect(dialogFullScreen).not.toBeVisible();
+  });
+
+  test("when Dialog Full Screen is open on render, then closed, opened and then closed again, the call to action element should be focused", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<DialogFullScreenComponent />);
+
+    const dialogFullScreen = page.getByRole("dialog");
+    await expect(dialogFullScreen).toBeVisible();
+    const closeButton = page.getByLabel("Close");
+    await closeButton.click();
+
+    const button = page
+      .getByRole("button")
+      .filter({ hasText: "Open Dialog Full Screen" });
+    await expect(button).not.toBeFocused();
+    await expect(dialogFullScreen).not.toBeVisible();
+
+    await button.click();
+    await expect(dialogFullScreen).toBeVisible();
+    await closeButton.click();
+    await expect(button).toBeFocused();
+  });
+
+  test("when nested Dialog's are opened/closed their respective call to action elements should be focused correctly", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<NestedDialog />);
+
+    const firstButton = page
+      .getByRole("button")
+      .filter({ hasText: "Open Main Dialog" });
+    const firstDialog = page.getByRole("dialog").first();
+    await expect(firstButton).not.toBeFocused();
+    await expect(firstDialog).not.toBeVisible();
+
+    await firstButton.click();
+    await expect(firstDialog).toBeVisible();
+    const secondButton = page
+      .getByRole("button")
+      .filter({ hasText: "Open Nested Dialog" });
+    await expect(secondButton).not.toBeFocused();
+    await secondButton.click();
+    const secondDialog = page.getByRole("dialog").last();
+    await expect(secondDialog).toBeVisible();
+
+    const secondCloseButton = page.getByLabel("Close").last();
+    await secondCloseButton.click();
+    await expect(secondButton).toBeFocused();
+
+    const firstCloseButton = page.getByLabel("Close").first();
+    await firstCloseButton.click();
+    await expect(firstButton).toBeFocused();
+  });
+
   test("should render component with autofocus disabled", async ({
     mount,
     page,
diff --git a/src/components/dialog-full-screen/dialog-full-screen.stories.tsx b/src/components/dialog-full-screen/dialog-full-screen.stories.tsx
index add20392e..decf45e6c 100644
--- a/src/components/dialog-full-screen/dialog-full-screen.stories.tsx
+++ b/src/components/dialog-full-screen/dialog-full-screen.stories.tsx
@@ -55,12 +55,19 @@ type Story = StoryObj<typeof DialogFullScreen>;
 
 export const Default: Story = () => {
   const [isOpen, setIsOpen] = useState(false);
+  const buttonRef = useRef<HTMLButtonElement>(null);
+
   return (
     <>
-      <Button onClick={() => setIsOpen(true)}>Open DialogFullScreen</Button>
+      <Button ref={buttonRef} onClick={() => setIsOpen(true)}>
+        Open DialogFullScreen
+      </Button>
       <DialogFullScreen
         open={isOpen}
-        onCancel={() => setIsOpen(false)}
+        onCancel={() => {
+          setIsOpen(false);
+          setTimeout(() => buttonRef.current?.focus(), 0);
+        }}
         title="Title"
         subtitle="Subtitle"
       >
diff --git a/src/components/dialog/dialog.mdx b/src/components/dialog/dialog.mdx
index 2419b3846..a101395ad 100644
--- a/src/components/dialog/dialog.mdx
+++ b/src/components/dialog/dialog.mdx
@@ -41,6 +41,10 @@ import Dialog from "carbon-react/lib/components/dialog";
 
 ### Default
 
+The call-to-action element should always be focused when the `Dialog` is closed. However, in some instances it may not receive focus
+due to specific browser design choices. The below example shows how to programmatically focus the call-to-action element when the `Dialog` is closed
+to ensure behaviour is consistent across all browsers.
+
 <Canvas of={DialogStories.DefaultStory} />
 
 ### With Maximum Size
diff --git a/src/components/dialog/dialog.pw.tsx b/src/components/dialog/dialog.pw.tsx
index db9c302e6..fb02cde2b 100644
--- a/src/components/dialog/dialog.pw.tsx
+++ b/src/components/dialog/dialog.pw.tsx
@@ -11,6 +11,7 @@ import {
   DialogWithAutoFocusSelect,
   DialogComponentFocusableSelectors,
   DefaultStory,
+  DefaultNestedStory,
   Editable,
   WithHelp,
   LoadingContent,
@@ -249,6 +250,78 @@ test.describe("Testing Dialog component properties", () => {
     ).toBeFocused();
   });
 
+  test("when Dialog is opened and then closed, the call to action element should be focused", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<DefaultStory />);
+
+    const button = page.getByRole("button").filter({ hasText: "Open Dialog" });
+    const dialog = page.getByRole("dialog");
+    await expect(button).not.toBeFocused();
+    await expect(dialog).not.toBeVisible();
+
+    await button.click();
+    await expect(dialog).toBeVisible();
+    const closeButton = page.getByLabel("Close");
+    await closeButton.click();
+    await expect(button).toBeFocused();
+    await expect(dialog).not.toBeVisible();
+  });
+
+  test("when Dialog is open on render, then closed, opened and then closed again, the call to action element should be focused", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<DefaultStory open />);
+
+    const dialog = page.getByRole("dialog");
+    await expect(dialog).toBeVisible();
+    const closeButton = page.getByLabel("Close");
+    await closeButton.click();
+
+    const button = page.getByRole("button").filter({ hasText: "Open Dialog" });
+    await expect(button).not.toBeFocused();
+    await expect(dialog).not.toBeVisible();
+
+    await button.click();
+    await expect(dialog).toBeVisible();
+    await closeButton.click();
+    await expect(button).toBeFocused();
+  });
+
+  test("when nested Dialog's are opened/closed their respective call to action elements should be focused correctly", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<DefaultNestedStory />);
+
+    const firstButton = page
+      .getByRole("button")
+      .filter({ hasText: "Open First Dialog" });
+    const firstDialog = page.getByRole("dialog").first();
+    await expect(firstButton).not.toBeFocused();
+    await expect(firstDialog).not.toBeVisible();
+
+    await firstButton.click();
+    await expect(firstDialog).toBeVisible();
+    const secondButton = page
+      .getByRole("button")
+      .filter({ hasText: "Open Nested Dialog" });
+    await expect(secondButton).not.toBeFocused();
+    await secondButton.click();
+    const secondDialog = page.getByRole("dialog").last();
+    await expect(secondDialog).toBeVisible();
+
+    const secondCloseButton = page.getByLabel("Close").last();
+    await secondCloseButton.click();
+    await expect(secondButton).toBeFocused();
+
+    const firstCloseButton = page.getByLabel("Close").first();
+    await firstCloseButton.click();
+    await expect(firstButton).toBeFocused();
+  });
+
   test("when disableAutoFocus prop is passed, the first focusable element should not be focused", async ({
     mount,
     page,
diff --git a/src/components/dialog/dialog.stories.tsx b/src/components/dialog/dialog.stories.tsx
index e979413b9..1b0026ac1 100644
--- a/src/components/dialog/dialog.stories.tsx
+++ b/src/components/dialog/dialog.stories.tsx
@@ -63,15 +63,19 @@ export const DefaultStory: Story = {
   },
   render: function DefaultStory({ onCancel, ...args }) {
     const [{ open }, updateArgs] = useArgs();
+    const buttonRef = useRef<HTMLButtonElement>(null);
     return (
       <>
-        <Button onClick={() => updateArgs({ open: true })}>Open Dialog</Button>
+        <Button ref={buttonRef} onClick={() => updateArgs({ open: true })}>
+          Open Dialog
+        </Button>
         <Dialog
           {...args}
           open={open}
           onCancel={(ev) => {
             onCancel?.(ev);
             updateArgs({ open: false });
+            setTimeout(() => buttonRef.current?.focus(), 0);
           }}
         >
           <Form
diff --git a/src/components/menu/menu-full-screen/menu-full-screen.component.tsx b/src/components/menu/menu-full-screen/menu-full-screen.component.tsx
index 34d1fbe3d..3b9594dab 100644
--- a/src/components/menu/menu-full-screen/menu-full-screen.component.tsx
+++ b/src/components/menu/menu-full-screen/menu-full-screen.component.tsx
@@ -91,6 +91,7 @@ export const MenuFullscreen = ({
     closeModal,
     modalRef: menuRef,
     topModalOverride,
+    focusCallToActionElement: document.activeElement as HTMLElement,
   });
 
   return (
diff --git a/src/components/menu/menu.mdx b/src/components/menu/menu.mdx
index bae54f902..2108870f1 100644
--- a/src/components/menu/menu.mdx
+++ b/src/components/menu/menu.mdx
@@ -151,6 +151,9 @@ This story is best viewed in the `canvas` view and by adjusting the size of the
 trigger when the screen size is smaller than `1200px`. Please note the `MenuItem`s are intended to have a width that fills the viewport,
 as such any `maxWidth` value passed will not be set when they are children of `MenuFullscreen`.
 
+The call-to-action `MenuItem` should always be focused when the `MenuFullscreen` is closed. However, in some instances it may not receive focus
+due to specific browser design choices.
+
 <Canvas of={MenuStories.FullscreenViewStory} />
 
 ## Props
diff --git a/src/components/menu/menu.pw.tsx b/src/components/menu/menu.pw.tsx
index fe9236d33..8b9323edb 100644
--- a/src/components/menu/menu.pw.tsx
+++ b/src/components/menu/menu.pw.tsx
@@ -52,6 +52,7 @@ import {
   MenuComponentSearch,
   MenuWithChildrenUpdating,
   MenuComponentFullScreen,
+  MenuComponentFullScreenSimple,
   MenuFullScreenBackgroundScrollTest,
   MenuComponentItems,
   MenuFullScreenWithSearchButton,
@@ -1062,6 +1063,46 @@ test.describe("Prop tests for Menu component", () => {
     }
   );
 
+  test("when a Menu Fullscreen is opened and then closed, the call to action element should be focused", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<MenuComponentFullScreenSimple open={false} />);
+
+    await page.setViewportSize({ width: 1200, height: 800 });
+    const item = page.getByRole("button").filter({ hasText: "Menu" });
+    await item.click();
+    const fullscreen = getComponent(page, "menu-fullscreen");
+    await waitForAnimationEnd(fullscreen);
+    const closeButton = page.getByLabel("Close");
+    await closeButton.click();
+    await expect(item).toBeFocused();
+  });
+
+  test("when Menu Fullscreen is open on render, then closed, opened and then closed again, the call to action element should be focused", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<MenuComponentFullScreenSimple />);
+
+    await page.setViewportSize({ width: 1200, height: 800 });
+    const fullscreen = getComponent(page, "menu-fullscreen");
+    await waitForAnimationEnd(fullscreen);
+    await expect(fullscreen).toBeVisible();
+    const closeButton = page.getByLabel("Close");
+    await closeButton.click();
+
+    const item = page.getByRole("button").filter({ hasText: "Menu" });
+    await expect(item).not.toBeFocused();
+    await expect(fullscreen).not.toBeVisible();
+
+    await item.click();
+    await waitForAnimationEnd(fullscreen);
+    await expect(fullscreen).toBeVisible();
+    await closeButton.click();
+    await expect(item).toBeFocused();
+  });
+
   // TODO: Skipped due to flaky focus behaviour. To review in FE-6428
   test.skip(`should verify that inner Menu without link is NOT available with tabbing in Fullscreen Menu`, async ({
     mount,
diff --git a/src/components/modal/modal.component.tsx b/src/components/modal/modal.component.tsx
index 4e0447a11..1b15de34b 100644
--- a/src/components/modal/modal.component.tsx
+++ b/src/components/modal/modal.component.tsx
@@ -89,6 +89,7 @@ const Modal = ({
     modalRef: ref,
     setTriggerRefocusFlag,
     topModalOverride,
+    focusCallToActionElement: document.activeElement as HTMLElement,
   });
 
   let background;
diff --git a/src/components/sidebar/sidebar.mdx b/src/components/sidebar/sidebar.mdx
index e97983ce8..3c01ca19b 100644
--- a/src/components/sidebar/sidebar.mdx
+++ b/src/components/sidebar/sidebar.mdx
@@ -43,6 +43,10 @@ import Sidebar from "carbon-react/lib/components/sidebar";
 
 ### Default
 
+The call-to-action element should always be focused when the `Sidebar` is closed. However, in some instances it may not receive focus
+due to specific browser design choices. The below example shows how to programmatically focus the call-to-action element when the `Sidebar` is closed
+to ensure behaviour is consistent across all browsers.
+
 <Canvas of={SidebarStories.DefaultStory} />
 
 ### Custom padding around content
diff --git a/src/components/sidebar/sidebar.pw.tsx b/src/components/sidebar/sidebar.pw.tsx
index cacbecff4..75a0ad4da 100644
--- a/src/components/sidebar/sidebar.pw.tsx
+++ b/src/components/sidebar/sidebar.pw.tsx
@@ -20,6 +20,8 @@ import {
   waitForAnimationEnd,
 } from "../../../playwright/support/helper";
 import {
+  Default,
+  DefaultNested,
   SidebarBackgroundScrollTestComponent,
   SidebarBackgroundScrollWithOtherFocusableContainers,
   SidebarComponent,
@@ -270,6 +272,78 @@ test.describe("Prop tests for Sidebar component", () => {
     await expect(closeIconButtonElement).toBeFocused();
   });
 
+  test("when Sidebar is opened and then closed, the call to action element should be focused", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<Default open={false} />);
+
+    const button = page.getByRole("button").filter({ hasText: "Open sidebar" });
+    const sidebar = sidebarPreview(page);
+    await expect(button).not.toBeFocused();
+    await expect(sidebar).not.toBeVisible();
+
+    await button.click();
+    await expect(sidebar).toBeVisible();
+    const closeButton = page.getByLabel("Close");
+    await closeButton.click();
+    await expect(button).toBeFocused();
+    await expect(sidebar).not.toBeVisible();
+  });
+
+  test("when Sidebar is open on render, then closed, opened and then closed again, the call to action element should be focused", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<Default />);
+
+    const sidebar = sidebarPreview(page);
+    await expect(sidebar).toBeVisible();
+    const closeButton = page.getByLabel("Close");
+    await closeButton.click();
+
+    const button = page.getByRole("button").filter({ hasText: "Open sidebar" });
+    await expect(button).not.toBeFocused();
+    await expect(sidebar).not.toBeVisible();
+
+    await button.click();
+    await expect(sidebar).toBeVisible();
+    await closeButton.click();
+    await expect(button).toBeFocused();
+  });
+
+  test("when nested Sidebar's are opened/closed their respective call to action elements should be focused correctly", async ({
+    mount,
+    page,
+  }) => {
+    await mount(<DefaultNested />);
+
+    const firstButton = page
+      .getByRole("button")
+      .filter({ hasText: "Open First Sidebar" });
+    const firstSidebar = sidebarPreview(page).first();
+    await expect(firstButton).not.toBeFocused();
+    await expect(firstSidebar).not.toBeVisible();
+
+    await firstButton.click();
+    await expect(firstSidebar).toBeVisible();
+    const secondButton = page
+      .getByRole("button")
+      .filter({ hasText: "Open Nested Sidebar" });
+    await expect(secondButton).not.toBeFocused();
+    await secondButton.click();
+    const secondSidebar = sidebarPreview(page).last();
+    await expect(secondSidebar).toBeVisible();
+
+    const secondCloseButton = page.getByLabel("Close").last();
+    await secondCloseButton.click();
+    await expect(secondButton).toBeFocused();
+
+    const firstCloseButton = page.getByLabel("Close").first();
+    await firstCloseButton.click();
+    await expect(firstButton).toBeFocused();
+  });
+
   test("should call onCancel callback when a click event is triggered", async ({
     mount,
     page,
diff --git a/src/components/sidebar/sidebar.stories.tsx b/src/components/sidebar/sidebar.stories.tsx
index fc2589c3a..9aca17b12 100644
--- a/src/components/sidebar/sidebar.stories.tsx
+++ b/src/components/sidebar/sidebar.stories.tsx
@@ -56,13 +56,20 @@ type Story = StoryObj<typeof Sidebar>;
 
 export const DefaultStory: Story = () => {
   const [isOpen, setIsOpen] = useState(defaultOpenState);
+  const buttonRef = useRef<HTMLButtonElement>(null);
+
   return (
     <>
-      <Button onClick={() => setIsOpen(true)}>Open sidebar</Button>
+      <Button ref={buttonRef} onClick={() => setIsOpen(true)}>
+        Open sidebar
+      </Button>
       <Sidebar
         aria-label="sidebar"
         open={isOpen}
-        onCancel={() => setIsOpen(false)}
+        onCancel={() => {
+          setIsOpen(false);
+          setTimeout(() => buttonRef.current?.focus(), 0);
+        }}
       >
         <Box mb={2}>
           <Button buttonType="primary">Test</Button>
diff --git a/src/hooks/__internal__/useModalManager/useModalManager.ts b/src/hooks/__internal__/useModalManager/useModalManager.ts
index f2be84ce4..f5c1a83bc 100644
--- a/src/hooks/__internal__/useModalManager/useModalManager.ts
+++ b/src/hooks/__internal__/useModalManager/useModalManager.ts
@@ -8,6 +8,7 @@ type UseModalManagerArgs = {
   setTriggerRefocusFlag?: (flag: boolean) => void;
   triggerRefocusOnClose?: boolean;
   topModalOverride?: boolean;
+  focusCallToActionElement?: HTMLElement;
 };
 
 const useModalManager = ({
@@ -17,9 +18,11 @@ const useModalManager = ({
   setTriggerRefocusFlag,
   triggerRefocusOnClose = true,
   topModalOverride = false,
+  focusCallToActionElement,
 }: UseModalManagerArgs) => {
   const listenerAdded = useRef(false);
   const modalRegistered = useRef(false);
+  const lastFocusedElement = useRef<HTMLElement | null>(null);
 
   const handleClose = useCallback(
     (ev: KeyboardEvent) => {
@@ -63,6 +66,12 @@ const useModalManager = ({
     };
   }, [removeListener]);
 
+  useEffect(() => {
+    if (!lastFocusedElement.current && focusCallToActionElement && open) {
+      lastFocusedElement.current = focusCallToActionElement;
+    }
+  }, [open, focusCallToActionElement]);
+
   const registerModal = useCallback(
     (ref: HTMLElement | null) => {
       /* istanbul ignore else */
@@ -80,6 +89,13 @@ const useModalManager = ({
       if (modalRegistered.current) {
         ModalManager.removeModal(ref, triggerRefocusOnClose);
 
+        if (lastFocusedElement.current) {
+          setTimeout(() => {
+            lastFocusedElement.current?.focus();
+            lastFocusedElement.current = null;
+          }, 0);
+        }
+
         modalRegistered.current = false;
       }
     },


Test patch:
diff --git a/src/components/dialog-full-screen/components.test-pw.tsx b/src/components/dialog-full-screen/components.test-pw.tsx
index e2c00e886..c2c99b297 100644
--- a/src/components/dialog-full-screen/components.test-pw.tsx
+++ b/src/components/dialog-full-screen/components.test-pw.tsx
@@ -25,12 +25,14 @@ const nestedDialogTitle = "Nested Dialog";
 
 export const DialogFullScreenComponent = ({
   children = "This is an example",
+  open = true,
   ...props
 }: Partial<DialogFullScreenProps>) => {
-  const [isOpen, setIsOpen] = useState(true);
+  const [isOpen, setIsOpen] = useState(open);
   const ref = useRef<HTMLButtonElement | null>(null);
   return (
     <>
+      <Button onClick={() => setIsOpen(true)}>Open Dialog Full Screen</Button>
       <DialogFullScreen
         focusFirstElement={ref}
         open={isOpen}
diff --git a/src/components/dialog/components.test-pw.tsx b/src/components/dialog/components.test-pw.tsx
index 27b28a376..54d0e15cd 100644
--- a/src/components/dialog/components.test-pw.tsx
+++ b/src/components/dialog/components.test-pw.tsx
@@ -210,8 +210,12 @@ export const DialogComponentFocusableSelectors = (
   );
 };
 
-export const DefaultStory = () => {
-  const [isOpen, setIsOpen] = useState(defaultOpenState);
+export const DefaultStory = ({
+  open = defaultOpenState,
+}: {
+  open?: boolean;
+}) => {
+  const [isOpen, setIsOpen] = useState(open);
   return (
     <>
       <Button onClick={() => setIsOpen(true)}>Open Dialog</Button>
@@ -253,6 +257,35 @@ export const DefaultStory = () => {
   );
 };
 
+export const DefaultNestedStory = () => {
+  const [isFirstDialogOpen, setIsFirstDialogOpen] = useState(false);
+  const [isNestedDialogOpen, setIsNestedDialogOpen] = useState(false);
+
+  return (
+    <>
+      <Button onClick={() => setIsFirstDialogOpen(true)}>
+        Open First Dialog
+      </Button>
+      <Dialog
+        open={isFirstDialogOpen}
+        onCancel={() => setIsFirstDialogOpen(false)}
+        title="First Dialog"
+      >
+        <Button onClick={() => setIsNestedDialogOpen(true)}>
+          Open Nested Dialog
+        </Button>
+        <Dialog
+          open={isNestedDialogOpen}
+          onCancel={() => setIsNestedDialogOpen(false)}
+          title="Nested Dialog"
+        >
+          <Textbox label="Nested Dialog Textbox" />
+        </Dialog>
+      </Dialog>
+    </>
+  );
+};
+
 export const Editable = () => {
   const [isOpen, setIsOpen] = useState(defaultOpenState);
   const [isDisabled, setIsDisabled] = useState(true);
diff --git a/src/components/menu/component.test-pw.tsx b/src/components/menu/component.test-pw.tsx
index a9582f2f0..119986de3 100644
--- a/src/components/menu/component.test-pw.tsx
+++ b/src/components/menu/component.test-pw.tsx
@@ -304,6 +304,30 @@ export const MenuComponentFullScreen = (
   );
 };
 
+export const MenuComponentFullScreenSimple = ({
+  open = true,
+}: {
+  open?: boolean;
+}) => {
+  const [menuOpen, setMenuOpen] = useState(open);
+
+  return (
+    <Menu menuType="light">
+      <MenuItem key="menu-item" onClick={() => setMenuOpen(true)}>
+        Menu
+      </MenuItem>
+      <MenuFullscreen
+        key="menu"
+        isOpen={menuOpen}
+        onClose={() => setMenuOpen(false)}
+      >
+        <MenuItem href="#">Menu Item One</MenuItem>
+        <MenuItem href="#">Menu Item Two</MenuItem>
+      </MenuFullscreen>
+    </Menu>
+  );
+};
+
 export const MenuComponentFullScreenWithLongSubmenuText = (
   props: Partial<MenuFullscreenProps>
 ) => {
diff --git a/src/components/sidebar/components.test-pw.tsx b/src/components/sidebar/components.test-pw.tsx
index 6d2742f4b..ce0d49ff1 100644
--- a/src/components/sidebar/components.test-pw.tsx
+++ b/src/components/sidebar/components.test-pw.tsx
@@ -8,15 +8,15 @@ import Toast from "../toast";
 import Textbox from "../textbox";
 import Dialog from "../dialog";
 
-export const Default = (args: Partial<SidebarProps>) => {
-  const [isOpen, setIsOpen] = useState(true);
+export const Default = ({ open = true }: { open?: boolean }) => {
+  const [isOpen, setIsOpen] = useState(open);
   const onCancel = () => {
     setIsOpen(false);
   };
   return (
     <>
       <Button onClick={() => setIsOpen(true)}>Open sidebar</Button>
-      <Sidebar {...args} aria-label="sidebar" open={isOpen} onCancel={onCancel}>
+      <Sidebar aria-label="sidebar" open={isOpen} onCancel={onCancel}>
         <Box mb={2}>
           <Button buttonType="primary">Test</Button>
           <Button buttonType="secondary" ml={2}>
@@ -29,6 +29,37 @@ export const Default = (args: Partial<SidebarProps>) => {
   );
 };
 
+export const DefaultNested = () => {
+  const [isFirstSidebarOpen, setIsFirstSidebarOpen] = useState(false);
+  const [isNestedSidebarOpen, setIsNestedSidebarOpen] = useState(false);
+  return (
+    <>
+      <Button onClick={() => setIsFirstSidebarOpen(true)}>
+        Open First Sidebar
+      </Button>
+      <Sidebar
+        open={isFirstSidebarOpen}
+        onCancel={() => setIsFirstSidebarOpen(false)}
+      >
+        <Button onClick={() => setIsNestedSidebarOpen(true)}>
+          Open Nested Sidebar
+        </Button>
+        <Sidebar
+          open={isNestedSidebarOpen}
+          onCancel={() => setIsNestedSidebarOpen(false)}
+        >
+          <Box mb={2}>
+            <Button buttonType="primary">Test</Button>
+            <Button buttonType="secondary" ml={2}>
+              Last
+            </Button>
+          </Box>
+        </Sidebar>
+      </Sidebar>
+    </>
+  );
+};
+
 export const SidebarComponent = (props: Partial<SidebarProps>) => {
   return (
     <>