Modals you can await.
A headless, zero-dependency modal stack for React. Open a modal like you call a function, and get its answer back.
npm install react-easy-modalsconst modals = useModals();async function deleteProject() { const answer = await modals.open(ConfirmDelete, { project: "acme-web", }); if (answer === "delete") removeProject();}Run it: the modal opens, and the promise waits for its answer.
Three steps to your first modal
No open state, no trigger component, no callback props.
- 1
Install
One package, no dependencies besides React.
npm install react-easy-modals - 2
Add the provider
It renders the stack at the root of your app.
<ModalProvider> <App /> </ModalProvider> - 3
Open a modal
Any component works. Its close value is the result.
const ok = await modals.open(Confirm);
The rest of the stack, when you need it
Every feature below is running live. Open the demos and try them.
A new modal hides the one below it until it closes.
open modals: 0modals.open(Step1);
modals.open(Step2); // Step1 waits underneath
modals.close(); // back to Step1Already on shadcn/ui?
Add a Modal built on your Dialog. The registry serves the Radix or Base UI version to match the style in your components.json.
npx shadcn@latest add @react-easy-modals/modalRemoved: <Dialog open={open} onOpenChange={setOpen}>Removed: <DialogContent>…</DialogContent>Removed: </Dialog>Added: const result = await modals.open(MyModal);