Utilities
Installation
CLI
npx shadcn@latest add @diceui/portalManual
Install the following dependencies:
npm install @radix-ui/react-slotCopy and paste the following code into your project.
"use client";
import { Slot as SlotPrimitive } from "radix-ui";
import * as React from "react";
import * as ReactDOM from "react-dom";
type SlotProps = React.ComponentProps<typeof SlotPrimitive.Slot>;
interface PortalProps extends SlotProps {
container?: Element | DocumentFragment | null;
}
function subscribe() {
return () => {};
}
function getSnapshot() {
return true;
}
function getServerSnapshot() {
return false;
}
function Portal(props: PortalProps) {
const { container: containerProp, ...portalProps } = props;
const mounted = React.useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot,
);
const container =
containerProp ?? (mounted ? globalThis.document?.body : null);
if (!container) return null;
return ReactDOM.createPortal(
<SlotPrimitive.Slot {...portalProps} />,
container,
);
}
export { Portal };
export type { PortalProps };"use client";
import { Slot as SlotPrimitive } from "radix-ui";
import * as React from "react";
import * as ReactDOM from "react-dom";
type SlotProps = React.ComponentProps<typeof SlotPrimitive.Slot>;
interface PortalProps extends SlotProps {
container?: Element | DocumentFragment | null;
}
function subscribe() {
return () => {};
}
function getSnapshot() {
return true;
}
function getServerSnapshot() {
return false;
}
function Portal(props: PortalProps) {
const { container: containerProp, ...portalProps } = props;
const mounted = React.useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot,
);
const container =
containerProp ?? (mounted ? globalThis.document?.body : null);
if (!container) return null;
return ReactDOM.createPortal(
<SlotPrimitive.Slot {...portalProps} />,
container,
);
}
export { Portal };
export type { PortalProps };"use client";
import { Slot as SlotPrimitive } from "radix-ui";
import * as React from "react";
import * as ReactDOM from "react-dom";
type SlotProps = React.ComponentProps<typeof SlotPrimitive.Slot>;
interface PortalProps extends SlotProps {
container?: Element | DocumentFragment | null;
}
function subscribe() {
return () => {};
}
function getSnapshot() {
return true;
}
function getServerSnapshot() {
return false;
}
function Portal(props: PortalProps) {
const { container: containerProp, ...portalProps } = props;
const mounted = React.useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot,
);
const container =
containerProp ?? (mounted ? globalThis.document?.body : null);
if (!container) return null;
return ReactDOM.createPortal(
<SlotPrimitive.Slot {...portalProps} />,
container,
);
}
export { Portal };
export type { PortalProps };"use client";
import { Slot as SlotPrimitive } from "radix-ui";
import * as React from "react";
import * as ReactDOM from "react-dom";
type SlotProps = React.ComponentProps<typeof SlotPrimitive.Slot>;
interface PortalProps extends SlotProps {
container?: Element | DocumentFragment | null;
}
function subscribe() {
return () => {};
}
function getSnapshot() {
return true;
}
function getServerSnapshot() {
return false;
}
function Portal(props: PortalProps) {
const { container: containerProp, ...portalProps } = props;
const mounted = React.useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot,
);
const container =
containerProp ?? (mounted ? globalThis.document?.body : null);
if (!container) return null;
return ReactDOM.createPortal(
<SlotPrimitive.Slot {...portalProps} />,
container,
);
}
export { Portal };
export type { PortalProps };"use client";
import { Slot as SlotPrimitive } from "radix-ui";
import * as React from "react";
import * as ReactDOM from "react-dom";
type SlotProps = React.ComponentProps<typeof SlotPrimitive.Slot>;
interface PortalProps extends SlotProps {
container?: Element | DocumentFragment | null;
}
function subscribe() {
return () => {};
}
function getSnapshot() {
return true;
}
function getServerSnapshot() {
return false;
}
function Portal(props: PortalProps) {
const { container: containerProp, ...portalProps } = props;
const mounted = React.useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot,
);
const container =
containerProp ?? (mounted ? globalThis.document?.body : null);
if (!container) return null;
return ReactDOM.createPortal(
<SlotPrimitive.Slot {...portalProps} />,
container,
);
}
export { Portal };
export type { PortalProps };"use client";
import { Slot as SlotPrimitive } from "radix-ui";
import * as React from "react";
import * as ReactDOM from "react-dom";
type SlotProps = React.ComponentProps<typeof SlotPrimitive.Slot>;
interface PortalProps extends SlotProps {
container?: Element | DocumentFragment | null;
}
function subscribe() {
return () => {};
}
function getSnapshot() {
return true;
}
function getServerSnapshot() {
return false;
}
function Portal(props: PortalProps) {
const { container: containerProp, ...portalProps } = props;
const mounted = React.useSyncExternalStore(
subscribe,
getSnapshot,
getServerSnapshot,
);
const container =
containerProp ?? (mounted ? globalThis.document?.body : null);
if (!container) return null;
return ReactDOM.createPortal(
<SlotPrimitive.Slot {...portalProps} />,
container,
);
}
export { Portal };
export type { PortalProps };Usage
import { Portal } from "@/components/portal"
export default function App() {
return (
<Portal>
{/* Content to be rendered in a different part of the DOM */}
<div>This will be rendered in the document body by default</div>
</Portal>
)
}Custom Container
Specify a target container for portal rendering:
import { Portal } from "@/components/portal"
export default function App() {
const containerRef = useRef<HTMLDivElement>(null)
return (
<>
<div ref={containerRef} />
<Portal container={containerRef.current}>
<div>This will be rendered in the custom container</div>
</Portal>
</>
)
}API Reference
Portal
A component that renders its children into a different part of the DOM tree using React's createPortal.
Props
Prop
Type