2.1.7 • Published 5 months ago

async-modal-react v2.1.7

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

async-modal-react

async-modal-react.png

Version

Documentation - livemehere-dev-packs

This is a simple solution to create a modal in React using hooks and async/await.

Really simple, only what you have to do is wrap your root component with ModalProvider and use useModal hook.

Demo

demo.gif

Short Description

  • You can open modal by using promise function.
  • You can open multiple modals at the same time.
  • You can close all modals at the same time.
  • You can close modal by clicking outside of modal.
  • You can customize reject reason and resolve value.
  • Typescript support.
  • No dependencies except React.

Install

npm install async-modal-react

yarn add async-modal-react

Usage

Wrap your Root Component with ModalProvider

  • closeOnOutsideClick props is for close modal when click outside of modal(default: true).
  • disableBodyScrollWhenOpen props is for disable body scroll when modal is opened(default: true).
  • closeOnRouteChange props is for close all modals when route is changed(default: true).
import { ModalProvider } from "async-modal-react";

ReactDOM.createRoot(document.getElementById("root")).render(
    <ModalProvider
      closeOnOutsideClick={true}
      disableBodyScrollWhenOpen={true}
      closeOnRouteChange={true}
    >
      <App />
    </ModalProvider>,
);

Create Your Modal Component

  • Component that used for modal receive 3 props: close, resolve, reject.
  • resolve function will return value when using pushModal function.
  • close and reject function will reject when using pushModal function.
  • reject reason and resolve value can customize by yourself.

close estimated as reject

const ExampleModal = ({ close, resolve, reject }) => {
  return (
    <div>
      <h2>ExampleModal</h2>
      <button onClick={() => resolve(`resolve!`)}>RESOLVE</button>
      <button onClick={() => reject("reject T-T")}>REJECT</button>
      <button onClick={close}>Close</button>
    </div>
  );
};

export default ExampleModal;

Use Modal with Hooks

  • useModal hook return pushModal and closeAllModals function.
import ExampleModal from "./components/ExampleModal";
import { useModal } from "async-modal-react";

function App() {
    const { pushModal, closeAllModals } = useModal();

    const openModal = async () => {
        try {
            // resolve
            const result = await pushModal(ExampleModal);
            console.log(result);
        } catch (e) {
            // reject, close
            console.log(e);
        }
    };

    return (
        <div>
            <button onClick={openModal}>OPEN</button>
        </div>
    );
}

export default App;

Typescript Support

Modal Component Props

  • import ModalProps from async-modal-react/types/modal and extend your props interface.
export interface ModalProps {
    close: () => void;
    resolve: <Result = any>(v: Result) => void;
    reject: <Reason = any>(reason: Reason) => void;
}
import { ModalProps } from "async-modal-react/types/modal";

export interface ExampleProps extends ModalProps {
  name: string;
}

const ExampleModal = ({ close, resolve, reject, name }: ExampleProps) => {
  return (
    <div>
      <h2>ExampleModal</h2>
      <button onClick={() => resolve(`resolve! ${name}`)}>RESOLVE</button>
      <button onClick={() => reject("reject T-T")}>REJECT</button>
      <button onClick={close}>Close</button>
    </div>
  );
};

export default ExampleModal;

Hooks

  • resolve type can be set by generic type.
  • second generic type is for modal props. (most case is not necessary)
  • pushModal function return Promise<ReturnType>.
  • options are higher priority than ModalProvider props. You can set individually.
 const result = await pushModal<ReturnType, Props>(
    ExampleModal, // Modal Component
    {}, // ExampleModal props
    { // Individual options
        onClickOutsideClose: true,
        disableScroll: true,
        enableInsideScroll: true, // use this when global disableScroll is true but you want to enable scroll in this modal.
    },
);

Customizing

Modal root element

 <div
      id="modal-root"
      style={{
        position: "fixed",
        top: 0,
        left: 0,
        width: "100%",
        height: "100%",
        background: "rgba(0, 0, 0, 0.5)",
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
      }}
    >
  {children}
</div>

customize #modal-root element with global css.

#modal-root {
  background: blue !important;
}

Multiple modals style

By Default modal root element display children with flex and justifyContent: center, alignItems: center. So if there are more than two modal is opened, they will be displayed in just like a flex.
if you want to stack layout, your modal component should have position: absolute style.

// ...
return (
    <div
        style={{
            background: "white",
            position: "absolute",
        }}
    >
        <h2>ExampleModal</h2>
        <button onClick={() => resolve(`resolve! ${name}`)}>RESOLVE</button>
        <button onClick={() => reject("reject T-T")}>REJECT</button>
        <button onClick={close}>Close</button>
        <button onClick={openModal}>OPEN</button>
    </div>
);

If Modal Component not have position: absolute look like.

multi-modal-flex.png

If Modal Component have position: absolute look like.

  • Two modals are stacked

multi-modal-absolute.png

2.1.7

5 months ago

2.1.2

5 months ago

2.1.1

5 months ago

2.1.4

5 months ago

2.1.3

5 months ago

2.1.6

5 months ago

2.1.5

5 months ago

2.0.9

5 months ago

2.0.8

5 months ago

2.1.0

5 months ago

2.0.7

5 months ago

1.3.1

6 months ago

1.3.0

6 months ago

2.0.3

6 months ago

2.0.2

6 months ago

2.0.5

6 months ago

2.0.4

6 months ago

2.0.6

6 months ago

2.0.1

6 months ago

2.0.0

6 months ago

1.2.9

6 months ago

1.2.8

6 months ago

1.2.7

6 months ago

1.2.6

6 months ago

1.2.5

6 months ago

1.2.0

6 months ago

1.2.4

6 months ago

1.2.3

6 months ago

1.2.2

6 months ago

1.2.1

6 months ago

1.1.0

7 months ago

1.0.1

7 months ago

1.0.0

7 months ago