coco-alert
v1.5.0
Published
Beautiful toast notifications for React & Next.js
Maintainers
Readme
🍫 CocoAlert
Beautiful, configurable toast notifications for React & Next.js
Independent timers. Hover-to-pause. Light & Dark themes. Zero dependencies.
✨ Why CocoAlert?
- 🎨 Light & Dark Mode - Beautiful built-in themes for any design
- ⚡ Independent Timers - Each alert manages its own lifecycle
- 🎯 Hover to Pause - Progress pauses exactly where it is
- 📍 7 Position Options - Place alerts anywhere on screen
- 💬 Confirm Dialogs - Built-in async confirmation with Promise API
- 🔧 Error Handler - Parse API errors with
cocoErr()utility - 📦 Tiny Bundle - Only ~3KB gzipped
- 🛠️ TypeScript Ready - Full type safety with JSDoc comments
- 🚀 Zero Dependencies - No external packages needed
📦 Installation
npm install coco-alertyarn add coco-alertpnpm add coco-alert🚀 Quick Start
Step 1: Add AlertContainer to your root component
import { AlertContainer, coco_Alert } from 'coco-alert/react';
function App() {
return (
<>
<AlertContainer
isLightMode={false}
position="top-right"
/>
<YourApp />
</>
);
}Step 2: Use alerts anywhere in your app
import { coco_Alert } from 'coco-alert/react';
function MyComponent() {
return (
<button onClick={() => coco_Alert.success('It works! 🎉')}>
Click Me
</button>
);
}That's it! No providers, no complex setup.
📖 Complete Examples
React (Vite, CRA)
import { AlertContainer, coco_Alert } from 'coco-alert/react';
import { useState } from 'react';
function App() {
const [isLightMode, setIsLightMode] = useState(false);
return (
<>
<AlertContainer
isLightMode={isLightMode}
position="top-right"
/>
<div>
<h1>My App</h1>
<button onClick={() => setIsLightMode(!isLightMode)}>
Toggle Theme
</button>
<button onClick={() => coco_Alert.success('Success!')}>
Show Alert
</button>
</div>
</>
);
}
export default App;Next.js App Router
// app/layout.tsx
'use client'; // Required for App Router!
import { AlertContainer } from 'coco-alert/react';
export default function RootLayout({ children }) {
return (
<html>
<body>
<AlertContainer
isLightMode={false}
position="top-right"
/>
{children}
</body>
</html>
);
}// app/page.tsx
'use client';
import { coco_Alert } from 'coco-alert/react';
export default function Page() {
return (
<div>
<h1>Next.js App Router</h1>
<button onClick={() => coco_Alert.info('Hello from Next.js! 👋')}>
Show Alert
</button>
</div>
);
}Next.js Pages Router
// pages/_app.tsx
import { AlertContainer } from 'coco-alert/react';
import type { AppProps } from 'next/app';
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<AlertContainer
isLightMode={false}
position="top-right"
/>
<Component {...pageProps} />
</>
);
}// pages/index.tsx
import { coco_Alert } from 'coco-alert/react';
export default function Home() {
return (
<div>
<h1>Next.js Pages Router</h1>
<button onClick={() => coco_Alert.success('It works! 🎉')}>
Show Alert
</button>
</div>
);
}🎯 Real-World Examples
Form Submission
import { coco_Alert } from 'coco-alert/react';
async function handleSubmit(e) {
e.preventDefault();
try {
await submitForm(formData);
coco_Alert.success('Form submitted successfully! ✅');
} catch (error) {
coco_Alert.error('Failed to submit form. Please try again.');
}
}API Calls with Error Handler
import { coco_Alert, cocoErr } from 'coco-alert/react';
async function fetchData() {
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error(await response.text());
const data = await response.json();
coco_Alert.success('Data loaded successfully!');
return data;
} catch (error) {
const err = cocoErr(error);
coco_Alert.error(err.message);
}
}Delete Confirmation
import { coco_Alert } from 'coco-alert/react';
async function handleDelete(id) {
const confirmed = await coco_Alert.confirm(
'Delete this item? This cannot be undone.'
);
if (confirmed) {
try {
await deleteItem(id);
coco_Alert.success('Item deleted successfully!');
} catch (error) {
coco_Alert.error('Failed to delete item');
}
} else {
coco_Alert.info('Deletion cancelled');
}
}Multiple Alerts
import { coco_Alert } from 'coco-alert/react';
function handleProcess() {
coco_Alert.info('Processing started...');
setTimeout(() => {
coco_Alert.success('Step 1 complete');
}, 1000);
setTimeout(() => {
coco_Alert.success('Step 2 complete');
}, 2000);
setTimeout(() => {
coco_Alert.success('All done! 🎉');
}, 3000);
}📚 API Reference
AlertContainer Props
interface AlertContainerProps {
isLightMode?: boolean; // Default: false (dark mode)
position?: AlertPosition; // Default: "top-right"
}
type AlertPosition =
| "top-left"
| "top-right" // Default
| "top-center"
| "center"
| "bottom-left"
| "bottom-right"
| "bottom-center";Examples
// Dark mode, top-right (default)
<AlertContainer />
// Light mode, top-right
<AlertContainer isLightMode={true} />
// Dark mode, bottom-center
<AlertContainer position="bottom-center" />
// Light mode, center
<AlertContainer isLightMode={true} position="center" />Alert Methods
Basic Alerts
coco_Alert.success(message: string, duration?: number, position?: AlertPosition);
coco_Alert.error(message: string, duration?: number, position?: AlertPosition);
coco_Alert.warning(message: string, duration?: number, position?: AlertPosition);
coco_Alert.info(message: string, duration?: number, position?: AlertPosition);| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| message | string | required | The message to display |
| duration | number | 4000 | Duration in milliseconds (4 seconds) |
| position | AlertPosition | Container's position | Override container position for this alert |
Examples
// Simple alert (uses container settings)
coco_Alert.success('Saved!');
// Custom duration (10 seconds)
coco_Alert.error('Critical error', 10000);
// Override position for this alert
coco_Alert.info('Loading...', 3000, 'center');
// All options
coco_Alert.warning('Session expiring', 5000, 'bottom-right');Confirmation Dialog
coco_Alert.confirm(message: string, position?: AlertPosition): Promise<boolean>Returns a Promise that resolves to:
trueif user clicks "Confirm"falseif user clicks "Cancel"
Examples
// Simple confirmation
const result = await coco_Alert.confirm('Are you sure?');
if (result) {
console.log('User confirmed!');
}
// With custom position
const result = await coco_Alert.confirm('Delete this?', 'center');
// In async function
async function handleAction() {
const confirmed = await coco_Alert.confirm('Proceed with this action?');
if (confirmed) {
await performAction();
coco_Alert.success('Action completed!');
} else {
coco_Alert.info('Action cancelled');
}
}Error Handler - cocoErr()
Parse API errors into user-friendly messages.
function cocoErr(error: any): CocoErrorResult
interface CocoErrorResult {
ok: false;
status: number | null;
message: string;
raw: any;
}Examples
import { coco_Alert, cocoErr } from 'coco-alert/react';
// Basic usage
try {
const response = await fetch('/api/data');
if (!response.ok) throw new Error(await response.text());
} catch (error) {
const err = cocoErr(error);
coco_Alert.error(err.message);
console.log('Status:', err.status);
console.log('Raw error:', err.raw);
}
// With CocoBase API errors
try {
await cocobaseAPI.call();
} catch (error) {
const err = cocoErr(error);
// Automatically extracts: statusCode, error.detail
coco_Alert.error(err.message);
}
// Generic error handling
try {
throw new Error('Something went wrong');
} catch (error) {
const err = cocoErr(error);
// Returns: { ok: false, status: null, message: "Unexpected error", raw: error }
coco_Alert.error(err.message);
}🎨 Light & Dark Themes
CocoAlert includes beautiful built-in themes:
Dark Mode (Default)
- Deep, rich backgrounds with vibrant accents
- Perfect for dark interfaces
- High contrast for readability
Light Mode
- Clean, bright backgrounds with subtle accents
- Perfect for light interfaces
- Optimized for daylight viewing
Theme Examples
// Dark mode (default)
<AlertContainer isLightMode={false} />
// Light mode
<AlertContainer isLightMode={true} />
// Dynamic theme switching
function App() {
const [isDark, setIsDark] = useState(true);
return (
<>
<AlertContainer isLightMode={!isDark} />
<button onClick={() => setIsDark(!isDark)}>
Toggle Theme
</button>
</>
);
}
// Sync with system preference
function App() {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
return <AlertContainer isLightMode={!prefersDark} />;
}🎯 Features
🎨 Themes
- Dark mode (default)
- Light mode
- Dynamic switching
- System preference sync
📍 Positions
- 7 position options
- Set globally or per-alert
- Auto-stacking
- Responsive spacing
⚡ Performance
- Independent timers
- Hover-to-pause
- No re-renders on new alerts
- Smooth animations
🎭 Alert Types
- Success (green)
- Error (red)
- Warning (yellow)
- Info (blue)
- Confirm (interactive)
📦 Lightweight
- ~3KB gzipped
- Zero dependencies
- Pure inline styles
- No CSS imports needed
🔧 Developer Experience
- ✅ TypeScript ready
- ✅ JSDoc comments
- ✅ React 16.8+
- ✅ Next.js compatible
💡 Pro Tips
1. Hover to Pause
All alerts automatically pause when you hover over them! The progress bar stops and resumes exactly where it left off.
coco_Alert.success('Hover over me to pause!');2. Multiple Alerts Stack Automatically
// Show multiple alerts - they stack automatically!
coco_Alert.info('Loading...');
coco_Alert.success('Step 1 complete');
coco_Alert.success('Step 2 complete');
coco_Alert.success('All done! 🎉');3. Quick Notifications
// 1 second quick notification
coco_Alert.success('Copied!', 1000);4. Center Important Alerts
// Use center position for critical messages
coco_Alert.error('Your session has expired', 5000, 'center');5. Position Override
// Container uses top-right by default
<AlertContainer position="top-right" />
// But you can override for specific alerts
coco_Alert.error('Critical error!', 5000, 'center');
coco_Alert.info('New notification', 3000, 'bottom-right');6. Error Handler Integration
// Wrap all API calls with cocoErr for consistent error handling
import { coco_Alert, cocoErr } from 'coco-alert/react';
async function apiCall() {
try {
const res = await fetch('/api/endpoint');
if (!res.ok) throw new Error(await res.text());
return await res.json();
} catch (error) {
const err = cocoErr(error);
coco_Alert.error(err.message);
throw error;
}
}🎨 Alert Types & Colors
| Type | Dark Mode | Light Mode | Use Case | Icon | |------|-----------|------------|----------|------| | Success | Green glow | Green tint | Successful operations | ✓ | | Error | Red glow | Red tint | Errors, failures | ✕ | | Warning | Yellow glow | Yellow tint | Warnings, cautions | ⚠ | | Info | Blue glow | Blue tint | General information | ℹ | | Confirm | Yellow glow | Yellow tint | User confirmations | ? |
🐛 Troubleshooting
Alerts not showing?
Make sure you've added the AlertContainer to your root component:
// ✅ Correct
function App() {
return (
<>
<AlertContainer />
<YourApp />
</>
);
}
// ❌ Wrong - no container
function App() {
return <YourApp />; // Won't work!
}TypeScript errors?
Install React types:
npm install --save-dev @types/react @types/react-domNext.js App Router issues?
Add 'use client'; at the top of files that use alerts:
'use client';
import { coco_Alert } from 'coco-alert/react';Theme not updating?
Make sure you're using state to control isLightMode:
// ✅ Correct - dynamic
const [isDark, setIsDark] = useState(false);
<AlertContainer isLightMode={!isDark} />
// ❌ Wrong - static
<AlertContainer isLightMode={false} />Alerts overlapping?
Only use one AlertContainer per application. Multiple containers will cause issues.
// ✅ Correct - one container
function App() {
return (
<>
<AlertContainer />
<Router />
</>
);
}
// ❌ Wrong - multiple containers
function App() {
return (
<>
<AlertContainer />
<SomeComponent>
<AlertContainer /> {/* Don't do this! */}
</SomeComponent>
</>
);
}📊 Comparison with Other Libraries
| Feature | CocoAlert | react-toastify | react-hot-toast | sonner |
|---------|-----------|----------------|-----------------|--------|
| Setup | Container only | Container + Provider | Container | Provider |
| Light/Dark Themes | ✅ Built-in | ⚠️ Manual CSS | ⚠️ Manual CSS | ✅ Yes |
| Hover to Pause | ✅ Built-in | ✅ Yes | ❌ No | ⚠️ Limited |
| Independent Timers | ✅ Yes | ⚠️ Limited | ⚠️ Limited | ✅ Yes |
| Confirm Dialog | ✅ Built-in | ❌ No | ❌ No | ❌ No |
| Error Handler | ✅ Built-in (cocoErr) | ❌ No | ❌ No | ❌ No |
| Bundle Size | 3KB | 8KB | 4KB | 6KB |
| Dependencies | 0 | 2 | 1 | 3 |
| TypeScript | ✅ Built-in | ✅ Yes | ✅ Yes | ✅ Yes |
| Position Control | ✅ Global + Override | ✅ Yes | ✅ Yes | ⚠️ Limited |
🤝 Contributing
We welcome contributions! Here's how:
- Fork the repo
- Create a branch:
git checkout -b feature/amazing-feature - Make changes and test thoroughly
- Commit:
git commit -m 'Add amazing feature' - Push:
git push origin feature/amazing-feature - Open a Pull Request
Development Setup
# Clone the repo
git clone https://github.com/cocobase-team/coco-alert.git
cd coco-alert
# Install dependencies
npm install
# Run development server
npm run dev
# Build
npm run build
# Test
npm test📄 License
MIT © Cocobase Team
See LICENSE for details.
🔗 Links
- Demo: coco-alert-demo.vercel.app
- NPM: npmjs.com/package/coco-alert
- GitHub: github.com/cocobase-team/coco-alert
- Issues: GitHub Issues
- Cocobase: cocobase.buzz
❤️ Support
If you find CocoAlert helpful:
📝 Changelog
v1.0.0 (Latest)
- ✨ Initial release
- 🎨 Light & Dark themes
- ⚡ Independent timers
- 🎯 Hover-to-pause
- 📍 7 position options
- 💬 Confirm dialogs
- 🔧 Error handler (
cocoErr) - 📦 Zero dependencies
- 🛠️ Full TypeScript support
Made with 💙 by Dycoder
Beautiful alerts. Full control. Zero hassle.
