React Universal Toast

A lightweight, customizable toast notification system for React applications with TypeScript support.

⚡ Lightweight
🔧 TypeScript
🎨 Customizable
npm install react-universal-toast

Interactive Demo

Toast Placement

Choose where toasts appear on the screen:

Toast Types

Advanced Features

Control Actions

Code Examples

Installation & Setup

# Install the package
npm install react-universal-toast
// Setup in your App.js
import React from 'react';
import { ToastProvider } from 'react-universal-toast';
import 'react-universal-toast/dist/styles.css';

function App() {
  return (
    <ToastProvider placement="top-right">
      {/* Your app components */}
    </ToastProvider>
  );
}

Hook API Usage

import { useToast } from 'react-universal-toast';

function MyComponent() {
  const { show, remove, clear } = useToast();

  const handleSuccess = () => {
    const id = show('Success! Operation completed.', { type: 'success' });
    // Auto-remove after 3 seconds
    setTimeout(() => remove(id), 3000);
  };

  return (
    <div>
      <button onClick={handleSuccess}>Show Success</button>
      <button onClick={() => show('Error!', { type: 'error' })}>Show Error</button>
      <button onClick={clear}>Clear All</button>
    </div>
  );
}

Utility API Usage

import { toast } from 'react-universal-toast';

function MyComponent() {
  const handleSubmit = async () => {
    try {
      await api.submit();
      toast.success('Data saved successfully!');
    } catch (error) {
      toast.error('Failed to save data');
    }
  };

  return <button onClick={handleSubmit}>Submit</button>;
}

Form Validation Example

import { toast } from 'react-universal-toast';

function LoginForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();
    
    if (!email || !password) {
      toast.error('Please fill in all fields');
      return;
    }

    if (!email.includes('@')) {
      toast.error('Please enter a valid email');
      return;
    }

    try {
      toast.info('Logging in...');
      await login(email, password);
      toast.success('Welcome back!');
    } catch (error) {
      toast.error('Invalid credentials');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input 
        type="email" 
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email" 
      />
      <input 
        type="password" 
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password" 
      />
      <button type="submit">Login</button>
    </form>
  );
}

TypeScript Usage

import { ToastType, Placement, useToast } from 'react-universal-toast';

interface ApiResponse {
  success: boolean;
  message: string;
}

function TypedComponent() {
  const { show } = useToast();

  const handleApiCall = async () => {
    try {
      const response: ApiResponse = await fetch('/api/data').then(r => r.json());
      
      const toastType: ToastType = response.success ? 'success' : 'error';
      show(response.message, { type: toastType });
    } catch (error) {
      show('Network error occurred', { type: 'error' });
    }
  };

  return <button onClick={handleApiCall}>Fetch Data</button>;
}

Frequently Asked Questions

Can I use multiple ToastProviders?

No, you should only have one ToastProvider at the root of your application. The toast system uses a singleton pattern to manage state globally.

How do I customize the styling?

You can override the CSS classes. Here's an example:

.toast {
  background: #your-color;
  border-radius: 12px;
  font-weight: bold;
}

.toast-success {
  background: linear-gradient(45deg, #10B981, #059669);
}

Can I display JSX content in toasts?

Yes! The show() method accepts ReactNode:

const customToast = (
  <div>
    <strong>Custom Toast</strong>
    <p>With JSX content!</p>
  </div>
);

show(customToast, { type: 'info' });

How do I auto-dismiss toasts?

Toasts don't auto-dismiss by default. You can implement this manually:

const { show, remove } = useToast();

const showAutoToast = () => {
  const id = show('Auto-dismissing toast', { type: 'info' });
  setTimeout(() => remove(id), 3000); // Remove after 3 seconds
};

Is it accessible?

The toasts are keyboard accessible and clickable. For screen reader support, consider adding ARIA labels to your toast messages for better accessibility.

Does it work with Next.js App Router?

Yes! Here's how to set it up with the App Router:

// app/layout.js
import { ToastProvider } from 'react-universal-toast';
import 'react-universal-toast/dist/styles.css';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <ToastProvider placement="top-right">
          {children}
        </ToastProvider>
      </body>
    </html>
  );
}

What about SSR compatibility?

The library is fully compatible with Server-Side Rendering. It handles hydration properly and works with Next.js, Gatsby, and other SSR frameworks.

How small is the bundle size?

The library is extremely lightweight with zero runtime dependencies. The entire package is under 5KB gzipped, making it perfect for performance-conscious applications.

Can I contribute to the project?

Absolutely! Contributions are welcome. Check out the GitHub repository for contribution guidelines and open issues.