Need help with react-cool-portal?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

wellyshen
682 Stars 18 Forks MIT License 1.5K Commits 14 Opened issues

Description

😎 🍒 React hook for Portals, which renders modals, dropdowns, tooltips etc. to <body> or else.

Services available

!
?

Need anything else?

Contributors list

# 12,736
React
CSS
interse...
HTML
340 commits
# 48,321
Webpack
reactjs
Sass
pdf-doc...
1 commit
# 291,205
Redis
Shell
Objecti...
nextjs
1 commit

REACT COOL PORTAL

This is a React hook for Portals. It helps you render children into a DOM node that exists outside the DOM hierarchy of the parent component. From now on you will never need to struggle with modals, dropdowns, tooltips etc. Check the features section out to learn more. Hope you guys 👍🏻 it.

❤️ it? ⭐️ it on GitHub or Tweet about it.

build status coverage status npm version npm downloads npm downloads gzip size All Contributors PRs welcome Twitter URL

Live Demo

demo

⚡️ Try yourself: https://react-cool-portal.netlify.app

Features

Requirement

To use

react-cool-portal
, you must use
[email protected]
or greater which includes hooks.

Installation

This package is distributed via npm.

$ yarn add react-cool-portal
# or
$ npm install --save react-cool-portal

Usage

Here are some minimal examples of how does it work. You can learn more about it by checking the API out.

Basic Use Case

Inserts an element or component into a different location in the DOM.

import usePortal from "react-cool-portal";

const App = () => { const { Portal } = usePortal();

return (

Wow! I am rendered outside the DOM hierarchy of my parent component.

); };

By default, the children of portal is rendered into

of
. You can specify the DOM element you want through the 
containerId
option.
import usePortal from "react-cool-portal";

const App = () => { const { Portal } = usePortal({ containerId: "my-portal-root" });

return (

Now I am rendered into the specify element (id="my-portal-root").

); };

Note: If the container element doesn't exist, we will create it for you.

Use with State

react-cool-portal
provides many useful features, which enable you to build a component with state. For instance, modal, dropdown, tooltip, and so on.

Edit usePortal

import usePortal from "react-cool-portal";

const App = () => { const { Portal, isShow, show, hide, toggle } = usePortal({ defaultShow: false, // The default visibility of portal, default is true onShow: (e) => { // Triggered when portal is shown // The event object will be the parameter of show(e?) }, onHide: (e) => { // Triggered when portal is hidden // The event object will be the parameter of hide(e?), it maybe MouseEvent (on clicks outside) or KeyboardEvent (press ESC key) }, });

return (

Open Modal Close Modal {isShow ? "Close" : "Open"} Modal
Modal title

Modal body text goes here.

); };

🧹 When no element in the container, we will remove it for you to avoid DOM mess. However, the feature can be turn off via the autoRemoveContainer option.

The above example shows how easy you can handle the visibility of your component. You may ask how to handle the visibility with animations? No worries, you can disable the built-in

show/hide
functions by setting the
internalShowHide
option to
false
then handling the visibility of your component via the
isShow
state.

Edit usePortal with Animation

import usePortal from "react-cool-portal";

const App = () => { const { Portal, isShow, show, hide, toggle } = usePortal({ defaultShow: false, internalShowHide: false, // Disable the built-in show/hide portal functions, default is true onShow: (e) => { // Triggered when isShow is set to true }, onHide: (e) => { // Triggered when isShow is set to false }, });

return (

Open Modal Close Modal {isShow ? "Close" : "Open"} Modal
Modal title

Modal body text goes here.

); };

Besides that, you can also handle the visibility of your component via React animation events or transition events like what I did for the demo app.

Build Your Customized Hook

Are you tired to write the same code over and over again? It's time to build your own hook based on

react-cool-portal
then use it wherever you want.
import { useCallback } from "react";
import usePortal from "react-cool-portal";

// Customize your hook based on react-cool-portal const useModal = (options = {}) => { const { Portal, isShow, ...rest } = usePortal({ ...options, defaultShow: false, internalShowHide: false, });

const Modal = useCallback( ({ children }) => (

{children}
), [isShow] );

return { Modal, isShow, ...rest }; };

// Use it wherever you want const App = () => { const { Modal, show, hide } = useModal();

return (

Open Modal Close Modal
Modal title

Modal body text goes here.

); };

One problem of the above example is that CSS transition/animation will be cut off due to the re-creating of the

Portal
component. So if you want to apply transitions or animations to the wrapped element of the customized hook. The
isShow
need to be passed from the props.

Edit usePortal - custom

const useModal = (options = {}) => {
  const { Portal, ...rest } = usePortal({
    ...options,
    defaultShow: false,
    internalShowHide: false,
  });

const Modal = useCallback( // Pass the isShow from props to prevent CSS transition/animation to be cut off ({ isShow, children }) => (

{children}
), [] );

return { Modal, ...rest }; };

Conditionally ESC or Click Outside to Hide

ESC or click outside to hide is an out-of-box feature of

react-cool-portal
. However, you can conditionally hide the portal based on the presence or absence of an element. Here we take a nested modal as the example:
import usePortal from "react-cool-portal";

const App = () => { const [showChildModal, setShowChildModal] = useState(false); const { Portal: ChildModal, show } = usePortal({ defaultShow: false }); const { Portal: ParentModal } = usePortal({ // Provide the class name of the child modal, so the parent modal will only be hidden after the child modal is hidden escToHide: ["child-modal"], // The same as above clickOutsideToHide: ["child-modal"], });

return (

I'm parent modal.

Open Child Modal

I'm child modal.

); };

API

const returnObj = usePortal(parameterObj);

Return object

It's returned with the following properties.

| Key | Type | Default | Description | | ------ | --------- | ------- | ----------------------------------------------------------------------------------------------- | | Portal | component | | Renders children into a DOM node that exists outside the DOM hierarchy of the parent component. | | isShow | boolean |

false
| The show/hide state of portal. | | show | function | | To show the portal or set the
isShow
to
true
. | | hide | function | | To hide the portal or set the
isShow
to
false
. | | toggle | function | | To toggle (show/hide) the portal or set the
isShow
to
true/false
. |

Parameter object (optional)

When use

react-cool-portal
you can configure the following options via the parameter.

| Key | Type | Default | Description | | ------------------- | ---------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | containerId | string |

react-cool-portal
| You can specify your own container id from an existing DOM element or let this hook automatically creates it for you. | | autoRemoveContainer | boolean |
true
| Enable/disable the built-in automatically remove container function. | | defaultShow | boolean |
true
| The initial show/hide state of the portal. | | clickOutsideToHide | boolean | array |
true
| Hide the portal by clicking outside of it. You can also provide class name(s) for conditionally hide. | | escToHide | boolean | array |
true
| Hide the portal by pressing ESC key. You can also provide class name(s) for conditionally hide. | | internalShowHide | boolean |
true
| Enable/disable the built-in
show/hide
portal functions, which gives you a flexible way to handle your portal. | | onShow | function | | Triggered when portal is shown or the
isShow
set to
true
. | | onHide | function | | Triggered when portal is hidden or the
isShow
set to
false
. |

Articles / Blog Posts

💡 If you have written any blog post or article about

react-cool-portal
, please open a PR to add it here.

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Welly

💻 📖 🚧

Dawid Karabin

📖

Honza Stepanovsky

🐛

This project follows the all-contributors specification. Contributions of any kind welcome!

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.