# toMountNodeProps

Utility function that normalizes Portal mount node properties.

## Utility function

Fluent UI uses a wrapper component called `Portal` to render portals using [`ReactDOM.createPortal()`](https://react.dev/reference/react-dom/createPortal).
`Portal` component accepts a `mountNode` prop that can be used to specify the DOM node where the portal should be rendered. That prop also accepts an object that allows to configure rendering of a mount node.

For example, you can pass `className` to add a class to the mount node:

```tsx
import { Portal } from '@coreai-ds/react-components';

const MyComponent = () => (
  <Portal
    mountNode={{
      className: 'my-mount-node',
    }}
  >
    <div>Portal content</div>
  </Portal>
);
```

To ensure that props normalization is consistent across all components, we use `toMountNodeProps` function to normalize `mountNode` prop.

```tsx
import { toMountNodeProps } from '@coreai-ds/react-components';

toMountNodeProps(element); // { element: element }
toMountNodeProps({ className: 'my-mount-node' }); // { className: 'my-mount-node' }
```

This function is used internally by the `Portal` component, but it can also be used to build custom components that accept the `mountNode` prop.

## Default

Source: Fluent, adapted for CoreAI.

[Download source](/coreai-design-system/source/examples/components-portal-tomountnodeprops--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { Button } from "@coreai-ds/react-components";
import type { PortalProps } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { toMountNodeProps } from "@coreai-ds/react-components";
import { mergeClasses } from "@coreai-ds/react-components";
import { Portal } from "@coreai-ds/react-components";

const useClasses = makeStyles({
    message: {
        backgroundColor: tokens.colorNeutralBackground1,
        border: `${tokens.strokeWidthThick} solid ${tokens.colorStatusSuccessBorder1}`,
        padding: '20px',
        fontSize: tokens.fontSizeBase600,
        position: 'fixed',
        top: '0',
        left: '0',
    },
    // Heads up!
    // Overrides Portal's default z-index
    portal: {
        zIndex: 1,
    },
});

const CustomMessage: React.FC<{
    children: React.ReactNode;
} & Pick<PortalProps, 'mountNode'>> = props => {
    const classes = useClasses();
    const mountNodeProps = toMountNodeProps(props.mountNode);
    mountNodeProps.className = mergeClasses(classes.portal, mountNodeProps.className);
    return (<Portal mountNode={mountNodeProps}>
      <div className={classes.message}>{props.children}</div>
    </Portal>);
};

export const Default = (): JSXElement => {
    const [open, setOpen] = React.useState(false);
    return (<>
      <Button onClick={() => setOpen(v => !v)}>Toggle message</Button>
      {open && <CustomMessage>This message is rendered in a custom mount node</CustomMessage>}
    </>);
};

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### toMountNodeProps API

The function that normalizes the `mountNode` prop into an object with element and className props.

```ts
declare function toMountNodeProps(mountNode: PortalProps["mountNode"]): { element?: HTMLElement | null; className?: string; };
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.