Marble UI
← Components

Portal

Preview: Default

Sets where every overlay (React Aria and Base UI components in Marble UI) renders. Point it at a themed element so popovers inherit data-theme / dark.

Import

import { PortalProvider, Portal } from '@marbleui/ui'

Props

<PortalProvider>

PropTypeDefaultDescription
children *requiredReactNode—
getContainer *required() => HTMLElement | null—

<Portal>

Render children into the nearest PortalProvider container (or document.body).

PropTypeDefaultDescription
children *requiredReactNode—

Usage notes

PortalProvider sets where overlays render; Portal renders children there. Use it so popovers and modals inherit a themed element (data-theme, dark mode) or live inside a specific container such as a shadow root.

<PortalProvider getContainer={() => document.getElementById('theme-root')}>
  <App />
</PortalProvider>
  • getContainer returns the target element; if it returns null, overlays fall back to the default (document.body).
  • Portal renders into the nearest PortalProvider container, or document.body when there is none. Use it to escape overflow: hidden or stacking contexts.
  • PortalProvider is built on React Aria’s UNSAFE_PortalProvider, so treat the container as stable across renders.
Example source · show
import { useState } from 'react'
import { Button } from '../button'
import { Portal } from './portal'

function Demo() {
  const [open, setOpen] = useState(false)
  return (
    <div className="flex flex-col items-center gap-3">
      <div className="w-72 overflow-hidden rounded-lg border border-border p-4 text-sm text-fg-muted">
        This box has overflow:hidden, but the portaled badge escapes it.
        <Button size="sm" className="mt-3" onPress={() => setOpen(!open)}>{open ? 'Hide' : 'Show'} floating badge</Button>
      </div>
      {open && (
        <Portal>
          <div className="fixed right-6 bottom-6 z-50 rounded-full bg-accent px-4 py-2 text-sm font-medium text-accent-fg shadow-lg">Rendered in a portal</div>
        </Portal>
      )}
    </div>
  )
}

export const styles = { Default: Demo }

Source: packages/ui/src/portal/portal.tsx

Catalog

Category
utilities
Priority
Core
Primitive
react-aria
React Aria
PortalProvider