Skip to main content
Docs

<UNSAFE_PortalProvider> component

The <UNSAFE_PortalProvider> component allows you to specify a custom container for Clerk floating UI elements (popovers, modals, tooltips, etc.) that use portals. Only Clerk components within the provider will be affected, components outside the provider will continue to use the default document.body for portals.

This is particularly useful when using Clerk components inside external UI libraries like Radix Dialog or React Aria Components, where portaled elements need to render within the dialog's container to remain interactable.

Caution

This component is marked as UNSAFE because it is an escape hatch that modifies the portal behavior of Clerk components. Not all portal locations will work correctly - some may cause issues with styling, accessibility, or other functionality. Typically, it is best to portal to the root of your application (e.g., the body element), outside of any possible overflow or stacking contexts.

Use <UNSAFE_PortalProvider> only when necessary, such as When Clerk components are rendered inside external dialogs or popovers, or when you need to group all portaled elements into a single container at the root of your app.

With Radix Dialog

A common use case is rendering Clerk components inside a Radix Dialog. Without <UNSAFE_PortalProvider>, the <UserButton> popover would render outside the dialog and may not be interactable.

app/components/UserDialog.tsx
'use client'

import { useRef } from 'react'
import * as Dialog from '@radix-ui/react-dialog'
import { UNSAFE_PortalProvider, UserButton } from '@clerk/nextjs'

export default function UserDialog() {
  const containerRef = useRef<HTMLDivElement>(null)

  return (
    <Dialog.Root>
      <Dialog.Trigger>Open Dialog</Dialog.Trigger>
      <Dialog.Portal>
        <Dialog.Overlay />
        <Dialog.Content ref={containerRef}>
          <UNSAFE_PortalProvider getContainer={() => containerRef.current}>
            <UserButton />
          </UNSAFE_PortalProvider>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  )
}
  • Name
    getContainer
    Type
    () => HTMLElement | null
    Description

    A function that returns the container element where portals should be rendered. This function is called each time a portal needs to be rendered, so it should return a stable reference to the container element.

  • Name
    children
    Type
    React.ReactNode
    Description

    The Clerk components that should have their portals rendered into the custom container.

Feedback

What did you think of this content?

Last updated on