Star 历史趋势
数据来源: GitHub API · 生成自 Stargazers.cn
README.md

react-native-pretty-toast

https://github.com/user-attachments/assets/b59a22b7-913d-4bc3-9629-5549de5e28d4

A toast library that actually uses the hardware cutout. The pill morphs out of the Dynamic Island on iPhone and out of the camera cutout on Android, expands to fit your content, and collapses back in — with sensible slide-in fallbacks on devices without a cutout.

  • Cutout-anchored toast on both platforms — Dynamic Island on iPhones and DisplayCutout hole-punch on Android, detected automatically from system insets
  • Backdrop-aware outline — samples the content underneath and flips the stroke between accent and neutral so the pill stays legible on any background
  • One API, three platforms — iOS, Android, and Web share the same toast.show() call
  • Sonner-style ergonomicstoast.promise(), toast.update(), and success / error / info / warning / loading shorthands
  • Works outside React — call toast.show() from redux middleware, fetch interceptors, or anywhere else; no useContext required
  • Interactive out of the box — swipe-up to dismiss, tappable pill, and a trailing action button for undo/retry
  • Production-minded — FIFO queue with maxQueue cap, { force: true } for critical interrupts, full lifecycle hooks (onShow, onHide, onAutoDismiss)
  • Accessible by default — screen-reader announcements on native (AccessibilityInfo) and web (aria-live), overridable per-toast
  • Fabric / New Architecture only

Installation

npm install react-native-pretty-toast

iOS Setup

Required: Info.plist

Add or update this key in your app's Info.plist:

<key>UIViewControllerBasedStatusBarAppearance</key> <true/>

This is required for the toast to properly hide the status bar when displayed. Without it, the status bar will render on top of the toast.

Expo users: Add this to your app.json:

{ "expo": { "ios": { "infoPlist": { "UIViewControllerBasedStatusBarAppearance": true } } } }

Requirements

  • iOS 15.1+ (Dynamic Island features require iPhone 14 Pro or later; older devices get a slide-in toast)
  • React Native 0.76+ (New Architecture / Fabric)

Usage

Wrap your app with ToastProvider once at the root:

import { ToastProvider } from 'react-native-pretty-toast'; export default function App() { return ( <ToastProvider> <HomeScreen /> </ToastProvider> ); }

You can trigger toasts two ways — pick whichever fits your use case:

1. Imperative API (call from anywhere)

Import toast directly. Works in non-component code: API error handlers, redux middleware, utility modules, etc.

import { toast } from 'react-native-pretty-toast'; toast.show({ icon: 'checkmark.seal.fill', title: 'Transaction Success!', message: 'Your payment has been processed', });

2. useToast hook (inside components)

import { useToast } from 'react-native-pretty-toast'; function HomeScreen() { const toast = useToast(); return ( <Button title="Show Toast" onPress={() => toast.show({ icon: 'checkmark.seal.fill', title: 'Transaction Success!', message: 'Your payment has been processed', duration: 3000, }) } /> ); }

Both share the same queue and state — calls from either entry point behave identically.

API

<ToastProvider>

Mount once at the root of your app.

PropTypeDefaultDescription
childrenReactNodeYour app tree.
useDynamicIslandbooleantrueWhen false, always use the slide-in variant even on Dynamic Island devices.
defaultConfigToastProviderDefaultsDefaults merged into every toast. Per-toast values always win. Excludes content fields (id, title, message, icon, iconSource, onPress, action).
maxQueuenumberunlimitedMax queue depth excluding the visible toast. When exceeded, the oldest queued toast is dropped. 0 disables queueing.
<ToastProvider useDynamicIsland maxQueue={3} defaultConfig={{ duration: 4000, enableSwipeDismiss: true }} > <App /> </ToastProvider>

toast.show(config, options?)

Shows a toast. Returns the toast's id so you can update or dismiss it later.

const id = toast.show({ icon: 'checkmark.seal.fill', title: 'Saved', message: 'Changes written to disk', });

ToastConfig

FieldTypeDefaultDescription
idstringautoStable identifier. Auto-generated if omitted.
iconSFSymbolNameSF Symbol name (e.g. 'checkmark.seal.fill'). Ignored when iconSource is set. On Android it's mapped to a bundled drawable via substring match; on web, to a unicode glyph.
iconSourceImageSourcePropTypeCustom image — require(...), remote URL, or file URI. When set, overrides icon.
titlestringBold title line.
messagestringSubtitle line. Pill height expands to fit.
durationnumber3000Auto-dismiss delay in ms. Ignored when autoDismiss is false or duration <= 0.
autoDismissbooleantrueIf false, toast stays until explicitly dismissed.
enableSwipeDismissbooleantrueSwipe-up to dismiss.
accentColorColorValuederivedOverrides the color derived from the icon. Drives the icon tint and pill accent stroke.
strokeColorColorValuedynamicFixed stroke color. Pass rgba(...) if you want transparency.
disableBackdropSamplingbooleanfalseSkip the backdrop luminance sampler that flips the outline between accent and neutral over varying backdrops.
actionToastActionTrailing button ({ label, onPress }). Tapping dismisses the toast.
accessibilityAnnouncementstringtitle + messageCustom screen-reader announcement. Empty string disables the announcement.
onPress() => voidCalled when the user taps the pill (not the action). Dismisses the toast after.
onShow() => voidFires when the toast begins presenting.
onHide() => voidFires when the toast finishes dismissing, for any reason.
onAutoDismiss() => voidFires only when dismissal was caused by the duration timer. Fires before onHide.

ShowOptions

FieldTypeDescription
forcebooleanPreempt the currently visible toast and present this one immediately.
toast.show({ title: 'Session expired' }, { force: true });

Variant shorthands

Each returns a toast id, accepts the same ShowOptions, and pre-fills the icon.

toast.success(title, config?, options?); toast.error(title, config?, options?); toast.info(title, config?, options?); toast.warning(title, config?, options?); toast.loading(title, config?, options?); // autoDismiss defaults to false
toast.success('Saved'); toast.error('Upload failed', { message: 'Check your connection', duration: 5000, }); toast.loading('Uploading…');

toast.update(id, partial)

Mutate an existing toast in place. Live toasts patch without re-running the enter animation; queued toasts are patched before presentation.

const id = toast.loading('Uploading…'); // later toast.update(id, { title: 'Done', icon: 'checkmark.circle.fill', autoDismiss: true, });

toast.promise(promise, messages)

Tie a toast's lifecycle to a promise. Shows a loading toast, morphs into success or error when the promise settles. Returns the original promise so await chains are preserved.

await toast.promise(api.save(data), { loading: 'Saving…', success: (result) => `Saved ${result.name}`, error: (e) => `Failed: ${(e as Error).message}`, });

Each messages field accepts either a plain string (rendered as the title) or a full ToastConfig (minus id). success and error additionally accept a function of the resolved value / error.

toast.dismiss(id?)

Dismiss the visible toast, or a specific queued toast by id.

toast.dismissAll()

Dismiss the visible toast and clear the queue.

Queue behavior

Multiple toast.show() calls are queued. Each toast is displayed after the previous one is dismissed. Use maxQueue on the provider to cap depth, or { force: true } to preempt.

SF Symbol Icons

The icon prop accepts any SF Symbol name. Browse the full catalog in Apple's SF Symbols app or online at sfsymbols.com. Icon tint color is automatically determined:

Symbol containsColor
checkmarkGreen
xmarkRed
exclamationOrange
infoBlue
heartPink
arrowBlue
OtherGray

Override with accentColor for any custom tint.

Examples

A runnable demo lives in example/ — an Expo app that exercises every variant, lifecycle hook, and custom-icon path. The web build is also deployed at blazejkustra.github.io/react-native-pretty-toast.

yarn install yarn example ios # or: yarn example android / yarn example web

yarn example start launches the Metro dev server if you already have a dev client installed. First run on a simulator/device uses ios / android to produce a native build.

// Persistent with an action toast.show({ icon: 'trash.fill', title: 'Message deleted', autoDismiss: false, action: { label: 'Undo', onPress: () => restoreMessage(), }, }); // Custom icon from a remote URL toast.show({ iconSource: { uri: 'https://example.com/avatar.png' }, title: 'Alice sent you a message', }); // Lifecycle hooks toast.show({ title: 'Connected', onShow: () => analytics.track('toast_shown'), onAutoDismiss: () => analytics.track('toast_timed_out'), onHide: () => cleanup(), }); // Preempt the current toast toast.show({ title: 'Session expired' }, { force: true });

License

MIT

react-native-pretty-toast

关于 About

Dynamic Island–aware toasts for React Native.

语言 Languages

TypeScript76.4%
Kotlin14.9%
Swift6.5%
Objective-C++1.5%
JavaScript0.6%
Ruby0.1%
Objective-C0.1%

提交活跃度 Commit Activity

代码提交热力图
过去 52 周的开发活跃度
39
Total Commits
峰值: 33次/周
Less
More

核心贡献者 Contributors