react-useportal-test
Version:
🌀 React hook for Portals
139 lines (120 loc) • 4.66 kB
Markdown
<h1 align="center">usePortal</h1>
<p align="center">🌀 React hook for using Portals</p>
<p align="center">
<a href="https://github.com/alex-cory/react-useportal/pulls">
<img src="https://camo.githubusercontent.com/d4e0f63e9613ee474a7dfdc23c240b9795712c96/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5052732d77656c636f6d652d627269676874677265656e2e737667" />
</a>
<a href="https://www.npmjs.com/package/react-useportal">
<img src="https://img.shields.io/npm/dt/react-useportal.svg" />
</a>
</p>
Need to make dropdowns, lightboxes/modals/dialogs, global message notifications, or tooltips in React? React Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component ([react docs](https://reactjs.org/docs/portals.html)).
<p align="center">
<a href="https://github.com/alex-cory/react-useportal">
<img src="https://github.com/alex-cory/react-useportal/raw/master/usePortal.gif" />
</a>
</p>
### Examples
- <a target="_blank" rel="noopener noreferrer" href='https://codesandbox.io/s/w6jp7z4pkk'>Code Sandbox Example</a>
Installation
------------
```shell
yarn add react react-dom react-useportal
```
Usage
-----
### Stateless
```jsx
import usePortal from 'react-useportal'
<Portal>
This text is portaled at the end of document.body!
</Portal>
<Portal bindTo={document && document.getElementById('san-francisco')}>
This text is portaled into San Francisco!
</Portal>
```
### With State
```jsx
import usePortal from 'react-useportal'
const App = () => {
var { openPortal, closePortal, isOpen, Portal } = usePortal()
// want to use array destructuring? You can do that too
var [openPortal, closePortal, isOpen, Portal] = usePortal()
return (
<>
<button onClick={openPortal}>
Open Portal
</button>
{isOpen && (
<Portal>
<p>
This Portal handles its own state.{' '}
<button onClick={closePortal}>Close me!</button>, hit ESC or
click outside of me.
</p>
</Portal>
)}
</>
)
}
```
### Need Animations?
```jsx
import usePortal from 'react-useportal'
const App = () => {
const { openPortal, closePortal, isOpen, Portal } = usePortal()
return (
<>
<button onClick={openPortal}>
Open Portal
</button>
<Portal>
<p className={isOpen ? 'animateIn' : 'animateOut'}>
This Portal handles its own state.{' '}
<button onClick={closePortal}>Close me!</button>, hit ESC or
click outside of me.
</p>
</Portal>
</>
)
}
```
**Make sure you are passing the html synthetic event to the `openPortal`. i.e. `onClick={e => openPortal(e)}`**
Options
-----
| Option | Description |
| --------------------- | ---------------------------------------------------------------------------------------- |
| `closeOnOutsideClick` | This will close the portal when not clicking within the portal. Default is `true` |
| `closeOnEsc` | This will allow you to hit ESC and it will close the modal. Default is `true` |
| `renderBelowClickedElement` | This will put the portal right under the element that you click on. Great for dropdowns. Required to pass event to openPortal `onClick={event => openPortal(event)}` |
| `bindTo` | This is the DOM node you want to attach the portal to. By default it attaches to `document.body` |
| `isOpen` | This will be the default for the portal. Default is `false` |
### Option Usage
```js
const {
openPortal,
closePortal,
togglePortal,
isOpen,
Portal
} = usePortal({
closeOnOutsideClick: true,
closeOnEsc: true,
renderBelowClickedElement, // appear directly under the clicked element/node in the DOM
bindTo, // attach the portal to this node in the DOM
isOpen: false,
})
```
Todos
------
- [ ] add support for popup windows [resource 1](https://javascript.info/popup-windows) [resource 2](https://hackernoon.com/using-a-react-16-portal-to-do-something-cool-2a2d627b0202). Maybe something like
```jsx
const { openPortal, closePortal, isOpen, Portal } = usePortal({
popup: ['', '', 'width=600,height=400,left=200,top=200']
})
// window.open('', '', 'width=600,height=400,left=200,top=200')
```
- [ ] make isomorphic
- [ ] make work without requiring the html synthetic event & document when you are required to have it and when you are not
- [ ] clean up code
- [ ] make work with both `[openPortal, closePortal, ..., Portal] = usePortal()` and like current object destructuring