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 do not 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 an 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>
Forward HTML attributes to portal content
PortalRoot.Provider also forwards any extra HTML attributes to the portal DOM element. Any standard HTML attribute you pass will be applied to every portal element rendered by components inside the provider (such as Dropdown, Autocomplete, DatePicker, Dialog, Drawer, Popover, and Tooltip).
import { PortalRoot, Dropdown, Dialog } from '@dnb/eufemia'render(<PortalRoot.Provider data-my-need="something"><Dropdown /><Dialog /></PortalRoot.Provider>)
In this example, every portal element will receive data-my-need="something" for content rendered outside the main React tree.
BrowserTranslate helper (Google Translate)
The BrowserTranslate helper component prevents browser translation tools (such as Google Translate) from modifying the content of form components. It works by combining the Eufemia Provider's formElement context with PortalRoot.Provider, so both the visible component (e.g. a button) and its portal-rendered content (e.g. a dropdown list) receive translate="no".
import { BrowserTranslate } from '@dnb/eufemia/shared'import { Dropdown } from '@dnb/eufemia'render(<BrowserTranslate off><Dropdown data={['Brukskonto', 'Sparekonto', 'BSU']} /></BrowserTranslate>)
When off is set, every form component inside the scope will have translate="no" on both its trigger element and its portal content. Without off, the component renders children as-is.