An opinionated toast component for React Native.
npm install react-native-sonnertoast("Hello!") anywhere
bash
npm install react-native-sonner
`
$3
`bash
npm install react-native-reanimated react-native-gesture-handler react-native-safe-area-context
Optional: for SVG icons
npm install react-native-svg
Optional: for haptic feedback
npm install expo-haptics
`
Make sure to follow the installation instructions for each peer dependency:
- react-native-reanimated
- react-native-gesture-handler
- react-native-safe-area-context
Quick Start
$3
`tsx
import { Toaster } from 'react-native-sonner';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
export default function App() {
return (
);
}
`
$3
`tsx
import { toast } from 'react-native-sonner';
function MyComponent() {
return (
title="Show Toast"
onPress={() => toast('Hello World!')}
/>
);
}
`
API
$3
`tsx
// Default toast
toast('Hello World!');
// With description
toast('Event created', {
description: 'Your event has been scheduled',
});
`
$3
`tsx
toast.success('Success!');
toast.error('Something went wrong');
toast.warning('Please check your input');
toast.info('New update available');
toast.loading('Uploading...');
`
$3
`tsx
toast.promise(
fetchData(),
{
loading: 'Loading data...',
success: (data) => Loaded ${data.count} items,
error: (err) => Error: ${err.message},
}
);
`
$3
`tsx
const toastId = toast.loading('Uploading...');
// Update the toast later
toast.update(toastId, {
type: 'success',
title: 'Upload complete!',
});
`
$3
`tsx
toast('File deleted', {
action: {
label: 'Undo',
onClick: () => restoreFile(),
},
cancel: {
label: 'Dismiss',
onClick: () => {},
},
});
`
$3
`tsx
// 10 seconds
toast('Long toast', { duration: 10000 });
// Never auto-dismiss
toast('Sticky toast', { duration: Infinity });
`
$3
Important toasts won't be hidden when the visible toast limit is reached:
`tsx
toast.error('Critical error!', { important: true });
`
$3
`tsx
const toastId = toast('Loading...');
// Dismiss specific toast
toast.dismiss(toastId);
// Dismiss all toasts
toast.dismiss();
`
$3
`tsx
toast('Hello', {
onDismiss: (t) => console.log('Toast dismissed:', t.id),
onAutoClose: (t) => console.log('Toast auto-closed:', t.id),
});
`
Toaster Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| position | Position | "top-center" | Toast position on screen |
| theme | "light" \| "dark" \| "system" | "system" | Color theme |
| duration | number | 4000 | Default duration in ms |
| visibleToasts | number | 3 | Max visible toasts |
| gap | number | 12 | Gap between toasts |
| offset | object | { top: 52, bottom: 52, left: 16, right: 16 } | Screen edge offsets |
| swipeToDismiss | boolean | true | Enable swipe gestures |
| swipeDirection | SwipeDirection \| SwipeDirection[] | ["left", "right"] | Swipe directions |
| pauseOnAppBackground | boolean | true | Pause timer when app backgrounds |
| richColors | boolean | false | Vibrant backgrounds |
| closeButton | boolean | false | Show close button |
| hapticFeedback | boolean | false | Enable haptic feedback |
| icons | ToastIcons | - | Custom icons |
| toastStyles | ToastStyles | - | Default styles for all toasts |
| variantStyles | VariantStyles | - | Per-variant style overrides |
| containerStyle | ViewStyle | - | Container style |
| animation | AnimationConfig | - | Animation configuration |
| toasterId | string | - | ID for multiple Toaster instances |
$3
- "top-left" / "top-center" / "top-right"
- "bottom-left" / "bottom-center" / "bottom-right"
$3
`tsx
animation={{
duration: 350, // Entry animation duration (ms)
exitDuration: 200, // Exit animation duration (ms)
useSpring: true, // Use spring animation for entry
damping: 18, // Spring damping
stiffness: 140, // Spring stiffness
mass: 1, // Spring mass
}}
/>
`
Per-toast animation:
`tsx
toast('Custom animation', {
animation: {
duration: 500,
useSpring: false,
},
});
`
Haptic Feedback
Enable haptic feedback for toast events (requires expo-haptics):
`tsx
`
Haptics are triggered on:
- Toast appearance (light impact, or notification type for success/warning/error)
- Action button press (medium impact)
- Cancel button press (light impact)
Accessibility
Toasts automatically announce to screen readers. Customize accessibility:
`tsx
toast('Order placed', {
accessibility: {
announceToScreenReader: true, // default: true
accessibilityLabel: 'Your order has been successfully placed',
},
});
`
Styling
$3
`tsx
toast('Styled toast', {
styles: {
container: { backgroundColor: '#1a1a1a' },
title: { color: '#fff', fontWeight: 'bold' },
description: { color: '#888' },
},
});
`
$3
`tsx
toastStyles={{
container: { borderRadius: 20 },
title: { fontFamily: 'Inter-Medium' },
}}
/>
`
$3
Style specific toast variants differently:
`tsx
variantStyles={{
success: {
container: { borderLeftWidth: 4, borderLeftColor: '#22c55e' },
title: { fontWeight: '600' },
},
error: {
container: { borderLeftWidth: 4, borderLeftColor: '#ef4444' },
},
warning: {
container: { backgroundColor: '#fef3c7' },
},
info: {
title: { color: '#1e40af' },
},
// 'loading' and 'default' variants also available
}}
/>
`
Style priority (lowest to highest):
1. Base styles (theme defaults)
2. toastStyles (applies to all toasts)
3. variantStyles[type] (per-variant overrides)
4. toast.styles (individual toast override)
$3
- container - Toast container
- content - Content wrapper
- title - Title text
- description - Description text
- actionButton - Action button
- actionButtonText - Action button text
- cancelButton - Cancel button
- cancelButtonText - Cancel button text
- closeButton - Close button
$3
`tsx
icons={{
success: ,
error: ,
warning: ,
info: ,
loading: ,
}}
/>
`
Per-toast icon:
`tsx
toast('Custom icon', {
icon: ,
});
`
Multiple Toaster Instances
Use toasterId to target specific Toaster instances:
`tsx
// In your layout
// Show toast in specific toaster
toast('Top notification', { toasterId: 'main' });
toast('Bottom notification', { toasterId: 'bottom' });
`
Hooks
$3
Access toast state in components:
`tsx
import { useToastState } from 'react-native-sonner';
function ToastCounter() {
const { toasts } = useToastState();
return Active toasts: {toasts.length} ;
}
`
Expo Support
React Native Sonner works with Expo out of the box:
`bash
npx expo install react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-svg expo-haptics
`
TypeScript
Full TypeScript support with exported types:
`tsx
import type {
ToastT,
ToastType,
Position,
ToasterProps,
AnimationConfig,
ToastStyles,
ToastIcons,
VariantStyles,
} from 'react-native-sonner';
``