@lapp-studio/react-toast-engine
v0.0.5
Published
[](https://www.npmjs.com/package/@lapp-studio/react-toast-engine) [](http
Downloads
956
Maintainers
Readme
React Toast Engine 🍞
React Toast Engine is a high-performance, headless toast management library for React and React Native.
It separates state logic (powered by Zustand) from the UI layer, allowing you to share the exact same notification logic across Web and Mobile. For React Native, it maintains flawless 60FPS animations natively using Reanimated and Gesture Handler, without locking the JS thread.
✨ Key Features
- 🚀 Zero-Lag State: Atomic updates via Zustand to prevent unnecessary re-renders across your app.
- 📱 Native First: Deep, out-of-the-box integration with
react-native-reanimated,react-native-gesture-handler, andreact-native-worklets. - 🌐 Truly Hybrid (Tree-Shakeable): Separate entry points for Core (
/) and Native (/native) ensure your Web builds never bundle heavy React Native libraries. - 🏗️ 100% Headless & Flexible: You build the UI components; the engine handles the stacking, queuing, lifecycle, and gesture logic.
- 🛡️ Smart Provider Stacking: If multiple providers exist in the DOM/Tree, the engine intelligently routes toasts only to the topmost (active) provider to prevent duplicates.
📦 Installation
Install the core library:
# npm
npm i @lapp-studio/react-toast-engine
# yarn
yarn add @lapp-studio/react-toast-engineReact Native Peer Dependencies
If you are using React Native, ensure you have the required animation and gesture libraries installed in your project:
yarn add react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-worklets🚀 Quick Start
1. Initialize the Client
Create a shared file (e.g., src/lib/toasts.ts) to configure your UI components and initialize the engine.
// src/lib/toasts.ts
import { createToastsClient } from "@lapp-studio/react-toast-engine/core";
// Import the native renderer only in your React Native app
import { PoolRenderer } from "@lapp-studio/react-toast-engine/native";
import {
MySuccessComponent,
MyErrorComponent,
MyInfoComponent,
} from "./components";
// Map your custom components to the engine's InfoTypes
const components = {
success: MySuccessComponent,
error: MyErrorComponent,
info: MyInfoComponent,
};
// Create and export the client tools
export const { store, utilities, renderer } = createToastsClient({
components,
PoolRenderer,
storeSettings: { poolLimit: 5 }, // Keep a maximum of 5 toasts in the DOM at once
});2. Setup the Provider
Wrap your application's root component with the generated Provider.
import { renderer } from "./lib/toasts";
export function App() {
return (
<renderer.Provider>
<MainScreen />
</renderer.Provider>
);
}3. Trigger Toasts
You can stack toasts from anywhere in your app—either via React hooks inside your components or via helper functions in standard TypeScript files.
Inside a React Component (Using Hooks):
import { Button } from "react-native";
import { utilities } from "./lib/toasts";
export const SaveButton = () => {
const stack = utilities.hooks.useStackToast();
const handlePress = () => {
stack({
title: "Success!",
description: "Profile updated.",
infoType: "success",
durationInMs: 3000,
});
};
return <Button title="Save" onPress={handlePress} />;
};Outside React (Using Helpers - Great for API Interceptors):
import { utilities } from "./lib/toasts";
import api from "./api";
api.interceptors.response.use(
(response) => response,
(error) => {
utilities.helpers.stack({
title: "Connection Error",
description: error.message,
infoType: "error",
durationInMs: 5000,
});
return Promise.reject(error);
},
);🎨 Creating Custom Components
Since the engine is headless, you have total control over the UI. Your components will receive toast data and an actions object. Using our exported types ensures full TypeScript support.
import React from "react";
import { YStack, Text } from "tamagui"; // Or your UI library of choice
import { ToastComponentProps } from "@lapp-studio/react-toast-engine";
export const MySuccessComponent = ({ toast, actions }: ToastComponentProps) => {
return (
<YStack
backgroundColor="$green10"
padding="$4"
borderRadius="$8"
onPress={() => actions?.onPress?.(toast)}
>
<Text color="white" fontWeight="bold" fontSize="$4">
{toast.title}
</Text>
<Text color="white" fontSize="$3">
{toast.description}
</Text>
</YStack>
);
};📱 React Native Architecture
The native implementation uses Shared Values and Worklets to achieve native-level performance:
- Swipe to Dismiss: Fully interactive, physics-based gestures to clear notifications. Swipe velocities are calculated in real-time.
- UI Thread Operations: Dismissing a toast uses
scheduleOnRNto bypass the JS thread entirely, avoiding stutters during heavy computations. - Safe Area Aware: Automatically shifts offsets using
react-native-safe-area-contextto prevent overlapping with notches or dynamic islands. - Dynamic Z-Index: Smart stacking logic that recalculates layer priorities smoothly as new toasts arrive or leave.
📄 License
MIT © L'App Studio
