Package Exports
- @cibobu/react-toast-popup
- @cibobu/react-toast-popup/components/Button/Button.css
- @cibobu/react-toast-popup/styles/tailwind-fallback.css
Readme
@cibobu/react-toast-popup
A comprehensive React component library featuring toast notifications, customizable buttons, and typography components built with TypeScript and Tailwind CSS.
✨ Features
- 🍞 Toast Notifications - Beautiful, accessible toast notifications with multiple types and animations
- 🎨 Button Component - Highly customizable button with multiple variants, styles, and sizes
- 📝 Typography Component - Comprehensive typography system with semantic variants
- 🎯 TypeScript Support - Fully typed components with excellent IntelliSense
- 🎨 Tailwind CSS - Built with Tailwind CSS for easy customization
- 📱 Responsive - Mobile-first design that works on all screen sizes
- ♿ Accessible - WCAG compliant with proper ARIA attributes
- 🚀 Tree Shakeable - Import only what you need
📦 Installation
npm install @cibobu/react-toast-popup
# or
yarn add @cibobu/react-toast-popup
# or
pnpm add @cibobu/react-toast-popup🚀 Quick Start
1. Setup (Choose One Option)
Option A: With Tailwind CSS (Recommended for customization)
# Install Tailwind CSS first
npm install -D tailwindcss postcss autoprefixer
# Then initialize Tailwind
npx tailwindcss init -ptailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
"./node_modules/@cibobu/react-toast-popup/**/*.{js,ts,jsx,tsx}"
],
theme: {
extend: {},
},
plugins: [],
}src/index.css:
@tailwind base;
@tailwind components;
@tailwind utilities;Option B: Without Tailwind CSS (Zero configuration) - RECOMMENDED
If you don't want to setup Tailwind CSS, simply import the fallback CSS:
src/index.css or src/main.jsx:
@import '@cibobu/react-toast-popup/dist/styles/tailwind-fallback.css';Or in your main JS file:
import '@cibobu/react-toast-popup/dist/styles/tailwind-fallback.css';This is the easiest way to get started! No configuration needed.
2. Basic Usage
import React from 'react';
import useNotification, { Button, Typography, Notification } from '@cibobu/react-toast-popup';
function App() {
const { showNotification, notifications, removeNotification } = useNotification();
return (
<div className="p-8">
<Typography variant="title-h1">Welcome!</Typography>
<Button
variant="primary"
style="filled"
onClick={() => showNotification({
type: 'success',
message: 'Hello World!',
duration: 3000
})}
>
Show Toast
</Button>
{/* Notification Container */}
<div className="fixed top-4 right-4 space-y-2">
{notifications.map((notification) => (
<Notification
key={notification.id}
type={notification.type}
message={notification.message}
onClose={() => removeNotification(notification.id)}
/>
))}
</div>
</div>
);
}
export default App;📚 Components
🍞 Toast Notifications
useNotification Hook
import useNotification from '@cibobu/react-toast-popup';
const { showNotification, notifications, removeNotification } = useNotification();API:
showNotification(options)- Show a new notificationnotifications- Array of current notificationsremoveNotification(id)- Remove a specific notification
Options:
interface NotificationOptions {
type: 'success' | 'info' | 'warning' | 'error';
message: string;
duration?: number; // in milliseconds
animation?: 'fade' | 'pop' | 'slide';
}Notification Component
import { Notification } from '@cibobu/react-toast-popup';
<Notification
type="success"
message="Operation completed successfully!"
onClose={() => console.log('closed')}
/>🎨 Button Component
import { Button } from '@cibobu/react-toast-popup';
// Basic usage
<Button variant="primary" style="filled" size="medium">
Click me
</Button>
// With loading state
<Button variant="primary" style="filled" loading>
Loading...
</Button>
// With icons
<Button
variant="primary"
style="filled"
leftIcon={<span>📧</span>}
rightIcon={<span>→</span>}
>
Send Email
</Button>
// Icon only
<Button variant="primary" style="filled" iconOnly>
⚙️
</Button>Props:
interface ButtonProps {
variant?: 'primary' | 'neutral' | 'error';
style?: 'filled' | 'stroke' | 'lighter' | 'ghost';
size?: 'x-small' | 'small' | 'medium';
loading?: boolean;
disabled?: boolean;
leftIcon?: React.ReactNode;
rightIcon?: React.ReactNode;
iconOnly?: boolean;
children: React.ReactNode;
className?: string;
}Variants & Styles:
- Primary: Blue color scheme
- Neutral: Gray color scheme
- Error: Red color scheme
Each variant supports 4 styles:
- Filled: Solid background
- Stroke: Outlined border
- Lighter: Light background
- Ghost: Transparent background
📝 Typography Component
import { Typography } from '@cibobu/react-toast-popup';
// Display variants
<Typography variant="display-d1">Large Display</Typography>
<Typography variant="display-d2">Medium Display</Typography>
// Title variants
<Typography variant="title-h1">Main Title</Typography>
<Typography variant="title-h2">Section Title</Typography>
<Typography variant="title-h3">Subsection Title</Typography>
<Typography variant="title-h4">Card Title</Typography>
// Subheading variants
<Typography variant="subheading-medium">Medium Subheading</Typography>
<Typography variant="subheading-small">Small Subheading</Typography>
// Label variants
<Typography variant="label-large">Large Label</Typography>
<Typography variant="label-medium">Medium Label</Typography>
<Typography variant="label-small">Small Label</Typography>
// Paragraph variants
<Typography variant="paragraph-medium">Regular paragraph text</Typography>
<Typography variant="paragraph-small">Small paragraph text</Typography>
// Custom element
<Typography variant="title-h1" as="h2">
Custom HTML element
</Typography>Props:
interface TypographyProps {
variant?:
| 'display-d1' | 'display-d2'
| 'title-h1' | 'title-h2' | 'title-h3' | 'title-h4'
| 'subheading-medium' | 'subheading-small' | 'subheading-x-small'
| 'label-large' | 'label-medium' | 'label-small' | 'label-x-small'
| 'paragraph-medium' | 'paragraph-small' | 'paragraph-x-small';
as?: keyof JSX.IntrinsicElements;
children: React.ReactNode;
className?: string;
}🎯 Complete Example
import React, { useState } from 'react';
import useNotification, { Button, Typography, Notification } from '@cibobu/react-toast-popup';
function ContactForm() {
const [formData, setFormData] = useState({ name: '', email: '' });
const [isSubmitting, setIsSubmitting] = useState(false);
const { showNotification, notifications, removeNotification } = useNotification();
const handleSubmit = async (e) => {
e.preventDefault();
setIsSubmitting(true);
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 2000));
showNotification({
type: 'success',
message: 'Form submitted successfully!',
duration: 3000
});
setFormData({ name: '', email: '' });
} catch (error) {
showNotification({
type: 'error',
message: 'Failed to submit form. Please try again.',
duration: 5000
});
} finally {
setIsSubmitting(false);
}
};
return (
<div className="max-w-md mx-auto p-6 bg-white rounded-lg shadow-lg">
<Typography variant="title-h2" className="mb-6 text-center">
Contact Us
</Typography>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<Typography variant="label-medium" className="block mb-2">
Name
</Typography>
<input
type="text"
value={formData.name}
onChange={(e) => setFormData({...formData, name: e.target.value})}
className="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
required
/>
</div>
<div>
<Typography variant="label-medium" className="block mb-2">
Email
</Typography>
<input
type="email"
value={formData.email}
onChange={(e) => setFormData({...formData, email: e.target.value})}
className="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
required
/>
</div>
<Button
type="submit"
variant="primary"
style="filled"
size="medium"
loading={isSubmitting}
disabled={isSubmitting}
className="w-full"
>
{isSubmitting ? 'Submitting...' : 'Submit Form'}
</Button>
</form>
{/* Toast Notifications */}
<div className="fixed top-4 right-4 space-y-2 z-50">
{notifications.map((notification) => (
<Notification
key={notification.id}
type={notification.type}
message={notification.message}
onClose={() => removeNotification(notification.id)}
/>
))}
</div>
</div>
);
}
export default ContactForm;🎨 Customization
Custom Styling
All components accept a className prop for custom styling:
<Button
variant="primary"
style="filled"
className="shadow-lg hover:shadow-xl transform hover:scale-105"
>
Custom Button
</Button>
<Typography
variant="title-h1"
className="text-gradient bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent"
>
Gradient Title
</Typography>Theme Customization
You can customize the appearance by extending your Tailwind config:
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
}
}
}
}
}🔧 TypeScript Support
This library is built with TypeScript and provides full type definitions:
import { Button, Typography, Notification } from '@cibobu/react-toast-popup';
import type { ButtonProps, TypographyProps } from '@cibobu/react-toast-popup';
// Fully typed props
const MyButton: React.FC<ButtonProps> = (props) => {
return <Button {...props} />;
};📱 Browser Support
- Chrome >= 60
- Firefox >= 60
- Safari >= 12
- Edge >= 79
🔧 Troubleshooting
Button Styles Not Appearing?
Problem: Button appears without styles (no colors, padding, etc.)
Solution: You need to import the CSS. Choose one:
Easy way (Recommended):
import '@cibobu/react-toast-popup/dist/styles/tailwind-fallback.css';
With Tailwind CSS:
npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p
Then add to your
tailwind.config.js:content: [ "./src/**/*.{js,jsx,ts,tsx}", "./node_modules/@cibobu/react-toast-popup/**/*.{js,ts,jsx,tsx}" ]
Error: "could not determine executable to run"
Problem: npx tailwindcss init -p fails
Solution: Install Tailwind CSS first:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -pReact Context Error
Problem: "Cannot read properties of undefined (reading 'ReactCurrentDispatcher')"
Solution: Make sure React is installed in your project:
npm install react react-dom🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- React - The UI library
- Tailwind CSS - The CSS framework
- TypeScript - Type safety
- React Icons - Icon library
Made with ❤️ by @cibobu