Full usage guide and API reference for react-native-overlay-flow.
For installation and a quick start, see the README.
- Opening overlays
- Asking for a result
- Replacing the current overlay
- Queueing an overlay
- Closing overlays
- Close lifecycle
- Bottom sheets and custom overlays
- API reference
overlay.open('payment-success', {
amount: 12000,
transactionId: 'TX-123',
});If another overlay is already visible, the new one appears above it.
overlay.open('payment-success', {
amount: 12000,
transactionId: 'TX-123',
});
overlay.open('confirm-delete', {
title: 'Delete transaction?',
});Use ask() when an overlay should return a value.
const confirmed = await overlay.ask('confirm-delete', {
title: 'Delete this item?',
description: 'This action cannot be undone.',
});
if (confirmed) {
await deleteItem();
}Inside the overlay component, call resolve().
function ConfirmDeleteOverlay({ payload, resolve }: Props) {
return (
<ConfirmModal
title={payload.title}
description={payload.description}
onCancel={() => resolve(false)}
onConfirm={() => resolve(true)}
/>
);
}Use replace() when the current overlay should become another one.
overlay.open('global-loader', {
message: 'Processing payment...',
});
try {
const result = await paymentApi.pay();
overlay.replace('payment-success', {
amount: result.amount,
transactionId: result.transactionId,
});
} catch {
overlay.replace('payment-error', {
message: 'Payment failed',
});
}Useful for flows like:
loader → success
loader → error
confirm → processingUse enqueue() when an overlay should wait until the current overlays are closed.
overlay.open('payment-success', {
amount: 12000,
transactionId: 'TX-123',
});
overlay.enqueue('rate-app');Result:
1. payment-success appears
2. user closes payment-success
3. rate-app appearsClose the top overlay:
overlay.closeTop();Close a specific overlay by id:
const id = overlay.open('payment-success', {
amount: 12000,
transactionId: 'TX-123',
});
overlay.close(id);Close all overlays:
overlay.closeAll();Overlays are not removed immediately when they close.
Instead, they receive a status:
type OverlayStatus = 'opening' | 'open' | 'closing';When status becomes "closing", the overlay can run its exit animation.
After the animation finishes, call:
onExitComplete();Example:
function AnimatedOverlay({
status,
close,
onExitComplete,
}: OverlayComponentProps<any>) {
return (
<MyAnimatedModal
visible={status !== 'closing'}
onClose={close}
onExitComplete={onExitComplete}
/>
);
}If onExitComplete() is not called, the overlay can be removed automatically after exitDuration.
The library does not provide a bottom sheet component.
Use your own bottom sheet library, such as @gorhom/bottom-sheet, and register the sheet as an overlay.
import { useEffect, useRef } from 'react';
import { BottomSheetModal } from '@gorhom/bottom-sheet';
import type { OverlayComponentProps } from 'react-native-overlay-flow';
export function FilterSheetOverlay({
payload,
status,
close,
onExitComplete,
}: OverlayComponentProps<any>) {
const ref = useRef<BottomSheetModal>(null);
useEffect(() => {
ref.current?.present();
}, []);
useEffect(() => {
if (status === 'closing') {
ref.current?.dismiss();
}
}, [status]);
return (
<BottomSheetModal ref={ref} onDismiss={onExitComplete}>
<FilterContent payload={payload} onApply={close} />
</BottomSheetModal>
);
}Then open it normally:
overlay.open('filter-sheet', {
initialCategory: 'phones',
});The same pattern applies to toasts, custom drawers, or any other overlay type — the library only needs a component to mount.
<OverlayProvider registry={overlayRegistry}>
<App />
<OverlayHost />
</OverlayProvider>| Component | Role |
|---|---|
OverlayProvider |
Stores the overlay state. |
OverlayHost |
Renders the active overlays. |
const overlay = useOverlay<AppOverlays>();overlay.open(name, payload?, options?);
overlay.ask(name, payload?, options?);
overlay.replace(name, payload?, options?);
overlay.enqueue(name, payload?, options?);
overlay.close(id);
overlay.closeTop();
overlay.closeAll();type OverlayOptions = {
dismissible?: boolean;
closeOnBack?: boolean;
exitDuration?: number;
};