rn-themed-alert
v0.2.0
Published
A themeable, animated, promise-based alert/confirm/prompt modal for React Native, plus toast notifications and a loading/progress overlay — a cross-platform replacement for Alert.alert / Alert.prompt.
Maintainers
Readme
rn-themed-alert
A themeable, animated, promise-based alert / confirm / prompt for React
Native — one component to replace Alert.alert, Alert.prompt (iOS-only),
and every one-off custom modal you've hand-rolled.
- 🎨 Fully themeable — colors, radius, font, dark mode included
- ⚡ Promise-based —
await confirm(...)instead of callback hell - 🧵 Queued — calling alert/confirm/prompt back-to-back shows them one at a time in order, never stacked
- ✍️ Prompt with validation — inline error text, no separate modal needed
- 🎬 Animated — spring scale-in, fade, tap feedback on buttons
- 🌗 5 variants — default, success, error, warning, info
- 📱 Cross-platform — same API and look on iOS and Android (unlike
Alert.prompt, which is iOS-only)
Install
npm install rn-themed-alertNo extra native dependencies — built on Modal, Animated, and TextInput
from react-native core.
Setup
Wrap your app once, near the root:
import { ThemedAlertProvider } from 'rn-themed-alert';
export default function App() {
return (
<ThemedAlertProvider>
<YourApp />
</ThemedAlertProvider>
);
}Usage
import { useAlert } from 'rn-themed-alert';
function SettingsScreen() {
const { alert, confirm, prompt } = useAlert();
const onDelete = async () => {
const ok = await confirm({
title: 'Delete account?',
message: 'This cannot be undone.',
variant: 'error',
confirmText: 'Delete',
destructive: true,
});
if (!ok) return;
// ... delete ...
await alert({ title: 'Account deleted', variant: 'success' });
};
const onRename = async () => {
const name = await prompt({
title: 'Rename chat',
placeholder: 'Chat name',
defaultValue: 'Weekend trip',
validate: (v) => (v.trim().length === 0 ? 'Name cannot be empty' : null),
});
if (name === null) return; // cancelled
// ... save `name` ...
};
return (/* buttons calling onDelete / onRename */);
}Theming
Pass a partial theme override to the provider — only override what you need, the rest falls back to sensible defaults:
import { ThemedAlertProvider, defaultDarkTheme } from 'rn-themed-alert';
<ThemedAlertProvider theme={{ primaryButtonBg: '#7C5CFF', borderRadius: 28 }}>
<YourApp />
</ThemedAlertProvider>
// or go full dark mode:
<ThemedAlertProvider theme={defaultDarkTheme}>
<YourApp />
</ThemedAlertProvider>Tie it to your app's own theme context by passing your current theme's
colors into theme={{ ... }} wherever you already read them (e.g. in your
root layout, alongside your existing useTheme()).
API
<ThemedAlertProvider theme?={Partial<AlertTheme>}>
Mount once near your app root. Renders the modal portal.
useAlert()
Returns { alert, confirm, prompt }.
alert(options): Promise<void>
| Option | Type | Default |
|---|---|---|
| title | string | required |
| message | string | — |
| variant | 'default' \| 'success' \| 'error' \| 'warning' \| 'info' | 'default' |
| buttonText | string | 'OK' |
| dismissOnBackdropPress | boolean | true |
confirm(options): Promise<boolean>
Same base options, plus:
| confirmText | string | 'Confirm' |
| cancelText | string | 'Cancel' |
| destructive | boolean | false — styles confirm button red |
Resolves true if confirmed, false if cancelled or backdrop-dismissed.
prompt(options): Promise<string | null>
Same base options, plus:
| placeholder | string | — |
| defaultValue | string | '' |
| secureTextEntry | boolean | false |
| keyboardType | 'default' \| 'email-address' \| 'numeric' \| 'phone-pad' | 'default' |
| validate | (value: string) => string \| null \| undefined | — return an error string to block confirm |
Resolves the entered string, or null if cancelled.
License
MIT
