Show promised based modal imperatively using hook for React.js.
This is basically the same repo as Harasz/use-async-modal except now you can pass props to the modal upon opening! 😎
You can install package using npm or yarn:
npm i @cmckenna/use-async-modal
yarn add @cmckenna/use-async-modal
First, we will need a component modal to show:
export const Dialog = ({ onResolve, title, acceptBtnText, cancelBtnText }) => {
return (
<div>
<button onClick={() => onResolve({ accepted: true })}>{acceptBtnText ?? 'Accept'}</button>
<button onClick={() => onResolve({ accepted: false })}>{cancelBtnText ?? 'Cancel'}</button>
</div>
);
};
Then in the component we want to open a modal, we need to use useModal
hook from use-async-modal
package. It is necessary to add only once the ModalContainer
component from use-async-modal
package as high as possible in your app.
import { useModal, ModalContainer } from "use-async-modal";
import { Dialog } from "./Dialog";
export const App = () => {
const showModal = useModal({
Component: Dialog,
/*
Type: Function
Desc: It will be invoked when the window is closed.
Options:
- resolved: value passed to onResolve.
*/
onClose: ({ resolved }) => {},
/*
Type: Function
Desc: It will be invoked when the window is opened.
Options:
- containerId: string containing attribute id for overlay in DOM,
- containerRef: HTMLDivElement ref to overlay.
*/
onOpen: ({ containerId, containerRef }) => {},
/*
Type: Object
Desc: Inline styles applied to overlay.
*/
overlayStyles: {
backgroundColor: "red",
margin: "1px"
},
/*
Type: String
Desc: Classes to be applied to overlay.
Accept multiple classes names separated
by space ex. "px-1 mx-2 bg-green".
*/
overlayClassName: "px-1",
/*
Type: Bool
Desc: If set to true, dialog will close
after escape key down.
Default value: false
*/
closeOnEsc: true,
/*
Type: Bool
Desc: If set to true, the dialog will
close when the overlay was clicked.
Default value: false
*/
closeOnOverlayClick: true,
/*
Type: same as onResolve
Desc: The value passed to the onResolve
function when the dialog was closed with
the Escape key or an overlay click.
*/
defaultResolved: { accepted: false },
/*
Type: String
Desc: Classes to be applied to overlay
after closing. Accept multiple classes
names separated by space.
*/
overlayClassNameOnClose: "fade-out",
/*
Type: same as onResolve
Desc: Classes to be applied to overlay
when open. Accept multiple classes names
separated by space.
*/
overlayClassNameOnOpen: "fade-in",
/*
Type: Number (unit: ms)
Desc: Delayed closing time expressed
in milliseconds.
*/
closeTimeoutMs: 1000,
/*
Type: Bool (default: true)
Desc: Locking the scrollbar on the page
when the model is open.
*/
blockBodyScroll: true,
});
async function handleClick() {
const status = await showModal({
title: 'Hello World',
acceptBtnText: 'Ok',
cancelBtnText: 'Deny'
});
// { accepted: true } or { accepted: false }
}
/*
necessary to add <ModalContainer /> once at the top of app
*/
return (
<>
<ModalContainer />
<button onClick={handleClick}>Open dialog</button>
</>
);
};
As a hook argument we pass an object with properties Component
which is our modal component. showModal
is a function that return promise with our value passed to function onResolve
in Dialog
component.
More examples of usage.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.