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

rn-anywhere-toast

v0.1.0

Published

React Native Customizable Toasts That Works With Modals! Well Anywhere Really.

Readme

rn-anywhere-toast

A React Native / Expo toast package built for places where normal absolute overlays are not enough, especially React Native Modal.

React Native modals are rendered in a native layer above the main app UI. A root-level toast with a very high zIndex can still appear behind a modal. rn-anywhere-toast keeps a global showToast API, but lets you mount a ToastReceiver inside the active modal so the toast is rendered in that native layer.

Installation

npm install rn-anywhere-toast
npx expo install react-native-gesture-handler react-native-reanimated react-native-svg
npm install lucide-react-native

Make sure Reanimated is configured in your app. Expo projects usually need the Reanimated Babel plugin:

// babel.config.js
module.exports = function (api) {
  api.cache(true);

  return {
    presets: ['babel-preset-expo'],
    plugins: ['react-native-reanimated/plugin'],
  };
};

Basic Usage

Wrap your app with ToastProvider.

import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { ToastProvider } from 'rn-anywhere-toast';

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <ToastProvider>
        <RootNavigator />
      </ToastProvider>
    </GestureHandlerRootView>
  );
}

Show a toast from any child component.

import { Button } from 'react-native';
import { useToast } from 'rn-anywhere-toast';

export function SaveButton() {
  const { showToast } = useToast();

  return (
    <Button
      title="Save"
      onPress={() => {
        showToast({
          type: 'success',
          message: 'Saved successfully',
        });
      }}
    />
  );
}

Built-in types:

'success' | 'error' | 'info' | 'warning'

If no type is passed, info is used.

Toasts Above Modals

For normal screens, the provider renders the toast overlay for you. For React Native Modal, mount ToastReceiver inside the modal.

import { Modal, View } from 'react-native';
import { ToastReceiver } from 'rn-anywhere-toast';

export function EditModal({ visible }: { visible: boolean }) {
  return (
    <Modal visible={visible} animationType="slide">
      <ToastReceiver />

      <View>
        <ModalContent />
      </View>
    </Modal>
  );
}

When the receiver is mounted, showToast sends new toasts to that receiver instead of the provider's root overlay. That keeps the toast above the modal on iOS and Android.

Receivers are stacked. If you open a modal on top of another modal, the most recently mounted ToastReceiver receives new toasts. When it unmounts, the previous receiver becomes active again.

Styling The Built-In Toasts

Use config to customize the built-in toast UI globally or per type.

import { ToastProvider } from 'rn-anywhere-toast';

export default function App() {
  return (
    <ToastProvider
      config={{
        duration: 4000,
        topOffset: 64,
        success: {
          backgroundColor: '#E6F4EA',
          textColor: '#1E4620',
          iconColor: '#1E4620',
          containerStyle: {
            borderRadius: 12,
            borderWidth: 1,
            borderColor: '#1E4620',
          },
          textStyle: {
            fontWeight: '600',
          },
        },
        error: {
          backgroundColor: '#FFDEDE',
          textColor: '#5C1D1D',
          hideIcon: true,
        },
      }}
    >
      <RootNavigator />
    </ToastProvider>
  );
}

Custom Icons

Pass a React node or a render function.

<ToastProvider
  config={{
    warning: {
      icon: <MyWarningIcon />,
    },
    success: {
      icon: ({ dismiss }) => <MySuccessIcon onPress={dismiss} />,
    },
  }}
>
  <RootNavigator />
</ToastProvider>

Bring Your Own Toast Component

Use renderToast when you want full control. You can set it globally or per type.

import { Pressable, Text, View } from 'react-native';
import { ToastProvider } from 'rn-anywhere-toast';

export default function App() {
  return (
    <ToastProvider
      config={{
        renderToast: ({ message, type, dismiss }) => (
          <Pressable onPress={dismiss}>
            <View
              style={{
                width: 340,
                padding: 16,
                borderRadius: 14,
                backgroundColor: type === 'error' ? '#2A1010' : '#111827',
              }}
            >
              <Text style={{ color: '#FFFFFF', fontWeight: '700' }}>
                {type.toUpperCase()}
              </Text>
              <Text style={{ color: '#FFFFFF', marginTop: 4 }}>{message}</Text>
            </View>
          </Pressable>
        ),
      }}
    >
      <RootNavigator />
    </ToastProvider>
  );
}

Per-type custom toasts override the global renderer:

<ToastProvider
  config={{
    error: {
      renderToast: ({ message, dismiss }) => (
        <ErrorToast message={message} onClose={dismiss} />
      ),
    },
  }}
>
  <RootNavigator />
</ToastProvider>

Per-Toast Options

showToast({
  id: 'profile-saved',
  type: 'success',
  message: 'Profile saved',
  duration: 5000,
  data: {
    source: 'settings-screen',
  },
});

Set duration: 0 to keep the toast visible until the user swipes it away or your custom component calls dismiss.

API

ToastProvider

<ToastProvider config={config}>{children}</ToastProvider>

useToast

const { showToast } = useToast();

showToast accepts:

type ShowToastOptions = {
  id?: string;
  message: React.ReactNode;
  type?: 'success' | 'error' | 'info' | 'warning';
  duration?: number;
  data?: Record<string, unknown>;
};

It returns the toast id.

ToastReceiver

Mount this inside a native layer, usually a React Native Modal, when toasts need to appear above that layer.

<Modal visible={visible}>
  <ToastReceiver />
  <ModalContent />
</Modal>

ToastConfig

type ToastConfig = {
  duration?: number;
  topOffset?: number;
  overlayStyle?: StyleProp<ViewStyle>;
  toastWrapperStyle?: StyleProp<ViewStyle>;
  renderToast?: (props: ToastRenderProps) => React.ReactNode;
  success?: ToastStyleConfig;
  error?: ToastStyleConfig;
  info?: ToastStyleConfig;
  warning?: ToastStyleConfig;
  default?: ToastStyleConfig;
};
type ToastStyleConfig = {
  backgroundColor?: string;
  textColor?: string;
  iconColor?: string;
  icon?: React.ReactNode | ((props: ToastRenderProps) => React.ReactNode);
  hideIcon?: boolean;
  duration?: number;
  containerStyle?: StyleProp<ViewStyle>;
  textStyle?: StyleProp<TextStyle>;
  renderToast?: (props: ToastRenderProps) => React.ReactNode;
};
type ToastRenderProps = {
  toast: Toast;
  message: React.ReactNode;
  type: 'success' | 'error' | 'info' | 'warning';
  dismiss: () => void;
  config?: ToastConfig;
  typeConfig?: ToastStyleConfig;
};

Development

npm install
npm run typecheck
npm run build