Repository: marigold-ui/marigold
Pull request #2761 (2023-02-10 08:36:31)

docs: improve `<Badge>` styles

changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: 32fc46eb66b41d390fe514814da2f0188841dbff

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/master/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/marigold-ui/marigold/new/update-badge-styles?filename=.changeset/smooth-poems-speak.md&value=---%0A%22%40marigold%2Fdocs%22%3A%20patch%0A---%0A%0Adocs%3A%20improve%20%60%3CBadge%3E%60%20styles%0A)


codecov[bot]: # [Codecov](https://codecov.io/gh/marigold-ui/marigold/pull/2761?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui) Report
> Merging [#2761](https://codecov.io/gh/marigold-ui/marigold/pull/2761?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui) (32fc46e) into [main](https://codecov.io/gh/marigold-ui/marigold/commit/e0045a5efaa0b95091d7eb2e2bc1891a5141dbda?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui) (e0045a5) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/marigold-ui/marigold/pull/2761/graphs/tree.svg?width=650&height=150&src=pr&token=YIIcKX7TZu&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui)](https://codecov.io/gh/marigold-ui/marigold/pull/2761?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui)

```diff
@@            Coverage Diff            @@
##              main     #2761   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          100       100           
  Lines         1165      1165           
  Branches       204       204           
=========================================
  Hits          1165      1165           
```

| Flag | Coverage Δ | |
|---|---|---|
| components | `100.00% <ø> (ø)` | |
| system | `100.00% <ø> (ø)` | |
| tokens | `100.00% <ø> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=marigold-ui#carryforward-flags-in-the-pull-request-comment) to find out more.



Patch:
diff --git a/.changeset/fifty-ravens-hope.md b/.changeset/fifty-ravens-hope.md
new file mode 100644
index 000000000..36fba57ce
--- /dev/null
+++ b/.changeset/fifty-ravens-hope.md
@@ -0,0 +1,6 @@
+---
+"@marigold/docs": minor
+"@marigold/components": minor
+---
+
+feat: Allow `<Dialog>` to be controlled via `<Dialog.Container>`
diff --git a/docs/src/components/Navigation/Navigation.tsx b/docs/src/components/Navigation/Navigation.tsx
index 0b39e8e30..457702446 100644
--- a/docs/src/components/Navigation/Navigation.tsx
+++ b/docs/src/components/Navigation/Navigation.tsx
@@ -90,31 +90,25 @@ const NavigationItem = ({
   variant,
   badge,
   ...props
-}: NavigationItemProps) => {
-  const badgeNameToLowerCase = (badge: string) => {
-    return badge.toLowerCase();
-  };
-  return (
-    <Box
-      as="li"
-      role="menuitem"
-      __baseCSS={{ listStyle: 'none' }}
-      css={css?.item}
-      display="flex"
-      justifyContent="space-between"
-      alignItems="center"
-    >
-      <Link variant="navigation" {...props}>
-        {title}
-      </Link>
-      {badge && (
-        <Badge variant={badgeNameToLowerCase(badge)} size="small">
-          {badge}
-        </Badge>
-      )}
-    </Box>
-  );
-};
+}: NavigationItemProps) => (
+  <Box
+    as="li"
+    role="menuitem"
+    css={[
+      css?.item,
+      {
+        display: 'flex',
+        alignItems: 'center',
+        gap: 'small-1',
+      },
+    ]}
+  >
+    <Link variant="navigation" {...props}>
+      {title}
+    </Link>
+    {badge && <Badge variant={badge.toLowerCase()}>{badge}</Badge>}
+  </Box>
+);
 
 const NavigationGroup = ({ name, items, css }: NavigationMenuGroupProps) => (
   <Box as="li" role="menuitem" __baseCSS={{ listStyle: 'none' }}>
diff --git a/docs/src/demos/components/Menu/index.ts b/docs/src/demos/components/Menu/index.ts
index 71ec50ec6..bca7fccb3 100644
--- a/docs/src/demos/components/Menu/index.ts
+++ b/docs/src/demos/components/Menu/index.ts
@@ -1,3 +1,4 @@
 export * from './menu-action.demo';
 export * from './menu-disabled.demo';
 export * from './kebab-menu.demo';
+export * from './menu-open-dialog.demo';
diff --git a/docs/src/demos/components/Menu/menu-open-dialog.demo.tsx b/docs/src/demos/components/Menu/menu-open-dialog.demo.tsx
new file mode 100644
index 000000000..13526664e
--- /dev/null
+++ b/docs/src/demos/components/Menu/menu-open-dialog.demo.tsx
@@ -0,0 +1,67 @@
+import { useState } from 'react';
+import {
+  Body,
+  Button,
+  Dialog,
+  Footer,
+  Header,
+  Headline,
+  Inline,
+  Menu,
+  Stack,
+  Text,
+} from '@marigold/components';
+
+export const OpenDialogFromMenu = () => {
+  const [open, setOpen] = useState(false);
+  const handleAction = (action: string) => {
+    switch (action) {
+      case 'two':
+        setOpen(!open);
+        break;
+      case 'one':
+        break;
+      default:
+        throw new Error(`Unhandled action "${action}"!`);
+    }
+  };
+  return (
+    <>
+      <Menu.Trigger>
+        <Button variant="menu" size="small">
+          Settings
+        </Button>
+        <Menu onAction={handleAction}>
+          <Menu.Item key="one">Save</Menu.Item>
+          <Menu.Item key="two">Delete</Menu.Item>
+        </Menu>
+      </Menu.Trigger>
+      <Dialog.Controller onOpenChange={o => setOpen(o)}>
+        {open && (
+          <Dialog closeButton>
+            {({ close, titleProps }) => (
+              <Stack space="medium">
+                <Header>
+                  <Headline {...titleProps}>Confirm delete</Headline>
+                </Header>
+                <Body>
+                  <Text>Do you really wanna delete this?</Text>
+                </Body>
+                <Footer>
+                  <Inline space="medium">
+                    <Button size="small" variant="ghost" onPress={close}>
+                      Abbrechen
+                    </Button>
+                    <Button size="small" variant="primary">
+                      Delete
+                    </Button>
+                  </Inline>
+                </Footer>
+              </Stack>
+            )}
+          </Dialog>
+        )}
+      </Dialog.Controller>
+    </>
+  );
+};
diff --git a/docs/src/pages/_app.tsx b/docs/src/pages/_app.tsx
index fe0c770ed..731490832 100644
--- a/docs/src/pages/_app.tsx
+++ b/docs/src/pages/_app.tsx
@@ -2,7 +2,7 @@ import type { AppProps } from 'next/app';
 import Head from 'next/head';
 import { MDXProvider } from '@mdx-js/react';
 
-import { Badge, MarigoldProvider, SSRProvider } from '@marigold/components';
+import { MarigoldProvider, SSRProvider } from '@marigold/components';
 import * as MarigoldComponents from '@marigold/components';
 import * as MarigoldIcons from '@marigold/icons';
 import unicornTheme from '@marigold/theme-unicorn';
@@ -70,10 +70,6 @@ const components = {
   ...MarigoldIcons,
 };
 
-const badgeNameToLowercase = (badge: string) => {
-  return badge.toLowerCase();
-};
-
 export interface PageProps {
   title?: string;
   caption?: string;
@@ -95,11 +91,6 @@ const MyApp = ({ Component, pageProps }: AppProps<PageProps>) => {
               <Title title={pageProps?.title} />
               {pageProps?.title && (
                 <Header>
-                  {pageProps?.badge && (
-                    <Badge variant={badgeNameToLowercase(pageProps.badge)}>
-                      {pageProps.badge}
-                    </Badge>
-                  )}
                   <GradientHeadline>{pageProps.title}</GradientHeadline>
                   {pageProps.caption && (
                     <Text variant="page-caption">{pageProps.caption}</Text>
diff --git a/docs/src/pages/components/dialog.mdx b/docs/src/pages/components/dialog.mdx
index d9b778089..64035a7f8 100644
--- a/docs/src/pages/components/dialog.mdx
+++ b/docs/src/pages/components/dialog.mdx
@@ -6,6 +6,7 @@ github: https://github.com/marigold-ui/marigold/blob/main/packages/components/sr
 edit: https://github.com/marigold-ui/marigold/blob/main/docs/src/pages/components/dialog.mdx
 switchTheme: true
 caption: Component for displaying dialogs.
+badge: updated
 ---
 
 The `<Dialog>` is a overlay component. This means it displays a modal as a reaction to an event. It appears in the middle of the display and blurs out the underlay.
@@ -14,6 +15,8 @@ This component can be styled in different parts. It has as parts `closeButton` a
 
 A special thing is also that you can have props on the `<Dialog.Trigger>` and on the `<Dialog>` itself. The `closeButton` is an optionally property with which you can close the `<Dialog>`.
 
+The `<Dialog.Controller>` should be used if you want to use the `<Dialog>` without a trigger. For example if you want to open it within a `<Menu>`.
+
 <Preview>
   <DialogDemo />
 </Preview>
@@ -76,6 +79,45 @@ import { Dialog } from '@marigold/components';
   ]}
 />
 
+### Controller props
+
+<PropsTable
+  props={[
+    {
+      property: 'open',
+      type: 'boolean',
+      description: 'Whether the overlay is open by default (controlled).',
+      default: 'false',
+    },
+    {
+      property: 'onOpenChange',
+      type: '(isOpen: boolean) => void',
+      description:
+        "Handler that is called when the overlay's open state changes.",
+      default: 'none',
+    },
+    {
+      property: 'dismissable',
+      type: 'boolean',
+      description:
+        'Whether to close the overlay when the user interacts outside it.',
+      default: 'true',
+    },
+    {
+      property: 'keyboardDismissable',
+      type: 'boolean',
+      description:
+        'Whether pressing the escape key to close the overlay should be disabled.',
+      default: 'true',
+    },
+    {
+      property: 'children',
+      type: 'ReactNode',
+      description: 'Children of the component.',
+    },
+  ]}
+/>
+
 ## Examples
 
 ### Form Dialog
@@ -93,3 +135,12 @@ If you choose to add `dismissable={false}` to your `<Dialog.Trigger>`, you can't
 ```tsx preview file=components/Dialog/dialog-dismiss.demo.tsx
 
 ```
+
+### Dialog opend from Menu
+
+This Example shows how to open a [`<Dialog>`](/components/dialog/) from a `<Menu.Item>`.
+For that you have not to use a `<Dialog.Trigger>`, instead use our `<Dialog.Controller>`. With that you don't have to use a `<Button>` to trigger the dialog.
+
+```tsx preview file=components/Menu/menu-open-dialog.demo.tsx
+
+```
diff --git a/docs/src/pages/components/menu.mdx b/docs/src/pages/components/menu.mdx
index 56b88ccb1..9554a6a37 100644
--- a/docs/src/pages/components/menu.mdx
+++ b/docs/src/pages/components/menu.mdx
@@ -89,3 +89,12 @@ It is very similar to the normal `<Menu>` component.
 ```tsx preview file=components/Menu/kebab-menu.demo.tsx
 
 ```
+
+### Menu item opens Dialog
+
+This Example shows how to open a [`<Dialog>`](/components/dialog/) from a `<Menu.Item>`.
+For that you have not to use a `<Dialog.Trigger>`, instead use our `<Dialog.Controller>`. With that you don't have to use a `<Button>` to trigger the dialog.
+
+```tsx preview file=components/Menu/menu-open-dialog.demo.tsx
+
+```
diff --git a/docs/src/theme/colors.ts b/docs/src/theme/colors.ts
index 9247402ae..367a6a02d 100644
--- a/docs/src/theme/colors.ts
+++ b/docs/src/theme/colors.ts
@@ -25,27 +25,27 @@ export const colors = {
   hover: {
     light: 'hsl(28, 100%, 53%, 0.1)',
   },
-  yellow: {
-    base: 'hsl(46, 81%, 63%)',
-    50: 'hsl(45, 97%, 54%)',
-  },
   info: {
     background: 'hsl(207, 100%, 98%)',
     base: 'hsl(208, 100%, 83%)',
     text: 'hsl(208, 100%, 20%)',
   },
-  red: {
-    50: 'hsl(0, 100%, 71%)',
+  success: {
+    background: 'hsl(79 81% 94%)',
+    base: 'hsl(84 69% 51%)',
+    text: 'hsl(85 84% 15%)',
   },
-
-  green: {
-    50: 'hsl(130, 57%, 56%)',
+  error: {
+    background: 'hsl(0 100% 95%)',
+    base: 'hsl(0 94% 65%)',
+    text: 'hsl(0 65% 36%)',
   },
-
-  blue: {
-    50: 'hsl(207, 86%, 57%)',
+  warning: {
+    background: 'hsl(50 100% 93%)',
+    base: 'hsl(45 97% 54%)',
+    text: 'hsl(31 100% 25%)',
   },
-  orange: {
-    50: 'hsl(29, 100%, 58%)',
+  yellow: {
+    base: 'hsl(46, 81%, 63%)',
   },
 };
diff --git a/docs/src/theme/components/Badge.style.ts b/docs/src/theme/components/Badge.style.ts
index dc93a8649..91cbc3aa5 100644
--- a/docs/src/theme/components/Badge.style.ts
+++ b/docs/src/theme/components/Badge.style.ts
@@ -4,45 +4,30 @@ export const Badge: Theme['components']['Badge'] = {
   base: {
     display: 'inline-flex',
     alignItems: 'center',
-    fontSize: 'fixed.medium-1',
+    fontSize: 'fixed.small-2',
     fontFamily: 'headline',
     textTransform: 'lowercase',
     borderRadius: 'medium-1',
-    border: '2px solid transparent',
     whiteSpace: 'nowrap',
-    py: 4,
-    px: 12,
-    mb: 16,
+    py: 'none',
+    px: 'small-1',
   },
   variant: {
     new: {
-      color: 'text.regular',
-      borderColor: 'green.50',
-      bg: 'green.50',
+      color: 'success.background',
+      bg: 'success.text',
     },
     updated: {
-      color: 'text.regular',
-      borderColor: 'blue.50',
-      bg: 'blue.50',
+      color: 'info.background',
+      bg: 'info.text',
     },
     beta: {
-      color: 'text.regular',
-      borderColor: 'yellow.50',
-      bg: 'yellow.50',
+      color: 'warning.background',
+      bg: 'warning.text',
     },
     deprecated: {
-      color: 'text.regular',
-      borderColor: 'red.50',
-      bg: 'red.50',
-    },
-  },
-  size: {
-    small: {
-      fontSize: '12px',
-      mb: 0,
-      py: 0,
-      px: 4,
-      ml: 16,
+      color: 'error.background',
+      bg: 'error.text',
     },
   },
 };
diff --git a/packages/components/src/Dialog/Dialog.stories.tsx b/packages/components/src/Dialog/Dialog.stories.tsx
index 2c8f48b0b..2d79dea13 100644
--- a/packages/components/src/Dialog/Dialog.stories.tsx
+++ b/packages/components/src/Dialog/Dialog.stories.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useState } from 'react';
 import type { Meta, ComponentStory } from '@storybook/react';
 
 import { Button } from '../Button';
@@ -14,6 +14,7 @@ import { Footer } from '../Footer';
 import { Header } from '../Header';
 import { Checkbox, CheckboxGroup } from '../Checkbox';
 import { Box } from '@marigold/system';
+import { Menu } from '../Menu';
 
 export default {
   title: 'Components/Dialog',
@@ -158,3 +159,56 @@ export const StickyFooter: ComponentStory<typeof Dialog.Trigger> = args => (
     </Dialog>
   </Dialog.Trigger>
 );
+
+export const FromMenu: ComponentStory<typeof Dialog.Trigger> = args => {
+  const [open, setOpen] = useState(false);
+  const handleAction = (action: string) => {
+    switch (action) {
+      case 'two':
+        setOpen(!open);
+        break;
+      default:
+        throw new Error(`Unhandled action "${action}"!`);
+    }
+  };
+
+  return (
+    <>
+      <Menu.Trigger>
+        <Button variant="menu" size="small">
+          Settings
+        </Button>
+        <Menu onAction={handleAction}>
+          <Menu.Item key="one">Save</Menu.Item>
+          <Menu.Item key="two">Delete</Menu.Item>
+        </Menu>
+      </Menu.Trigger>
+      <Dialog.Controller onOpenChange={o => setOpen(o)}>
+        {open && (
+          <Dialog closeButton>
+            {({ close, titleProps }) => (
+              <Stack space="medium">
+                <Header>
+                  <Headline {...titleProps}>Confirm delete</Headline>
+                </Header>
+                <Body>
+                  <Text>Do you really wanna delete this?</Text>
+                </Body>
+                <Footer>
+                  <Inline space="medium">
+                    <Button size="small" variant="ghost" onPress={close}>
+                      Abbrechen
+                    </Button>
+                    <Button size="small" variant="primary">
+                      Delete
+                    </Button>
+                  </Inline>
+                </Footer>
+              </Stack>
+            )}
+          </Dialog>
+        )}
+      </Dialog.Controller>
+    </>
+  );
+};
diff --git a/packages/components/src/Dialog/Dialog.tsx b/packages/components/src/Dialog/Dialog.tsx
index 621f3abb3..4501df37d 100644
--- a/packages/components/src/Dialog/Dialog.tsx
+++ b/packages/components/src/Dialog/Dialog.tsx
@@ -14,6 +14,7 @@ import { Header } from '../Header';
 import { Headline } from '../Headline';
 import { DialogContextProps, useDialogContext } from './Context';
 import { DialogTrigger } from './DialogTrigger';
+import { DialogController } from './DialogController';
 
 // Close Button
 // ---------------
@@ -145,3 +146,4 @@ export const Dialog = ({
 };
 
 Dialog.Trigger = DialogTrigger;
+Dialog.Controller = DialogController;
diff --git a/packages/components/src/Dialog/DialogController.tsx b/packages/components/src/Dialog/DialogController.tsx
new file mode 100644
index 000000000..b162b854e
--- /dev/null
+++ b/packages/components/src/Dialog/DialogController.tsx
@@ -0,0 +1,52 @@
+import { useOverlayTriggerState } from '@react-stately/overlays';
+import React, { ReactElement, ReactNode, useRef } from 'react';
+import { Modal, Overlay } from '../Overlay';
+import { DialogContext } from './Context';
+
+export interface DialogControllerProps {
+  children: ReactNode;
+  dismissable?: boolean;
+  keyboardDismissable?: boolean;
+  open?: boolean;
+  onOpenChange?: (isOpen: boolean) => void;
+}
+
+export const DialogController = ({
+  children,
+  dismissable = true,
+  keyboardDismissable = true,
+  onOpenChange,
+}: DialogControllerProps) => {
+  const childArray = React.Children.toArray(children);
+  if (childArray.length > 1) {
+    throw new Error('Only a single child can be passed to DialogController.');
+  }
+
+  const lastChild = useRef<ReactElement | null>(null);
+  const child = React.isValidElement(childArray[0]) ? childArray[0] : null;
+  if (child) {
+    lastChild.current = child;
+  }
+
+  const state = useOverlayTriggerState({
+    isOpen: !!child,
+    onOpenChange,
+  });
+
+  const ctx = { open: state.isOpen, close: state.close };
+
+  return (
+    <DialogContext.Provider value={ctx}>
+      <Overlay open={state.isOpen}>
+        <Modal
+          open={state.isOpen}
+          onClose={state.close}
+          dismissable={dismissable}
+          keyboardDismissable={keyboardDismissable}
+        >
+          {lastChild.current}
+        </Modal>
+      </Overlay>
+    </DialogContext.Provider>
+  );
+};


Test patch:
diff --git a/packages/components/src/Dialog/Dialog.test.tsx b/packages/components/src/Dialog/Dialog.test.tsx
index cb31444e8..9ec33cc5d 100644
--- a/packages/components/src/Dialog/Dialog.test.tsx
+++ b/packages/components/src/Dialog/Dialog.test.tsx
@@ -1,14 +1,15 @@
 /* eslint-disable testing-library/no-node-access */
+/* eslint-disable testing-library/no-container */
 import React from 'react';
 import { fireEvent, render, screen, waitFor } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
 
+import { OverlayProvider } from '@react-aria/overlays';
 import { ThemeProvider } from '@marigold/system';
 
 import { Dialog } from './Dialog';
 import { Button } from '../Button';
 import { Headline } from '../Headline';
-import { OverlayProvider } from '@react-aria/overlays';
 
 const theme = {
   colors: {
@@ -52,6 +53,17 @@ const theme = {
 };
 
 const user = userEvent.setup();
+
+let errorMock: jest.SpyInstance;
+
+beforeEach(() => {
+  errorMock = jest.spyOn(console, 'error').mockImplementation();
+});
+
+afterEach(() => {
+  errorMock.mockRestore();
+});
+
 test('renders children correctly', () => {
   render(
     <OverlayProvider>
@@ -416,3 +428,89 @@ test('dialog supports size', () => {
   expect(dialog).toBeVisible();
   expect(dialog).toHaveStyle('width: 400px');
 });
+
+test('renders with dialog controller', () => {
+  render(
+    <OverlayProvider>
+      <Dialog.Controller>
+        <Dialog>
+          <Headline>Headline</Headline>Content
+        </Dialog>
+      </Dialog.Controller>
+    </OverlayProvider>
+  );
+
+  const dialog = screen.getByRole('dialog');
+  expect(dialog).toBeVisible();
+});
+
+test('onOpenChange has been called in dialog controller', () => {
+  const setState = jest.fn();
+  const useStateSpy = jest.spyOn(React, 'useState');
+  // eslint-disable-next-line no-sparse-arrays
+  useStateSpy.mockImplementation(() => [, setState]);
+  render(
+    <OverlayProvider>
+      <Dialog.Controller onOpenChange={a => setState(a)}>
+        <Dialog>
+          <Headline>Headline</Headline>Content
+        </Dialog>
+      </Dialog.Controller>
+    </OverlayProvider>
+  );
+
+  expect(setState).toHaveBeenCalled();
+});
+
+test('dialog controller accepts only one child', () => {
+  render(
+    <OverlayProvider>
+      <Dialog.Controller>
+        <Dialog>
+          <Headline>Headline</Headline>Content
+        </Dialog>
+      </Dialog.Controller>
+    </OverlayProvider>
+  );
+
+  const dialog = screen.getByRole('dialog');
+  expect(dialog).toBeVisible();
+
+  const parent = dialog.parentElement;
+  expect(parent?.children).toHaveLength(1);
+  expect(parent?.children).not.toHaveLength(2);
+
+  expect(parent).toBeValid();
+  expect(dialog).toBeValid();
+});
+
+test('dialog controller throw errof if not one child', () => {
+  expect(() => {
+    render(
+      <OverlayProvider>
+        <Dialog.Controller>
+          <Dialog>Content</Dialog>
+          <div>something</div>
+        </Dialog.Controller>
+      </OverlayProvider>
+    );
+  }).toThrow(Error);
+  expect(errorMock).toHaveBeenCalled();
+});
+
+test('dialog controller expect no valid child', () => {
+  const children = null;
+  const { container } = render(
+    <OverlayProvider>
+      <Dialog.Controller data-testid="dialog">{children}</Dialog.Controller>
+    </OverlayProvider>
+  );
+
+  expect(
+    container.querySelector(`div[data-overlay-container="true"]`)?.childNodes
+  ).toHaveLength(0);
+
+  expect(
+    container.querySelector(`div[data-overlay-container="true"]`)?.lastChild
+  ).toBeNull();
+});