Typed, awaitable modal flows for React, with headless Motion presets and deterministic orchestration.
Documentation: https://sonnv1912.github.io/react-motion-modal/
- Input and result types inferred from one registry
- Awaitable
open()with explicit resolved/cancelled outcomes - Isolated systems instead of a process-wide singleton
stack,replace, andsingletonpolicies- Headless
dialog,drawer, andsheetpresets - Focus management, scroll locking, portals, and reduced motion
npm install react-motion-modal motion zustandImport the structural stylesheet once:
import 'react-motion-modal/style.css';import {
createModalSystem,
defineModal,
ModalProvider,
type ModalRenderProps,
motionPresets,
} from 'react-motion-modal';
type ConfirmInput = {
title: string;
};
function ConfirmModal({
input,
resolve,
cancel,
}: ModalRenderProps<ConfirmInput, boolean>) {
return (
<section className="dialog">
<h2>{input.title}</h2>
<button onClick={() => cancel()}>Cancel</button>
<button onClick={() => resolve(true)}>Confirm</button>
</section>
);
}
const confirm = defineModal({
component: ConfirmModal,
preset: motionPresets.dialog(),
policy: 'singleton',
});
export const modals = createModalSystem({ confirm });
export function App() {
return (
<>
<Routes />
<ModalProvider
system={modals}
defaultOptions={{
backdrop: {
style: { backgroundColor: 'rgb(0 0 0 / 40%)' },
},
}}
/>
</>
);
}Open the modal from application code and await its typed result:
const outcome = await modals.open('confirm', {
title: 'Delete this item?',
});
if (outcome.status === 'resolved' && outcome.value) {
await deleteItem();
}Cancellation resolves with a reason such as escape, backdrop,
programmatic, replaced, or provider-unmounted; it does not reject.
The package CSS owns structural positioning and overflow only. Your application
owns backdrop color, surface, spacing, shadow, and typography through
defaultOptions, definition defaults, open options, and modal component styles.
apps/library: published packageapps/example: runnable typed-flow examplesapps/document: Rspress documentation and interactive playgrounddocs/ideas/typed-motion-flows.md: v2 product direction
See the documentation migration guide when moving from the v1 global store API.