Import
import { PortalRoot } from '@dnb/eufemia'
Description
PortalRoot is a React component that helps you make React's createPortal.
It lets you render some children into a different part of the DOM.
Good to know
- It contains CSS styles and screen reader accessibility features needed for proper usage of portals.
- It comes with support for style isolation.
- Everything inside the
PortalRootcan later be customized and stacked on top of each other using CSSz-index. - It is used in other components, like Tooltip, Modal, TermDefinition and DatePicker's calendar.
- A wrapper is inserted automatically as a child node to the HTML
<body>or the<IsolatedStyleScope scopeHash="your-scope" />element. - It adds
dnb-core-styleclass to the portal element, so you don't need to deal with that yourself. - In order to remove it from the accessibility tree, it uses
role="presentation". That means, when your content is visible, you need to set focus to it, so screen readers can read it. PortalRootprops override values fromPortalRoot.Providerif both are present.beforeSelectortakes precedence overinsideSelectorwhen both are provided on the same level.
Relevant links
Usage
For basic usage, just wrap your content with the PortalRoot component:
import { PortalRoot } from '@dnb/eufemia'render(<PortalRoot>Your content</PortalRoot>)
It will create a wrapper div and insert it as a child node to the HTML <body> element:
<body><!-- The portal root will be inserted here --><!-- Other content --></body>
Define where the portal root should be rendered
Sometimes you might want to have more control over where the portal root element is placed in the HTML structure.
To achieve this, you can create a element in your HTML with the id eufemia-portal-root:
<body><div class="with-something-else"><div id="app" /><div id="eufemia-portal-root" /></div></body>
Customize with id property
You can also customize the portal root element by passing a custom id property to the PortalRoot component:
import { PortalRoot } from '@dnb/eufemia'// This will use the existing element with id="my-custom-portal-root"render(<PortalRoot id="my-custom-portal-root">Your content</PortalRoot>)
This will create or reuse an element with the specified id in the HTML structure:
<body><div class="with-something-else"><div id="app" /><div id="my-custom-portal-root" /></div></body>
Without pre-existing element
If you are not able to modify the HTML structure, you can make use of the beforeSelector or insideSelector property to define where the portal root should be placed.
You can pass these selectors directly to PortalRoot:
import { PortalRoot } from '@dnb/eufemia'// Insert the portal root before the element with id="my-custom-id"render(<PortalRoot beforeSelector="#my-custom-id">Your content</PortalRoot>,)// Insert the portal root as the first child inside the element with class="my-selector"render(<PortalRoot insideSelector=".my-selector">Your content</PortalRoot>)
Customize properties via provider (context)
You can also pass properties to each PortalRoot by using the PortalRoot.Provider.
In this example, the DatePicker component renders its portal content before the element with the id my-custom-id.
import { PortalRoot, DatePicker } from '@dnb/eufemia'render(<PortalRoot.Provider beforeSelector="#my-custom-id"><DatePicker /></PortalRoot.Provider>,)
This makes the DatePicker render its portal content right before my-custom-id.
<body><div class="with-something-else"><!-- The portal root will be inserted here --><div id="my-custom-id" /></div></body>