Magic Modallatest

Introduction

Build awaitable, type-safe modal flows for web, iOS, and Android.

Magic Modal turns a modal interaction into a typed async result. Mount one MagicModalPortal near the application root. Call show() from an event, effect, service, or any other async flow.

const result = await magicModal.show<ConfirmationResult>(ConfirmationModal, {
  accessibilityLabel: "Confirm purchase",
});

if (
  result.reason === MagicModalHideReason.INTENTIONAL_HIDE &&
  result.data.confirmed
) {
  completePurchase();
}

show() returns a handle that is itself the promise, carrying modalID, update, and hide for the entry it opened. The older const { promise } = magicModal.show(...) form still works: promise is an alias of the handle.

Core model

The mental model

  1. MagicModalPortal owns the modal stack. Mount it once.
  2. magicModal.show pushes one entry and returns an awaitable handle.
  3. useMagicModal().hide closes that entry with typed data.
  4. The promise resolves to HideReturn<T>, including the close reason.

Every show() call creates an independent stack entry. Opening another modal keeps the earlier entry and its promise in place.

Application modals

Magic Modal handles discrete interactions and async decisions. Snap points and nested bottom-sheet scrolling are outside its scope.

Set up a runtime

Choose the installation for the target. Mount the portal near the application root.

On this page