{/* eslint-disable-next-line react/no-danger */}
diff --git a/packages/react/src/select/positioner/SelectPositioner.tsx b/packages/react/src/select/positioner/SelectPositioner.tsx
index 82e7f8d8b4..4ca9617e4f 100644
--- a/packages/react/src/select/positioner/SelectPositioner.tsx
+++ b/packages/react/src/select/positioner/SelectPositioner.tsx
@@ -10,6 +10,7 @@ import { popupStateMapping } from '../../utils/popupStateMapping';
import { useSelectPositioner } from './useSelectPositioner';
import type { Align, Side } from '../../utils/useAnchorPositioning';
import { SelectPositionerContext } from './SelectPositionerContext';
+import { InternalBackdrop } from '../../utils/InternalBackdrop';
/**
* Positions the select menu popup against the trigger.
@@ -38,7 +39,7 @@ const SelectPositioner = React.forwardRef(function SelectPositioner(
...otherProps
} = props;
- const { open, mounted, setPositionerElement, listRef, labelsRef, floatingRootContext } =
+ const { open, mounted, setPositionerElement, listRef, labelsRef, floatingRootContext, modal } =
useSelectRootContext();
const { getPositionerProps, positioner } = useSelectPositioner({
@@ -83,6 +84,7 @@ const SelectPositioner = React.forwardRef(function SelectPositioner(
return (
+ {mounted && modal && }
{renderElement()}
diff --git a/packages/react/src/select/root/SelectRoot.test.tsx b/packages/react/src/select/root/SelectRoot.test.tsx
index 1ce53296a8..8110d4b23b 100644
--- a/packages/react/src/select/root/SelectRoot.test.tsx
+++ b/packages/react/src/select/root/SelectRoot.test.tsx
@@ -348,4 +348,66 @@ describe('
', () => {
'',
);
});
+
+ describe('prop: modal', () => {
+ it('should render an internal backdrop when `true`', async () => {
+ const { user } = await render(
+
+
+ Open
+
+
+
+ 1
+
+
+
+
+
+
,
+ );
+
+ const trigger = screen.getByTestId('trigger');
+
+ await user.click(trigger);
+
+ await waitFor(() => {
+ expect(screen.queryByRole('listbox')).not.to.equal(null);
+ });
+
+ const positioner = screen.getByTestId('positioner');
+
+ expect(positioner.previousElementSibling).to.have.attribute('role', 'presentation');
+ });
+
+ it('should not render an internal backdrop when `false`', async () => {
+ const { user } = await render(
+
+
+ Open
+
+
+
+ 1
+
+
+
+
+
+
,
+ );
+
+ const trigger = screen.getByTestId('trigger');
+
+ await user.click(trigger);
+
+ await waitFor(() => {
+ expect(screen.queryByRole('listbox')).not.to.equal(null);
+ });
+
+ const positioner = screen.getByTestId('positioner');
+
+ expect(positioner.previousElementSibling).to.equal(null);
+ });
+ });
});
diff --git a/packages/react/src/select/root/SelectRoot.tsx b/packages/react/src/select/root/SelectRoot.tsx
index 0dcf93b522..c7848d5f23 100644
--- a/packages/react/src/select/root/SelectRoot.tsx
+++ b/packages/react/src/select/root/SelectRoot.tsx
@@ -8,12 +8,6 @@ import { useFieldRootContext } from '../../field/root/FieldRootContext';
import { visuallyHidden } from '../../utils/visuallyHidden';
import { PortalContext } from '../../portal/PortalContext';
-const inertStyle = `
- [data-floating-ui-inert] {
- pointer-events: none !important;
- }
-`;
-
/**
* Groups all parts of the select.
* Doesn’t render its own HTML element.
@@ -71,10 +65,6 @@ const SelectRoot: SelectRoot = function SelectRoot
(
return (
- {selectRoot.rootContext.open && modal && (
- /* eslint-disable-next-line react/no-danger */
-
- )}
{props.children}
diff --git a/packages/react/src/utils/InternalBackdrop.tsx b/packages/react/src/utils/InternalBackdrop.tsx
new file mode 100644
index 0000000000..1bb8d8b5b2
--- /dev/null
+++ b/packages/react/src/utils/InternalBackdrop.tsx
@@ -0,0 +1,8 @@
+import * as React from 'react';
+
+/**
+ * @ignore - internal component.
+ */
+export function InternalBackdrop() {
+ return ;
+}