The Basics

    What it is

    A Portal is used to render content to document.body, outside of the normal HTML DOM structure. This is a component with no affiliated designs because the contents of the portal are left completely free-form.

    Most importantly, contents within a Portal retain the styling present in the original application when the original application is mounted in a Shadow DOM.

    How it works

    • The Root component detects whether it is mounted in a shadow DOM and prepares a portal off of document.body for future use.
    • The Portal component then attaches its content to this pre-made <div>.

    When to use

    • When blocking the entire page, like Modal or Lightbox.
    • When positioning a floating component, like the dropdown menu of Multiselect

    When not to use

    • If your needs can already be met with an existing Forge component.

    Forge components that Portal

    Multiselect

    Use Multiselect to create a dropdown list where users select 1 or more options.

    SingleSelect

    Use SingleSelect to create a dropdown list where users select a single option.

    Modal

    Use Modal to create a container that pops up over the page, forcing users to acknowledge or interact with its contents.

    Lightbox

    Use Lightbox to create a large container that pops up over the page, forcing users to acknowledge or interact with its contents.

    Tooltip

    Use Tooltip to create a small floating container that displays helpful text on hover or focus.

    Toast

    Use Toast to create a temporary notification or message that floats above page content.

    Typeahead

    Use Typeahead to create a field where users enter and edit data more efficiently using suggested text.

    How to use

    The Portal component must be a child of the Root component, otherwise its contents will never render.

    <Root>
      <Portal>
        Portal Contents
      </Portal>
    </Root>
    

    Style

    Design details

    There is no styling associated with a Portal. Application developers are on their own to create their own styling for whatever content appears inside the Portal.

    Placement and hierarchy

    Doesn’t apply to this component.

    Content

    Doesn’t apply to this component.

    Demos

    Portal Basic Share

    Coding

    Developer tips

    If access to the HTMLDivElement used as the mount point for the portal is required, there are two ways to get it:

    • Supply a ref to Portal
    • Use the withPortalData or withPortalDataAndRef higher order components to supply a non-null portalData: { portalNode } as a prop to your component.
      • Note, that this is how Portal is implemented.

    You must define custom styles in order to position your content on the page appropriately.

    Repository

    Implementation links

    Portal directory in Bitbucket

    Implementation details

    It is strongly recommended to familiarize yourself with the Forge source code. While this documentation is a best effort to document the intent and usage of a component, sometimes some features only become clear when looking at the source code. Also, looking at Forge's source code may help identify and fix bugs in either your application or Forge itself.

    Storybook files

    Forge maintains at least one storybook file per component. While the primary audience for these files is typically the Forge team, these storybook files may cover usages of the component not covered by a demo. The storybook for the latest version of forge can be found at go/forge-storybook-lts.

    Testing library

    Forge strongly encourages using testing-library to write tests for your application.

    "The more your tests resemble the way your software is used, the more confidence they can give you."

    If you're having trouble testing a Forge component using testing-library, it would be a good idea to see how Forge tests its own components. For the most part, Forge tries to use screen.getByRole as much as it can, as that API provides the best feedback on a11y compliance. Forge discourages the use of document.querySelector and screen.getByTestId as both APIs encourage using implementation details to test your component, and discourage adding roles to your component.

    With that being said, many of Forge's components were not built with accessability in mind. These components do break the recommendations listed above.

    Import statements

    In Nimbus applications

    athenaOne serves the Forge bundle independently from your application's bundle. Importing Forge components directly from '@athena/forge' takes advantage of this feature.

    import { Portal } from '@athena/forge'

    In standalone applications

    Importing components using the exact path to the module takes advantage of webpack's tree shaking feature. Webpack will include only that module and its dependencies.

    import Portal from '@athena/forge/Portal';

    To use this import guidance, Typescript applications must use typescript >= 4.7.3, and should add this setting to their tsconfig.json file:

    {
    "compilerOptions": {
    "moduleResolution": "Node16",
    }
    }

    If this setting doesn't work for your application, use this import statement instead:

    import Portal from '@athena/forge/dist/Portal';

    Props