diff --git a/src/lib/components/dialog/_NestedDialog.svelte b/src/lib/components/dialog/_NestedDialog.svelte
new file mode 100644
index 0000000..398f2a8
--- /dev/null
+++ b/src/lib/components/dialog/_NestedDialog.svelte
@@ -0,0 +1,21 @@
+
+
+
diff --git a/src/lib/components/dialog/_NestedTestComponent.svelte b/src/lib/components/dialog/_NestedTestComponent.svelte
new file mode 100644
index 0000000..8d20307
--- /dev/null
+++ b/src/lib/components/dialog/_NestedTestComponent.svelte
@@ -0,0 +1,9 @@
+
+
+
+{#if open}
+ (open = false)} />
+{/if}
diff --git a/src/lib/components/dialog/dialog.test.ts b/src/lib/components/dialog/dialog.test.ts
index 2d25916..d014349 100644
--- a/src/lib/components/dialog/dialog.test.ts
+++ b/src/lib/components/dialog/dialog.test.ts
@@ -1,6 +1,7 @@
import { Dialog, DialogDescription, DialogOverlay, DialogTitle } from "."
import TestTabSentinel from "./_TestTabSentinel.svelte";
import ManagedDialog from "./_ManagedDialog.svelte";
+import NestedTestComponent from "./_NestedTestComponent.svelte";
import { suppressConsoleLogs } from "$lib/test-utils/suppress-console-logs";
import { render } from "@testing-library/svelte";
import TestRenderer from "$lib/test-utils/TestRenderer.svelte";
@@ -9,7 +10,7 @@ import Div from "$lib/internal/elements/Div.svelte";
import Form from "$lib/internal/elements/Form.svelte";
import P from "$lib/internal/elements/P.svelte";
import Input from "$lib/internal/elements/Input.svelte";
-import { assertActiveElement, assertDialog, assertDialogDescription, DialogState, getByText, getDialog, getDialogOverlay } from "$lib/test-utils/accessibility-assertions";
+import { assertActiveElement, assertDialog, assertDialogDescription, DialogState, getByText, getDialog, getDialogOverlay, getDialogOverlays, getDialogs } from "$lib/test-utils/accessibility-assertions";
import { click, Keys, press } from "$lib/test-utils/interactions";
import Transition from "$lib/components/transitions/TransitionRoot.svelte";
import { tick } from "svelte";
@@ -677,3 +678,176 @@ describe('Mouse interactions', () => {
)
})
+describe('Nesting', () => {
+ it.each`
+ strategy | action
+ ${'with `Escape`'} | ${() => press(Keys.Escape)}
+ ${'with `Outside Click`'} | ${() => click(document.body)}
+ ${'with `Click on Dialog.Overlay`'} | ${() => click(getDialogOverlays().pop()!)}
+ `(
+ 'should be possible to open nested Dialog components and close them $strategy',
+ async ({ action }) => {
+ render(NestedTestComponent)
+
+ // Verify we have no open dialogs
+ expect(getDialogs()).toHaveLength(0)
+
+ // Open Dialog 1
+ await click(getByText('Open 1'))
+
+ // Verify that we have 1 open dialog
+ expect(getDialogs()).toHaveLength(1)
+
+ // Verify that the `Open 2 a` has focus
+ assertActiveElement(getByText('Open 2 a'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 2 b'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 2 c'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 2 a'))
+
+ // Open Dialog 2 via the second button
+ await click(getByText('Open 2 b'))
+
+ // Verify that we have 2 open dialogs
+ expect(getDialogs()).toHaveLength(2)
+
+ // Verify that the `Open 3 a` has focus
+ assertActiveElement(getByText('Open 3 a'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 3 b'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 3 c'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 3 a'))
+
+ // Close the top most Dialog
+ await action()
+
+ // Verify that we have 1 open dialog
+ expect(getDialogs()).toHaveLength(1)
+
+ // Verify that the `Open 2 b` button got focused again
+ assertActiveElement(getByText('Open 2 b'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 2 c'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 2 a'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 2 b'))
+
+ // Open Dialog 2 via button b
+ await click(getByText('Open 2 b'))
+
+ // Verify that the `Open 3 a` has focus
+ assertActiveElement(getByText('Open 3 a'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 3 b'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 3 c'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 3 a'))
+
+ // Verify that we have 2 open dialogs
+ expect(getDialogs()).toHaveLength(2)
+
+ // Open Dialog 3 via button c
+ await click(getByText('Open 3 c'))
+
+ // Verify that the `Open 4 a` has focus
+ assertActiveElement(getByText('Open 4 a'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 4 b'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 4 c'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 4 a'))
+
+ // Verify that we have 3 open dialogs
+ expect(getDialogs()).toHaveLength(3)
+
+ // Close the top most Dialog
+ await action()
+
+ // Verify that the `Open 3 c` button got focused again
+ assertActiveElement(getByText('Open 3 c'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 3 a'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 3 b'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 3 c'))
+
+ // Verify that we have 2 open dialogs
+ expect(getDialogs()).toHaveLength(2)
+
+ // Close the top most Dialog
+ await action()
+
+ // Verify that we have 1 open dialog
+ expect(getDialogs()).toHaveLength(1)
+
+ // Verify that the `Open 2 b` button got focused again
+ assertActiveElement(getByText('Open 2 b'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 2 c'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 2 a'))
+
+ // Verify that we can tab around
+ await press(Keys.Tab)
+ assertActiveElement(getByText('Open 2 b'))
+
+ // Close the top most Dialog
+ await action()
+
+ // Verify that we have 0 open dialogs
+ expect(getDialogs()).toHaveLength(0)
+
+ // Verify that the `Open 1` button got focused again
+ assertActiveElement(getByText('Open 1'))
+ }
+ )
+})
+