Skip to content

Commit 26a5f2f

Browse files
committed
add rough docs
1 parent b9b0995 commit 26a5f2f

File tree

3 files changed

+133
-5
lines changed

3 files changed

+133
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
{/* Copyright 2025 Adobe. All rights reserved.
2+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
3+
you may not use this file except in compliance with the License. You may obtain a copy
4+
of the License at http://www.apache.org/licenses/LICENSE-2.0
5+
Unless required by applicable law or agreed to in writing, software distributed under
6+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
7+
OF ANY KIND, either express or implied. See the License for the specific language
8+
governing permissions and limitations under the License. */}
9+
10+
import {Layout} from '@react-spectrum/docs';
11+
export default Layout;
12+
13+
import docs from 'docs:@react-aria/overlays';
14+
import {HeaderInfo, PropTable, FunctionAPI, PageDescription} from '@react-spectrum/docs';
15+
import packageData from '@react-aria/overlays/package.json';
16+
17+
---
18+
category: Utilities
19+
keywords: [overlays, portals]
20+
---
21+
22+
# PortalProvider
23+
24+
<PageDescription>{docs.exports.UNSTABLE_PortalProvider.description}</PageDescription>
25+
26+
<HeaderInfo
27+
packageData={packageData}
28+
componentNames={['UNSTABLE_PortalProvider', 'useUNSTABLE_PortalContext']} />
29+
30+
## Introduction
31+
32+
`UNSTABLE_PortalProvider` is a utility wrapper component that can be used to set where components like
33+
Modals, Popovers, Toasts, and Tooltips will portal their overlay element to. This is typically used when
34+
your app is already portalling other elements to a location other than the `document.body` and thus requires
35+
your React Aria components to send their overlays to the same container.
36+
37+
## Props
38+
39+
<PropTable links={docs.links} component={docs.exports.UNSTABLE_PortalProvider} />
40+
41+
## Example
42+
43+
The example below shows how you can use `UNSTABLE_PortalProvider` to portal your Toasts to an arbitrary container. Note that
44+
the Toast in this example is taken directly from the [React Aria Components Toast documentation](Toast.html#example), please visit that page for
45+
a detailed explanation of its implementation.
46+
47+
```tsx example
48+
import {UNSTABLE_PortalProvider} from '@react-aria/overlays';
49+
///- begin collapse -///
50+
import {UNSTABLE_ToastRegion as ToastRegion, UNSTABLE_Toast as Toast, UNSTABLE_ToastQueue as ToastQueue, UNSTABLE_ToastContent as ToastContent, Button, Text} from 'react-aria-components';
51+
52+
53+
// Define the type for your toast content.
54+
interface MyToastContent {
55+
title: string,
56+
description?: string
57+
}
58+
59+
// Create a global ToastQueue.
60+
const queue = new ToastQueue<MyToastContent>();
61+
62+
function MyToastRegion() {
63+
return (
64+
<ToastRegion queue={queue}>
65+
{({toast}) => (
66+
<Toast toast={toast}>
67+
<ToastContent>
68+
<Text slot="title">{toast.content.title}</Text>
69+
<Text slot="description">{toast.content.description}</Text>
70+
</ToastContent>
71+
<Button slot="close">x</Button>
72+
</Toast>
73+
)}
74+
</ToastRegion>
75+
76+
);
77+
}
78+
///- end collapse -///
79+
80+
// See the above Toast docs link for the ToastRegion implementation
81+
function App() {
82+
let container = React.useRef(null);
83+
return (
84+
<>
85+
<UNSTABLE_PortalProvider getContainer={() => container.current}>
86+
<MyToastRegion />
87+
<Button
88+
onPress={() => queue.add({
89+
title: 'Toast complete!',
90+
description: 'Great success.'
91+
})}>
92+
Toast
93+
</Button>
94+
</UNSTABLE_PortalProvider>
95+
<div ref={container} style={{height: '70px', width: '200px', overflow: 'auto'}}>
96+
Toasts are portalled here!
97+
</div>
98+
</>
99+
);
100+
}
101+
102+
<App />
103+
```
104+
105+
## Contexts
106+
107+
The `getContainer` set by the nearest PortalProvider can be accessed by calling `useUNSTABLE_PortalContext`. This can be
108+
used by custom overlay components to ensure that they are also being consistently portalled throughout your app.
109+
110+
<FunctionAPI links={docs.links} function={docs.exports.useUNSTABLE_PortalContext} />
111+
112+
```tsx
113+
import {useUNSTABLE_PortalContext} from '@react-aria/overlays';
114+
115+
function MyOverlay(props) {
116+
let {children} = props;
117+
let {getContainer} = useUNSTABLE_PortalContext();
118+
return ReactDOM.createPortal(children, getContainer());
119+
}
120+
```

packages/@react-aria/overlays/src/PortalProvider.tsx

+12-5
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,20 @@
1313
import React, {createContext, ReactNode, useContext} from 'react';
1414

1515
export interface PortalProviderProps {
16-
/* Should return the element where we should portal to. Can clear the context by passing null. */
17-
getContainer?: () => HTMLElement | null
16+
/** Should return the element where we should portal to. Can clear the context by passing null. */
17+
getContainer?: () => HTMLElement | null,
18+
/** The content of the PortalProvider. Should contain all children that want to portal their overlays to the element returned by the provided getContainer(). */
19+
children: ReactNode
1820
}
1921

20-
export const PortalContext = createContext<PortalProviderProps>({});
22+
export interface PortalProviderContextValue extends Omit<PortalProviderProps, 'children'>{};
2123

22-
export function UNSTABLE_PortalProvider(props: PortalProviderProps & {children: ReactNode}): ReactNode {
24+
export const PortalContext = createContext<PortalProviderContextValue>({});
25+
26+
/**
27+
* Sets the portal container for all overlay elements rendered by its children.
28+
*/
29+
export function UNSTABLE_PortalProvider(props: PortalProviderProps): ReactNode {
2330
let {getContainer} = props;
2431
let {getContainer: ctxGetContainer} = useUNSTABLE_PortalContext();
2532
return (
@@ -29,6 +36,6 @@ export function UNSTABLE_PortalProvider(props: PortalProviderProps & {children:
2936
);
3037
}
3138

32-
export function useUNSTABLE_PortalContext(): PortalProviderProps {
39+
export function useUNSTABLE_PortalContext(): PortalProviderContextValue {
3340
return useContext(PortalContext) ?? {};
3441
}

packages/@react-aria/overlays/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ export type {AriaPopoverProps, PopoverAria} from './usePopover';
3030
export type {AriaModalOverlayProps, ModalOverlayAria} from './useModalOverlay';
3131
export type {OverlayProps} from './Overlay';
3232
export type {Placement, PlacementAxis, PositionProps} from '@react-types/overlays';
33+
export type {PortalProviderProps, PortalProviderContextValue} from './PortalProvider';

0 commit comments

Comments
 (0)