@editora/toast
v2.0.5
Published
Enterprise toast notification library for React and web apps, with SaaS-ready UX patterns, accessibility, and high-performance lifecycle controls.
Maintainers
Readme
Editora Toast
[!IMPORTANT] Live Website: https://editora-ecosystem.netlify.app/
Storybook: https://editora-ecosystem-storybook.netlify.app/
Advanced toast notification system with enterprise features, backward compatibility, and rich customization options.
A modern, framework-agnostic toast notification library designed for enterprise applications. Features advanced UX patterns, accessibility compliance, plugin architecture, and seamless integration with rich text editors.
📸 Screenshots
Hero Section

Basic Toast Types

Beautiful Themes

Interactive Actions

Interactive Feedback Form

Progress Scenarios

Advanced Features

Async Operations

Error Handling

✨ Features
Core Features
- 🚀 Framework Agnostic - Works with any JavaScript framework or vanilla JS
- ♿ Accessibility First - WCAG AA compliant with screen reader support
- 🔄 Promise Lifecycle - Automatic state transitions for async operations
- 📱 Mobile Optimized - Touch gestures, swipe-to-dismiss, and responsive design
- 🎨 Advanced Theming - 13 built-in themes with CSS variables and custom themes
- 🔌 Plugin Architecture - Extensible with custom plugins and hooks
- 📊 Smart Queue Management - Priority-based queuing with overflow strategies
- 🎯 Rich Content Support - HTML, icons, actions, progress bars, and custom rendering
- 🎪 Spring Physics Animations - Realistic animations with customizable physics parameters
- 🏗️ SSR Safe - Server-side rendering compatible
- 🪝 Editor Integration - Built-in hooks for rich text editors
- 🔒 Security - HTML sanitization and XSS protection
- 📦 Zero Dependencies - Lightweight and self-contained
Advanced Features (v2.0.0)
- 🔄 Toast Updates - Modify existing toasts dynamically with smooth transitions
- 🎯 Toast Grouping - Group related notifications with stacking and management
- 🎪 Custom Animation Hooks - User-defined animation functions for complete control
- 📍 Multiple Positions - Support for all screen corners and center positioning
- 🎨 Animation Manager - Centralized system supporting CSS, spring, and custom animations
- 📱 Gesture Support - Swipe and drag gestures for mobile interaction
- 🎯 Focus Management - Proper keyboard navigation and focus handling
- 🔄 Promise Integration - Seamless integration with async operations and promises
- 📊 Progress Tracking - Built-in progress bars with percentage display
- 🎯 Action Buttons - Interactive buttons within toasts for user actions
- 🎨 Theme Variants - Light, dark, system, colored, minimal, glass, neon, retro, ocean, forest, sunset, midnight themes
- 🔧 Global Configuration - Comprehensive configuration system for all aspects
Performance & Architecture
- ⚡ Optimized Queue Management - O(1) insertion with priority-based queuing
- 🎯 Batched DOM Updates - Efficient rendering with minimal reflows
- 🧠 Memory Safe - Automatic cleanup and leak prevention
- 🚀 Virtualized Rendering - Handles large queues without performance degradation
- 🔄 Event-Driven Architecture - Plugin system with comprehensive hooks
- 📦 Tree-Shakable - Import only what you need for smaller bundles
📦 Installation
npm install @editora/toast🌐 CDN Usage
You can also use Editora Toast directly from a CDN without installing it via npm. Include the following scripts in your HTML:
Examples
https://editora-ecosystem.netlify.app/toast-demo.html
Basic CDN Setup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My App</title>
<!-- Include the CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@editora/toast@latest/dist/toast.css">
</head>
<body>
<!-- Your content here -->
<!-- Include the JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/@editora/toast@latest/dist/index.umd.js"></script>
<script>
// Now you can use the toast functions (legacy API supports an optional options object)
toast.success('Hello from CDN!', { theme: 'light', position: 'top-right' });
toast.error('Something went wrong!', { duration: 1000 });
toast.info('This is an info message', { theme: 'light', position: 'top-right' });
toast.warning('This is a warning', { theme: 'light', position: 'top-right' });
// Advanced usage (toastAdvanced, toastPro)
// global window.toastPro.show()
// global window.toastAdvanced.show()
const notification = toastAdvanced.show({
message: 'File uploaded successfully!',
level: 'success',
icon: '✓',
actions: [
{ label: 'View', onClick: () => console.log('View clicked') },
{ label: 'Dismiss', onClick: () => notification.dismiss() }
]
});
const notification = toastPro.show({
message: 'File uploaded successfully!',
level: 'success',
icon: '✓',
actions: [
{ label: 'View', onClick: () => console.log('View clicked') },
{ label: 'Dismiss', onClick: () => notification.dismiss() }
]
});
</script>
</body>
</html>CDN URLs
- JavaScript:
https://cdn.jsdelivr.net/npm/@editora/toast@latest/dist/index.umd.js - CSS:
https://cdn.jsdelivr.net/npm/@editora/toast@latest/dist/toast.css
Note: Replace
@latestwith a specific version number (e.g.,@2.0.0) for production use to avoid unexpected updates.
🚀 Quick Start
Basic Usage (Backward Compatible)
import { toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Simple notifications (migrated to optional advanced options)
toast.success('File saved successfully!', { theme: 'light', position: 'top-right' });
toast.error('Failed to save file', { theme: 'light', position: 'top-right' });
toast.info('Info message', { theme: 'light', position: 'top-right' });
toast.warning('Warning message', { theme: 'light', position: 'top-right' });Advanced Usage (v2.0.0 Features)
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Rich notifications with actions and progress
const notification = toast.show({
message: 'Document uploaded successfully!',
level: 'success',
icon: '✓',
actions: [
{ label: 'View Document', onClick: () => console.log('View clicked') },
{ label: 'Share', onClick: () => console.log('Share clicked') },
{ label: 'Dismiss', onClick: () => notification.dismiss() }
],
progress: { value: 100, showPercentage: true },
duration: 6000
});
// Promise-based notifications with automatic state transitions
toast.promise(
uploadFile(file),
{
loading: 'Uploading file...',
success: (data) => `File "${data.name}" uploaded successfully!`,
error: (error) => `Upload failed: ${error.message}`
}
);
// Update existing toast dynamically
const loadingToast = toast.loading('Saving document...');
setTimeout(() => {
toast.update(loadingToast.id, {
message: 'Document saved successfully!',
level: 'success',
icon: '💾',
actions: [{ label: 'Open', onClick: () => {} }]
});
}, 2000);
// Group related notifications
toast.group('file-operations', {
message: 'File 1 processed',
level: 'success'
});
toast.group('file-operations', {
message: 'File 2 processed',
level: 'success'
});🎛️ Configuration
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Global configuration with all available options
toast.configure({
// Positioning
position: 'top-right', // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center'
// Timing
duration: 5000, // Default duration in milliseconds
pauseOnHover: true, // Pause timer when hovering
// Display
maxVisible: 5, // Maximum visible toasts
theme: 'system', // Theme: 'light' | 'dark' | 'system' | 'colored' | 'minimal' | 'glass' | 'neon' | 'retro' | 'ocean' | 'forest' | 'sunset' | 'midnight' | 'custom'
// Accessibility
enableAccessibility: true, // Enable screen reader support
enableKeyboardNavigation: true, // Enable keyboard navigation
// Interactions
swipeDismiss: true, // Enable swipe to dismiss on mobile
dragDismiss: false, // Enable drag to dismiss
clickToDismiss: true, // Click anywhere to dismiss
// Queue Management
queueStrategy: 'priority', // 'fifo' | 'priority' | 'stack'
maxQueueSize: 10, // Maximum queued toasts
// Animations
animation: {
type: 'spring', // 'css' | 'spring' | 'custom'
config: {
stiffness: 120,
damping: 12,
mass: 1,
precision: 0.01
}
},
// Advanced
enableHtml: false, // Allow HTML in messages (use with caution)
sanitizeHtml: true, // Sanitize HTML content
zIndex: 9999, // Base z-index for toasts
containerClass: 'custom-container' // Custom container class
});🎨 Theming

Built-in Themes
Editora Toast comes with 13 beautiful themes:
light- Clean white background with subtle shadowsdark- Dark background with high contrast textsystem- Automatically switches between light/dark based on system preferencecolored- Vibrant gradient backgrounds for each toast levelminimal- Clean design with subtle borders and minimal stylingglass- Frosted glass effect with backdrop blurneon- Bright neon colors with glowing effectsretro- 80s/90s style with bold colors and gradientsocean- Blue aquatic theme with calming colorsforest- Green natural theme with earthy tonessunset- Warm orange/pink sunset colorsmidnight- Deep blue dark theme with subtle gradientscustom- Fully customizable with CSS variables
Usage
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Set global theme
toast.configure({
theme: 'glass' // or 'neon', 'retro', 'ocean', etc.
});
// Per-toast theme
toast.show({
message: 'Hello World',
theme: 'colored'
});CSS Variables
:root {
--editora-toast-bg: rgba(0, 0, 0, 0.85);
--editora-toast-color: #fff;
--editora-toast-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
--editora-toast-border-radius: 6px;
--editora-toast-font-family: system-ui, -apple-system, 'Segoe UI', Roboto;
--editora-toast-font-size: 13px;
--editora-toast-padding: 10px 14px;
}Theme Classes
<!-- Apply theme globally -->
<div data-theme="glass">
<!-- All toasts will use glass theme -->
</div>
<!-- Or apply to specific container -->
<div class="editora-toast-container" data-theme="neon">
</div>🎯 Advanced Features
Promise Lifecycle Toasts

Automatically handle async operations with state transitions:
import { toastAdvanced as toast } from '@editora/toast';
// Promise-based notifications
const uploadPromise = uploadFile(file);
toast.promise(uploadPromise, {
loading: {
message: 'Uploading file...',
icon: '⏳',
progress: { indeterminate: true }
},
success: {
message: 'File uploaded successfully!',
icon: '✅',
duration: 4000,
actions: [{ label: 'View', onClick: () => openFile() }]
},
error: {
message: 'Upload failed. Please try again.',
icon: '❌',
duration: 6000,
actions: [
{ label: 'Retry', onClick: () => retryUpload() },
{ label: 'Cancel', onClick: () => {} }
]
}
});Interactive Actions

Add interactive buttons to your toasts:
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
const notification = toast.show({
message: 'Document saved successfully!',
level: 'success',
icon: '💾',
actions: [
{
label: 'Open Document',
onClick: () => openDocument(),
primary: true // Primary action styling
},
{
label: 'Share',
onClick: () => shareDocument(),
variant: 'secondary'
},
{
label: 'Dismiss',
onClick: () => notification.dismiss(),
variant: 'ghost'
}
],
duration: 8000 // Longer duration for actions
});Progress Tracking

Built-in progress bars with customizable display:
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Determinate progress
const progressToast = toast.show({
message: 'Processing files...',
level: 'info',
progress: {
value: 0,
showPercentage: true,
color: '#007acc'
}
});
// Update progress
let progress = 0;
const interval = setInterval(() => {
progress += 10;
toast.update(progressToast.id, {
progress: { value: progress, showPercentage: true },
message: `Processing files... ${progress}%`
});
if (progress >= 100) {
clearInterval(interval);
toast.update(progressToast.id, {
message: 'Processing complete!',
level: 'success',
progress: { value: 100, showPercentage: true }
});
}
}, 500);Toast Updates

Modify existing toasts dynamically:
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Create a loading toast
const loadingToast = toast.loading('Connecting to server...');
// Update with progress
setTimeout(() => {
toast.update(loadingToast.id, {
message: 'Authenticating...',
progress: { value: 25, showPercentage: true }
});
}, 1000);
// Update with success
setTimeout(() => {
toast.update(loadingToast.id, {
message: 'Connected successfully!',
level: 'success',
icon: '🔗',
progress: { value: 100, showPercentage: true },
actions: [{ label: 'Explore', onClick: () => {} }]
});
}, 2000);Toast Grouping

Group related notifications together:
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Group file operations
const files = ['document.pdf', 'image.jpg', 'data.json'];
files.forEach((file, index) => {
setTimeout(() => {
toast.group('file-upload', {
message: `Uploaded ${file}`,
level: 'success',
icon: '📁',
duration: 3000
});
}, index * 500);
});
// Group error notifications
toast.group('validation-errors', {
message: 'Invalid email format',
level: 'error',
icon: '⚠️'
});
toast.group('validation-errors', {
message: 'Password too weak',
level: 'error',
icon: '🔒'
});Interactive Feedback Forms

Create interactive forms within toasts:
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
toast.show({
message: 'How was your experience?',
level: 'info',
icon: '⭐',
render: () => {
const container = document.createElement('div');
container.innerHTML = `
<div style="display: flex; gap: 8px; margin-top: 8px;">
<button class="feedback-btn" data-rating="1">😞</button>
<button class="feedback-btn" data-rating="2">😐</button>
<button class="feedback-btn" data-rating="3">😊</button>
<button class="feedback-btn" data-rating="4">😃</button>
<button class="feedback-btn" data-rating="5">😍</button>
</div>
`;
container.addEventListener('click', (e) => {
if (e.target.classList.contains('feedback-btn')) {
const rating = e.target.dataset.rating;
submitFeedback(rating);
toast.success('Thank you for your feedback!');
}
});
return container;
},
duration: 10000
});🔌 Plugins
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
const myPlugin = {
name: 'my-plugin',
install(manager) {
// Add custom functionality
manager.on('beforeShow', (toast) => {
console.log('Toast about to show:', toast.message);
});
}
};
toast.use(myPlugin);📱 Positions
toast.show({
message: 'Hello World',
position: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center'
});🎪 Advanced Features
Spring Physics Animations
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Spring animation with custom physics
toast.show({
message: 'Spring animated toast!',
level: 'success',
animation: {
type: 'spring',
config: {
stiffness: 120, // Spring stiffness (default: 100)
damping: 12, // Spring damping (default: 10)
mass: 1, // Spring mass (default: 1)
precision: 0.01 // Animation precision (default: 0.01)
}
}
});Custom Animation Hooks
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Custom animation functions
toast.show({
message: 'Custom animated toast!',
level: 'info',
animation: {
type: 'custom',
show: async (element, toast) => {
// Custom show animation
element.style.opacity = '0';
element.style.transform = 'rotateX(90deg)';
await new Promise(resolve => {
element.style.transition = 'all 0.5s ease';
element.style.opacity = '1';
element.style.transform = 'rotateX(0deg)';
element.addEventListener('transitionend', resolve, { once: true });
});
},
hide: async (element, toast) => {
// Custom hide animation
element.style.transition = 'all 0.3s ease';
element.style.opacity = '0';
element.style.transform = 'scale(0.8)';
return new Promise(resolve => {
setTimeout(resolve, 300);
});
},
update: async (element, toast, updates) => {
// Custom update animation
element.style.transform = 'scale(1.05)';
setTimeout(() => {
element.style.transform = 'scale(1)';
}, 150);
}
}
});Global Animation Configuration
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Set default animation for all toasts
toast.configure({
animation: {
type: 'spring',
config: { stiffness: 150, damping: 15 }
}
});Toast Groups
// Group related notifications
toast.group('upload-group', {
message: 'Upload 1 complete',
level: 'success'
});
toast.group('upload-group', {
message: 'Upload 2 complete',
level: 'success'
});Custom Render Function
toast.show({
render: () => {
const div = document.createElement('div');
div.innerHTML = '<strong>Custom</strong> content';
return div;
}
});Editor Integration
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Listen for editor events
toast.onEditorEvent('spellcheck-error', (error) => {
toast.error(`Spelling error: ${error.word}`, { theme: 'light', position: 'top-right' });
});
// Trigger editor events
toast.triggerEditorEvent('media-upload-progress', { progress: 50 });📋 API Reference
Core Methods
toast.show(options)- Show a toast with full optionstoast.update(id, options)- Update an existing toast dynamicallytoast.dismiss(id?)- Dismiss a specific toast or all toaststoast.clear()- Clear all visible toasts
Convenience Methods
toast.info(message, options?)- Info level toasttoast.success(message, options?)- Success level toasttoast.error(message, options?)- Error level toasttoast.warning(message, options?)- Warning level toasttoast.loading(message, options?)- Loading state toast
Advanced Methods (v2.0.0)
toast.promise(promise, options)- Promise lifecycle toasts with automatic state transitionstoast.group(id, options)- Group related toasts with stacking behaviortoast.configure(config)- Update global configurationtoast.use(plugin)- Install a plugintoast.onEditorEvent(event, handler)- Listen for editor integration eventstoast.triggerEditorEvent(event, data)- Trigger editor integration events
Toast Options Interface
interface ToastOptions {
// Content
message: string;
level?: 'info' | 'success' | 'error' | 'warning' | 'loading' | 'progress' | 'promise' | 'custom';
icon?: string;
html?: boolean;
render?: () => HTMLElement;
// Behavior
duration?: number;
pauseOnHover?: boolean;
clickToDismiss?: boolean;
// Positioning
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';
// Interactions
actions?: ToastAction[];
swipeDismiss?: boolean;
dragDismiss?: boolean;
// Progress
progress?: ToastProgress;
// Styling
theme?: string;
className?: string;
// Advanced
groupId?: string;
priority?: number;
animation?: ToastAnimation;
onShow?: (toast: Toast) => void;
onHide?: (toast: Toast) => void;
onUpdate?: (toast: Toast, updates: Partial<ToastOptions>) => void;
}
interface ToastAction {
label: string;
onClick: (toast: Toast) => void;
variant?: 'primary' | 'secondary' | 'ghost';
primary?: boolean;
}
interface ToastProgress {
value: number; // 0-100
showPercentage?: boolean;
indeterminate?: boolean;
color?: string;
size?: 'sm' | 'md' | 'lg';
}
interface ToastAnimation {
type: 'css' | 'spring' | 'custom';
config?: SpringConfig;
show?: AnimationFunction;
hide?: AnimationFunction;
update?: AnimationFunction;
}🎮 Live Demo & Examples
Try out all the features with our comprehensive demo:
# Clone the repository
git clone https://github.com/ajaykr089/Editora.git
cd Editora/packages/editora-toast
# Install dependencies
npm install
# Start the demo server
npm run demo
# or
python3 -m http.server 8086
# Then open: http://localhost:8086/examples/web/toast-demo.htmlThe demo showcases:
- ✅ All 13 built-in themes
- 🎯 Interactive actions and buttons
- 📊 Progress bars and indicators
- 🔄 Promise lifecycle management
- 🎪 Spring physics animations
- 📱 Mobile gestures and touch support
- ♿ Accessibility features
- 🎨 Custom rendering and HTML content
- 📱 Responsive design across devices
🔧 Build & Development
# Install dependencies
npm install
# Build
npm run build
# Development watch
npm run dev
# Clean
npm run clean🌍 Browser Support
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
📄 License
MIT © Ajay Kumar
🤝 Contributing
Contributions welcome! Please see the main repository for contribution guidelines.
📚 Migration Guide
From v1.x to v2.0.0
The v2.0.0 release introduces powerful new features while maintaining full backward compatibility. Your existing code will continue to work without changes.
✨ New Features in v2.0.0
// v1.x (still works)
import { toast } from '@editora/toast';
import "@editora/toast/toast.css";
toast.success('Hello World', { theme: 'light', position: 'top-right' });
// v2.0.0 advanced features
import { toastAdvanced as toast } from '@editora/toast';
import "@editora/toast/toast.css";
// Promise lifecycle toasts
toast.promise(fetchData(), {
loading: 'Loading...',
success: 'Data loaded!',
error: 'Failed to load'
});
// Rich content with actions
toast.show({
message: 'File uploaded!',
level: 'success',
icon: '✅',
actions: [
{ label: 'View', onClick: () => {} },
{ label: 'Share', onClick: () => {} }
],
progress: { value: 100, showPercentage: true }
});
// Dynamic toast updates
const toast = toast.loading('Saving...');
toast.update(toast.id, { message: 'Saved!', level: 'success' });
// Toast grouping
toast.group('operations', { message: 'Task 1 complete', level: 'success' });
toast.group('operations', { message: 'Task 2 complete', level: 'success' });Configuration Changes
// New configuration options in v2.0.0
toast.configure({
theme: 'system', // New themes: glass, neon, retro, ocean, etc.
swipeDismiss: true, // Mobile gesture support
dragDismiss: false,
animation: {
type: 'spring', // New spring physics animations
config: { stiffness: 120, damping: 12 }
},
queueStrategy: 'priority', // Priority-based queuing
enableKeyboardNavigation: true // Enhanced accessibility
});For more detailed migration information, see the migration guide.
