npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-system-toast

v1.0.0

Published

System toasts for React Native. Real Android Toast, a matching iOS presenter, no root component.

Readme

react-native-system-toast

A real android.widget.Toast on Android, and a matching presenter on iOS. One function, nothing to mount, no dependencies.

import { toast } from 'react-native-system-toast';

toast('Saved');

That is the whole thing. There is no <Toast /> to put at the root of your app, no provider, and no context to be inside — so this works from an error handler, a retry callback, a saga, or module scope before React has rendered anything.

| | | |---|---| | Install size | 14 kB packed, 25 files | | Runtime dependencies | none | | Classes surviving R8 | 7 | | Architecture | New Architecture Turbo Native Module |

Install

npm install react-native-system-toast
cd ios && pod install

Requires the New Architecture. No linking, no manifest changes, no permissions.

API

Four things are exported. That is deliberate — everything below is the complete surface, not a selection.

toast(message, options?)

Shows a toast. Returns nothing; it never throws and never rejects.

import { toast } from 'react-native-system-toast';

// The common case
toast('Saved');

// Longer, for something the user needs to actually read
toast('Could not reach the server. Your changes are saved locally.', {
  duration: 'long',
});

// Top of the screen — honoured on iOS, see the Android note below
toast('Copied to clipboard', { position: 'top' });
interface ToastOptions {
  duration?: 'short' | 'long';   // default 'short'
  position?: 'top' | 'bottom';   // default 'bottom'
}

'short' is 2000 ms and 'long' is 3500 ms — Android's own values, matched exactly on iOS so one call behaves the same on both platforms.

Real use, outside React entirely:

// api.ts — no component, no hook, no provider
import { toast } from 'react-native-system-toast';

export async function save(draft: Draft) {
  try {
    await client.put('/drafts', draft);
    toast('Saved');
  } catch {
    toast('Saved offline. It will sync when you reconnect.', {
      duration: 'long',
    });
  }
}

toast.hide()

Dismisses whatever is on screen. Safe to call when there is nothing showing.

import { toast } from 'react-native-system-toast';

toast('Uploading…', { duration: 'long' });

const response = await upload(file);
toast.hide();                    // the upload finished early
toast(`Uploaded ${response.name}`);

Useful when a toast announces something in progress that might end before its duration does.

getToastCapabilities()

Synchronous and free — no bridge call, so it is safe to read during render.

import { getToastCapabilities } from 'react-native-system-toast';

const { platform, positionControl, durationMs } = getToastCapabilities();
interface ToastCapabilities {
  platform: 'ios' | 'android';
  positionControl: boolean;                    // false on Android 11+
  durationMs: { short: number; long: number };  // 2000 / 3500
}

Branch on positionControl rather than on Platform.OS or an API level, so the reason a placement was ignored stays visible in your own code:

const { positionControl } = getToastCapabilities();

// Only offer the choice where it means something
{positionControl && (
  <Switch value={preferTop} onValueChange={setPreferTop} />
)}

toast('Copied', { position: positionControl && preferTop ? 'top' : 'bottom' });

And to time something that has to agree with the toast:

const { durationMs } = getToastCapabilities();

toast('Undo available');
const timer = setTimeout(commit, durationMs.short);   // not a guessed 2000

Types

import type {
  ToastOptions,
  ToastDuration,
  ToastPosition,
  ToastCapabilities,
} from 'react-native-system-toast';

Two behaviours that are not the platform default

Both are deliberate. Both are things a raw Toast gets wrong.

Only one toast exists at a time

A raw Android Toast queues. Call it ten times and the user watches ten toasts in sequence, for fifteen seconds. This package keeps a single toast and replaces its text in place, restarting the timer:

// One toast. Reads "Message 5 of 5". Gone ~2s later.
for (let i = 1; i <= 5; i++) toast(`Message ${i} of 5`);

A burst collapses into a single show

Every Toast.show() is an IPC to NotificationManagerService. Firing several in one tick is enough to take down system_server — an Android 17 emulator answered a five-call loop with "Process system isn't responding", wedging the whole device rather than just the app.

So calls inside a 60 ms window collapse to one, keeping the last message. Only the last one in a burst is readable anyway. The window is invisible in normal use and you never need to debounce at the call site.

Platform differences

Read these before deciding this package fits.

position: 'top' does nothing on Android 11+

Android 11 made Toast.setGravity() a no-op for text toasts:

"The following methods are no-ops, so your app shouldn't use them: setGravity()" — Android 11 behaviour changes

React Native's own ToastAndroid carries the same warning. This is not something a library can work around while still using a real system toast — the system owns placement now.

So on API 30 and above this package does not call setGravity() at all, reports positionControl: false, and warns once in __DEV__ with a link to that page. On API 29 and below, 'top' works.

If you need a top-anchored message on modern Android, you want a Snackbar or a JavaScript toast library. That is a real trade, and pretending otherwise would just move the surprise to your users.

Dark mode

| | Follows the system theme | |---|---| | iOS | Yes — .systemChromeMaterial and .label, no theme code in this library | | Android | Whatever the OS does. Verified on Android 17: the toast stays light even with system dark mode on |

The Android toast is rendered by system_server, not by your app, so its appearance is entirely the platform's business. That is the cost of using the real widget instead of drawing a lookalike — you get the system's behaviour including where it is inconsistent.

iOS has no toast API

There is no UIToast, in UIKit or SwiftUI, and the HUD the system shows for silent mode or AirPods is private. So the iOS side is drawn — but drawn out of system parts, so it tracks the platform rather than freezing one moment of it into hard-coded colours:

  • UIVisualEffectView with .systemChromeMaterial, and .label for text, so light and dark are handled by the OS
  • Dynamic Type, including at accessibility sizes
  • Real safe-area insets, so it clears the Dynamic Island and the home indicator
  • No travel when Reduce Motion is on, only a fade
  • A VoiceOver announcement, because a view that appears without taking focus is otherwise silent
  • Non-interactive, in a passthrough window — taps reach your UI underneath, the same as Android

Size and release builds

The Android side needs no ProGuard or R8 keep rules. android/consumer-rules.pro is intentionally empty and records why: no reflection, no name-based lookup, and no resources resolved by name, so resource shrinking has nothing of this library's to delete.

Verified rather than assumed — example/ builds with minifyEnabled and shrinkResources on, and toasts work in that build. Seven classes survive into the release dex.

iOS has no equivalent step. Swift and Objective-C compile ahead of time and Xcode dead-strips release builds already. The library does ship a PrivacyInfo.xcprivacy, accurately empty: it collects nothing, makes no network calls, and uses no required-reason APIs.

Example app

example/ exercises every option, including the ones that fail:

yarn example android
yarn example ios

It reads getToastCapabilities() and labels its own Position section accordingly, so running it on an Android 11+ device shows you the limitation rather than describing it.

Comparison

| | This | react-native-toast-message | burnt | |---|---|---|---| | Native system toast on Android | yes | no, drawn in JS | yes | | Root component required | no | <Toast /> | no | | Runtime dependencies | 0 | 0 | 2 | | Custom styling | none, on purpose | extensive | some |

If you want branded toasts with your own colours, icons and animations, use react-native-toast-message — that is what it is for. Use this one when you want what the platform already does.

Author

Built by Balamurugan V.

GitHub · LinkedIn · [email protected]

Issues and pull requests are welcome — particularly reports from devices whose OEM styles the system toast differently.

Licence

MIT