- Advanced Toast
- ArrowButton
- Arrows
- Avatar
- Backdrop
- Basic Toast
- Breadcrumb
- Button
- CardBackground
- Card
- ChatButton
- Checkbox
- Checkboxes
- Chip
- ChoiceExpander
- Clickable
- Date Field
- Dropdown
- ElasticHeight
- ExpandableCard
- Filter
- FormCheckbox
- Form Control
- Form Label
- HamburgerIcon
- Heading
- Image
- Link
- Loader
- Number Field
- Pagination
- Password
- Phone Field
- Popin
- Portal
- Prose
- Radio Group
- Radio
- Range
- Select
- SidebarLayout
- Spinner
- Switch
- Tabs
- Tag
- TextField
- ValidationMessage
Portal Target Container:
'use client';
import { Portal } from '@/ui/Portal';
import { useState } from 'react';
export function PortalDemo() {
const [showPortal, setShowPortal] = useState(false);
return (
<div className="space-y-16">
<button
onClick={() => setShowPortal(!showPortal)}
className="rounded-md bg-blue-600 px-16 py-8 text-white hover:bg-blue-700"
>
{showPortal ? 'Hide' : 'Show'} Portal Content
</button>
{showPortal && (
<Portal target="portal-demo-target">
<div className="rounded-md border border-gray-300 bg-white p-16 shadow-lg">
<p className="text-gray-900">
This content is rendered in a portal outside the normal DOM hierarchy.
</p>
</div>
</Portal>
)}
<div
id="portal-demo-target"
className="min-h-64 rounded-md border-2 border-dashed border-gray-400 p-16"
>
<p className="mb-8 text-sm text-gray-600">Portal Target Container:</p>
</div>
</div>
);
}
Installation
npx shadcn@latest add https://develop.trident-ui.pro.clubmed/r/portal.json
Usage
'use client';
import { Portal } from '@/docs/lib/ui/portal';
export function Component() {
return (
<>
<Portal target="modal-root">
<div className="modal-content">This will be rendered in the #modal-root element</div>
</Portal>
<div id="modal-root" />
</>
);
}API Reference
Portal
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | undefined | The content to render inside the portal. If no children are provided, nothing will be rendered. |
target | string | "portal" | The ID of the DOM element where the portal content will be rendered. If the element doesn't exist, it will be created automatically. |
disabled | boolean | false | When true, renders children in place instead of using a portal. Useful for disabling portal behavior conditionally. |
key | string | undefined | Optional React key for the portal. Passed directly to createPortal. |
Notes
-
React Portal: Uses React's
createPortalAPI to render content outside the parent component's DOM hierarchy while maintaining the React component tree. -
Automatic Container Creation: If the target element with the specified ID doesn't exist, the Portal component automatically creates a new
<div>with that ID and appends it todocument.body. The created element includes default classes:relative,isolate, andz-1. -
Client-Side Only: The Portal component is a client component (
"use client") and only renders on the client side. It returnsnullduring server-side rendering to prevent hydration mismatches. -
Conditional Rendering: The portal only renders when:
- The component has mounted on the client (
isClientistrue) - Children are provided (
Children.count(children) > 0) - A valid portal container exists
disabledprop isfalse
- The component has mounted on the client (
-
Disabled Mode: When
disabled={true}, the Portal component renders children directly in place without using a portal. This is useful for conditionally enabling/disabling portal behavior based on breakpoints or other conditions. -
Use Cases: Portals are commonly used for:
- Modal dialogs that need to escape parent overflow/z-index constraints
- Tooltips and popovers that need to be positioned relative to the viewport
- Dropdown menus that might be clipped by parent containers
- Toast notifications that need to appear at the root level
-
withPortal HOC: The component exports a
withPortalhigher-order component that wraps any component with Portal functionality:const ModalWithPortal = withPortal('modal-root', MyModalComponent); -
Z-Index Management: Portal containers created automatically have
z-1class applied, providing a base stacking context. You can control the z-index of portal content through className on the children. -
Multiple Portals: You can render multiple Portal components with different
targetIDs to create separate portal roots for different types of content (e.g., modals, tooltips, notifications).