UNPKG

react-toast-kit

Version:

A modern, accessible toast notification system for React applications with automatic CSS injection

13 lines (10 loc) 13.5 kB
// CSS as JS module for better bundler support const css = "/* Base toast container styles */\n.react-toast-container {\n position: fixed;\n z-index: 99999; /* Tăng z-index để hiển thị trên tất cả component */\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n pointer-events: none;\n}\n\n.react-toast-container[data-position=\"top-right\"] {\n top: 1rem;\n right: 1rem;\n align-items: flex-end;\n}\n\n.react-toast-container[data-position=\"top-center\"] {\n top: 1rem;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.react-toast-container[data-position=\"top-left\"] {\n top: 1rem;\n left: 1rem;\n align-items: flex-start;\n}\n\n.react-toast-container[data-position=\"bottom-right\"] {\n bottom: 1rem;\n right: 1rem;\n align-items: flex-end;\n}\n\n.react-toast-container[data-position=\"bottom-center\"] {\n bottom: 1rem;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.react-toast-container[data-position=\"bottom-left\"] {\n bottom: 1rem;\n left: 1rem;\n align-items: flex-start;\n}\n\n/* Toast item styles */\n.react-toast-item {\n width: 100%;\n pointer-events: auto;\n max-width: 380px;\n}\n\n@media (max-width: 640px) {\n .react-toast-item {\n max-width: 92vw;\n }\n}\n\n/* Toast styles */\n.react-toast {\n position: relative;\n overflow: hidden;\n padding: 0.5rem;\n border-radius: 0.5rem;\n box-shadow: \n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04),\n 0 0 0 1px rgba(0, 0, 0, 0.05); /* Thêm border subtle */\n font-family: system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n font-size: 0.95rem;\n word-break: break-word;\n -webkit-hyphens: auto;\n -moz-hyphens: auto;\n hyphens: auto;\n backdrop-filter: blur(8px); /* Thêm blur effect */\n -webkit-backdrop-filter: blur(8px); /* Safari support */\n}\n\n/* Add glass effect styling from docs */\n.react-toast[data-style=\"glass\"] {\n background: rgba(255, 255, 255, 0.9); /* Tăng opacity để rõ hơn */\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px);\n border: 1px solid rgba(255, 255, 255, 0.3);\n box-shadow: \n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04),\n inset 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n\n.react-toast[data-theme=\"dark\"][data-style=\"glass\"] {\n background: rgba(15, 23, 42, 0.9); /* Tăng opacity cho dark mode */\n backdrop-filter: blur(20px);\n -webkit-backdrop-filter: blur(20px);\n border: 1px solid rgba(255, 255, 255, 0.1);\n box-shadow: \n 0 20px 25px -5px rgba(0, 0, 0, 0.3),\n 0 10px 10px -5px rgba(0, 0, 0, 0.1),\n inset 0 1px 0 rgba(255, 255, 255, 0.05);\n}\n\n/* Gradient style */\n.react-toast[data-style=\"gradient\"] {\n background-image: linear-gradient(to right, var(--toast-gradient-from, rgba(59, 130, 246, 0.7)), var(--toast-gradient-to, rgba(37, 99, 235, 0.8)));\n}\n\n/* Shimmer effect styling */\n.react-toast[data-style=\"shimmer\"] {\n position: relative;\n overflow: hidden;\n}\n\n.react-toast[data-style=\"shimmer\"]::after {\n content: '';\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.2), transparent);\n animation: shimmer 2s linear infinite;\n}\n\n@keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n}\n\n/* Neon effect */\n.react-toast[data-style=\"neon\"] {\n box-shadow: 0 0 20px rgba(59, 130, 246, 0.5);\n animation: pulse-glow 2s ease-in-out infinite;\n}\n\n@keyframes pulse-glow {\n 0%, 100% { box-shadow: 0 0 5px rgba(59, 130, 246, 0.5); }\n 50% { box-shadow: 0 0 20px rgba(59, 130, 246, 0.5), 0 0 30px rgba(59, 130, 246, 0.3); }\n}\n\n/* Pill style */\n.react-toast[data-style=\"pill\"] {\n border-radius: 50px;\n}\n\n/* Retro style */\n.react-toast[data-style=\"retro\"] {\n border: 2px solid #000;\n box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.9);\n}\n\n.react-toast[data-theme=\"dark\"][data-style=\"retro\"] {\n border: 2px solid #fff;\n box-shadow: 4px 4px 0px rgba(255, 255, 255, 0.7);\n}\n\n/* Confetti style */\n.react-toast[data-style=\"confetti\"] {\n background-image: url(\"data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M11 18c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm48 25c3.866 0 7-3.134 7-7s-3.134-7-7-7-7 3.134-7 7 3.134 7 7 7zm-43-7c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm63 31c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM34 90c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zm56-76c1.657 0 3-1.343 3-3s-1.343-3-3-3-3 1.343-3 3 1.343 3 3 3zM12 86c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm28-65c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm23-11c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-6 60c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm29 22c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zM32 63c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm57-13c2.76 0 5-2.24 5-5s-2.24-5-5-5-5 2.24-5 5 2.24 5 5 5zm-9-21c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM60 91c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM35 41c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2zM12 60c1.105 0 2-.895 2-2s-.895-2-2-2-2 .895-2 2 .895 2 2 2z' fill='rgba(255,255,255,.1)' fill-opacity='0.1' fill-rule='evenodd'/%3E%3C/svg%3E\");\n}\n\n/* Variant styles */\n.react-toast[data-variant=\"success\"] {\n background-color: #10b981;\n color: #ffffff;\n box-shadow: \n 0 20px 25px -5px rgba(16, 185, 129, 0.3),\n 0 10px 10px -5px rgba(16, 185, 129, 0.1);\n}\n\n.react-toast[data-variant=\"error\"] {\n background-color: #ef4444;\n color: #ffffff;\n box-shadow: \n 0 20px 25px -5px rgba(239, 68, 68, 0.3),\n 0 10px 10px -5px rgba(239, 68, 68, 0.1);\n}\n\n.react-toast[data-variant=\"warning\"] {\n background-color: #f59e0b;\n color: #ffffff;\n box-shadow: \n 0 20px 25px -5px rgba(245, 158, 11, 0.3),\n 0 10px 10px -5px rgba(245, 158, 11, 0.1);\n}\n\n.react-toast[data-variant=\"info\"] {\n background-color: #3b82f6;\n color: #ffffff;\n box-shadow: \n 0 20px 25px -5px rgba(59, 130, 246, 0.3),\n 0 10px 10px -5px rgba(59, 130, 246, 0.1);\n}\n\n.react-toast[data-variant=\"loading\"] {\n background-color: #6b7280;\n color: #ffffff;\n box-shadow: \n 0 20px 25px -5px rgba(107, 114, 128, 0.3),\n 0 10px 10px -5px rgba(107, 114, 128, 0.1);\n}\n\n.react-toast[data-variant=\"default\"] {\n background-color: #ffffff;\n color: #1f2937;\n border: 1px solid #e5e7eb;\n box-shadow: \n 0 20px 25px -5px rgba(0, 0, 0, 0.1),\n 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n}\n\n/* Dark mode variants with stronger contrast */\n.react-toast[data-theme=\"dark\"][data-variant=\"success\"] {\n background-color: #047857; /* Darker but still visible */\n color: #ffffff;\n border: 1px solid #059669;\n box-shadow: \n 0 20px 25px -5px rgba(4, 120, 87, 0.4),\n 0 10px 10px -5px rgba(4, 120, 87, 0.2);\n}\n\n.react-toast[data-theme=\"dark\"][data-variant=\"error\"] {\n background-color: #b91c1c; /* Darker but still visible */\n color: #ffffff;\n border: 1px solid #dc2626;\n box-shadow: \n 0 20px 25px -5px rgba(185, 28, 28, 0.4),\n 0 10px 10px -5px rgba(185, 28, 28, 0.2);\n}\n\n.react-toast[data-theme=\"dark\"][data-variant=\"warning\"] {\n background-color: #b45309; /* Darker but still visible */\n color: #ffffff;\n border: 1px solid #d97706;\n box-shadow: \n 0 20px 25px -5px rgba(180, 83, 9, 0.4),\n 0 10px 10px -5px rgba(180, 83, 9, 0.2);\n}\n\n.react-toast[data-theme=\"dark\"][data-variant=\"info\"] {\n background-color: #1d4ed8; /* Darker but still visible */\n color: #ffffff;\n border: 1px solid #2563eb;\n box-shadow: \n 0 20px 25px -5px rgba(29, 78, 216, 0.4),\n 0 10px 10px -5px rgba(29, 78, 216, 0.2);\n}\n\n.react-toast[data-theme=\"dark\"][data-variant=\"loading\"] {\n background-color: #4b5563; /* Darker but still visible */\n color: #ffffff;\n border: 1px solid #6b7280;\n box-shadow: \n 0 20px 25px -5px rgba(75, 85, 99, 0.4),\n 0 10px 10px -5px rgba(75, 85, 99, 0.2);\n}\n\n.react-toast[data-theme=\"dark\"][data-variant=\"default\"] {\n background-color: #1f2937;\n color: #f9fafb;\n border: 1px solid #374151;\n box-shadow: \n 0 20px 25px -5px rgba(0, 0, 0, 0.3),\n 0 10px 10px -5px rgba(0, 0, 0, 0.1);\n}\n\n/* Toast content */\n.toast-content {\n display: flex;\n flex-direction: column;\n}\n\n/* Title */\n.react-toast h4 {\n margin: 0;\n font-size: 1rem;\n font-weight: 600;\n line-height: 1.5;\n}\n\n/* Description */\n.react-toast div:not(.toast-content) {\n /* margin-top: 0.25rem; */\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n/* Icon container */\n.toast-icon-container {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n margin-right: 0.75rem;\n}\n\n.toast-icon-animated {\n animation: toast-icon-animation 1s ease-in-out;\n}\n\n@keyframes toast-icon-animation {\n 0% {\n transform: scale(0);\n opacity: 0;\n }\n 50% {\n transform: scale(1.2);\n }\n 100% {\n transform: scale(1);\n opacity: 1;\n }\n}\n\n/* Progress bar */\n.react-toast-progress {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 3px;\n}\n\n.react-toast[data-progress-position=\"top\"] .react-toast-progress {\n top: 0;\n bottom: auto;\n}\n\n.react-toast[data-progress-position=\"left\"] .react-toast-progress {\n top: 0;\n bottom: 0;\n right: auto;\n width: 3px;\n height: 100%;\n}\n\n.react-toast[data-progress-position=\"right\"] .react-toast-progress {\n top: 0;\n bottom: 0;\n left: auto;\n width: 3px;\n height: 100%;\n}\n\n.react-toast-progress-fill {\n height: 100%;\n width: 100%;\n}\n\n/* Enhanced progress bar styles */\n.react-toast-progress.fancy {\n background: linear-gradient(to right, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.2));\n backdrop-filter: blur(4px);\n}\n\n.react-toast-progress.gradient-wave .react-toast-progress-fill {\n background: linear-gradient(90deg, #3b82f6, #8b5cf6, #ec4899, #3b82f6);\n background-size: 300% 100%;\n animation: gradient-wave 2s linear infinite;\n}\n\n@keyframes gradient-wave {\n 0% { background-position: 0% 50%; }\n 100% { background-position: 100% 50%; }\n}\n\n.react-toast-progress.pulse .react-toast-progress-fill {\n animation: progress-pulse 2s infinite;\n}\n\n@keyframes progress-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n}\n\n.react-toast-progress.three-d .react-toast-progress-fill {\n box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);\n}\n\n.react-toast-progress.glow .react-toast-progress-fill {\n box-shadow: 0 0 10px rgba(255, 255, 255, 0.7);\n}\n\n.react-toast-progress.rainbow .react-toast-progress-fill {\n background: linear-gradient(90deg, red, orange, yellow, green, blue, indigo, violet);\n background-size: 700% 100%;\n animation: rainbow 4s linear infinite;\n}\n\n@keyframes rainbow {\n 0% { background-position: 0% 50%; }\n 50% { background-position: 100% 50%; }\n 100% { background-position: 0% 50%; }\n}\n\n.react-toast-progress.dashed .react-toast-progress-fill {\n background-image: linear-gradient(to right, currentColor 50%, transparent 50%);\n background-size: 20px 100%;\n}\n\n/* Close button */\n.react-toast-close {\n position: absolute;\n top: 0.75rem;\n right: 0.75rem;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 1.5rem;\n height: 1.5rem;\n border: none;\n background: transparent;\n color: currentColor;\n opacity: 0.5;\n cursor: pointer;\n transition: opacity 0.2s;\n}\n\n.react-toast-close:hover {\n opacity: 1;\n}\n\n/* Ripple effect */\n.toast-ripple {\n position: relative;\n overflow: hidden;\n}\n\n.toast-ripple-element {\n position: absolute;\n border-radius: 50%;\n background-color: rgba(255, 255, 255, 0.3);\n width: 100px;\n height: 100px;\n margin-top: -50px;\n margin-left: -50px;\n animation: ripple 0.7s linear;\n transform: scale(0);\n opacity: 0.5;\n pointer-events: none;\n}\n\n@keyframes ripple {\n to {\n transform: scale(4);\n opacity: 0;\n }\n}\n\n/* Floating animation */\n.react-toast-floating {\n animation: float 3s ease-in-out infinite;\n}\n\n@keyframes float {\n 0% {\n transform: translateY(0);\n }\n 50% {\n transform: translateY(-5px);\n }\n 100% {\n transform: translateY(0);\n }\n}\n\n/* Accessibility */\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n\n/* Mobile optimizations */\n@media (max-width: 640px) {\n .react-toast-container {\n width: calc(100% - 2rem);\n max-width: 100%;\n }\n\n .react-toast-item {\n width: 100%;\n }\n\n .react-toast {\n font-size: 0.9rem;\n }\n\n .toast-content {\n padding: 0.75rem;\n }\n\n /* Improved touch targets */\n .react-toast-close {\n width: 2rem;\n height: 2rem;\n }\n}"; // Auto-inject CSS if in browser environment if (typeof document !== 'undefined' && !document.getElementById('react-toast-kit-styles')) { const style = document.createElement('style'); style.id = 'react-toast-kit-styles'; style.textContent = css; document.head.appendChild(style); } export default css;