diff --git a/packages/react/src/components/ComposedModal/ComposedModal.featureflag.mdx b/packages/react/src/components/ComposedModal/ComposedModal.featureflag.mdx
index 9e731d397a28..3b4d8cda9093 100644
--- a/packages/react/src/components/ComposedModal/ComposedModal.featureflag.mdx
+++ b/packages/react/src/components/ComposedModal/ComposedModal.featureflag.mdx
@@ -95,3 +95,16 @@ to a different level:
```
+
+Instead of wrapping your component with `ComposedModalPresence`, you can also use the higher-order function `withComposedModalPresence`.
+This will automatically wrap your component and handle the props as well as their types for you:
+
+```jsx
+export const MyComposedModal = withComposedModalPresence(
+ ({ onSubmit, onClose }) => {
+ ...
+ },
+);
+
+
+```
diff --git a/packages/react/src/components/ComposedModal/ComposedModalPresence.tsx b/packages/react/src/components/ComposedModal/ComposedModalPresence.tsx
index c0e4d3b762ff..9f8727a826b2 100644
--- a/packages/react/src/components/ComposedModal/ComposedModalPresence.tsx
+++ b/packages/react/src/components/ComposedModal/ComposedModalPresence.tsx
@@ -9,6 +9,8 @@ import React, {
createContext,
useContext,
useMemo,
+ type ComponentType,
+ type FC,
type PropsWithChildren,
} from 'react';
import {
@@ -80,3 +82,28 @@ export const useExclusiveComposedModalPresenceContext = (id: string) => {
const ctx = useContext(ComposedModalPresenceContext);
return ctx?.isPresenceExclusive(id) ? ctx : undefined;
};
+
+type WithComposedModalPresenceProps = Pick;
+
+/**
+ * Higher-order function that wraps a component with ComposedModalPresence
+ */
+export const withComposedModalPresence = (
+ Component: ComponentType
+): FC => {
+ const WithComposedModalPresence: FC<
+ TProps & WithComposedModalPresenceProps
+ > = (props) => {
+ const { open, ...componentProps } = props;
+
+ return (
+
+
+
+ );
+ };
+
+ WithComposedModalPresence.displayName = `withComposedModalPresence(${Component.displayName || Component.name || 'Component'})`;
+
+ return WithComposedModalPresence;
+};
diff --git a/packages/react/src/components/ComposedModal/index.tsx b/packages/react/src/components/ComposedModal/index.tsx
index fe29537ca9d7..6963d3e3dd31 100644
--- a/packages/react/src/components/ComposedModal/index.tsx
+++ b/packages/react/src/components/ComposedModal/index.tsx
@@ -13,6 +13,7 @@ export {
} from './ComposedModal';
export {
ComposedModalPresence,
+ withComposedModalPresence,
type ComposedModalPresenceProps,
} from './ComposedModalPresence';
diff --git a/packages/react/src/components/Modal/Modal.featureflag.mdx b/packages/react/src/components/Modal/Modal.featureflag.mdx
index 7417e558ab54..1b11ee9620a9 100644
--- a/packages/react/src/components/Modal/Modal.featureflag.mdx
+++ b/packages/react/src/components/Modal/Modal.featureflag.mdx
@@ -97,3 +97,16 @@ different level:
```
+
+Instead of wrapping your component with `ModalPresence`, you can also use the higher-order function `withModalPresence`.
+This will automatically wrap your component and handle the props as well as their types for you:
+
+```jsx
+export const MyModal = withModalPresence(
+ ({ onSubmit, onClose }) => {
+ ...
+ },
+);
+
+
+```
diff --git a/packages/react/src/components/Modal/ModalPresence.tsx b/packages/react/src/components/Modal/ModalPresence.tsx
index fbf72e809f60..db9b9b0feb5f 100644
--- a/packages/react/src/components/Modal/ModalPresence.tsx
+++ b/packages/react/src/components/Modal/ModalPresence.tsx
@@ -9,6 +9,8 @@ import React, {
createContext,
useContext,
useMemo,
+ type ComponentType,
+ type FC,
type PropsWithChildren,
} from 'react';
import {
@@ -73,3 +75,26 @@ export const useExclusiveModalPresenceContext = (id: string) => {
const ctx = useContext(ModalPresenceContext);
return ctx?.isPresenceExclusive(id) ? ctx : undefined;
};
+
+type WithModalPresenceProps = Pick;
+
+/**
+ * Higher-order function that wraps a component with ModalPresence
+ */
+export const withModalPresence = (
+ Component: ComponentType
+): FC => {
+ const WithModalPresence: FC = (props) => {
+ const { open, ...componentProps } = props;
+
+ return (
+
+
+
+ );
+ };
+
+ WithModalPresence.displayName = `withModalPresence(${Component.displayName || Component.name || 'Component'})`;
+
+ return WithModalPresence;
+};
diff --git a/packages/react/src/components/Modal/index.ts b/packages/react/src/components/Modal/index.ts
index 3376928cf848..f16d15a13400 100644
--- a/packages/react/src/components/Modal/index.ts
+++ b/packages/react/src/components/Modal/index.ts
@@ -5,7 +5,17 @@
* LICENSE file in the root directory of this source tree.
*/
import Modal, { type ModalProps } from './Modal';
-import { ModalPresence, type ModalPresenceProps } from './ModalPresence';
+import {
+ ModalPresence,
+ withModalPresence,
+ type ModalPresenceProps,
+} from './ModalPresence';
export default Modal;
-export { Modal, ModalPresence, type ModalProps, type ModalPresenceProps };
+export {
+ Modal,
+ ModalPresence,
+ withModalPresence,
+ type ModalProps,
+ type ModalPresenceProps,
+};