UNPKG

react-toast-kit

Version:

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

506 lines (439 loc) 12.5 kB
/* Base toast container styles */ .react-toast-container { position: fixed; z-index: 99999; /* Tăng z-index để hiển thị trên tất cả component */ display: flex; flex-direction: column; gap: 0.5rem; pointer-events: none; } .react-toast-container[data-position="top-right"] { top: 1rem; right: 1rem; align-items: flex-end; } .react-toast-container[data-position="top-center"] { top: 1rem; left: 50%; transform: translateX(-50%); align-items: center; } .react-toast-container[data-position="top-left"] { top: 1rem; left: 1rem; align-items: flex-start; } .react-toast-container[data-position="bottom-right"] { bottom: 1rem; right: 1rem; align-items: flex-end; } .react-toast-container[data-position="bottom-center"] { bottom: 1rem; left: 50%; transform: translateX(-50%); align-items: center; } .react-toast-container[data-position="bottom-left"] { bottom: 1rem; left: 1rem; align-items: flex-start; } /* Toast item styles */ .react-toast-item { width: 100%; pointer-events: auto; max-width: 380px; } @media (max-width: 640px) { .react-toast-item { max-width: 92vw; } } /* Toast styles */ .react-toast { position: relative; overflow: hidden; padding: 0.5rem; border-radius: 0.5rem; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04), 0 0 0 1px rgba(0, 0, 0, 0.05); /* Thêm border subtle */ font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; font-size: 0.95rem; word-break: break-word; -webkit-hyphens: auto; -moz-hyphens: auto; hyphens: auto; backdrop-filter: blur(8px); /* Thêm blur effect */ -webkit-backdrop-filter: blur(8px); /* Safari support */ } /* Add glass effect styling from docs */ .react-toast[data-style="glass"] { background: rgba(255, 255, 255, 0.9); /* Tăng opacity để rõ hơn */ backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.3); box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.1); } .react-toast[data-theme="dark"][data-style="glass"] { background: rgba(15, 23, 42, 0.9); /* Tăng opacity cho dark mode */ backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.05); } /* Gradient style */ .react-toast[data-style="gradient"] { 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))); } /* Shimmer effect styling */ .react-toast[data-style="shimmer"] { position: relative; overflow: hidden; } .react-toast[data-style="shimmer"]::after { content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.2), transparent); animation: shimmer 2s linear infinite; } @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } /* Neon effect */ .react-toast[data-style="neon"] { box-shadow: 0 0 20px rgba(59, 130, 246, 0.5); animation: pulse-glow 2s ease-in-out infinite; } @keyframes pulse-glow { 0%, 100% { box-shadow: 0 0 5px rgba(59, 130, 246, 0.5); } 50% { box-shadow: 0 0 20px rgba(59, 130, 246, 0.5), 0 0 30px rgba(59, 130, 246, 0.3); } } /* Pill style */ .react-toast[data-style="pill"] { border-radius: 50px; } /* Retro style */ .react-toast[data-style="retro"] { border: 2px solid #000; box-shadow: 4px 4px 0px rgba(0, 0, 0, 0.9); } .react-toast[data-theme="dark"][data-style="retro"] { border: 2px solid #fff; box-shadow: 4px 4px 0px rgba(255, 255, 255, 0.7); } /* Confetti style */ .react-toast[data-style="confetti"] { 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"); } /* Variant styles */ .react-toast[data-variant="success"] { background-color: #10b981; color: #ffffff; box-shadow: 0 20px 25px -5px rgba(16, 185, 129, 0.3), 0 10px 10px -5px rgba(16, 185, 129, 0.1); } .react-toast[data-variant="error"] { background-color: #ef4444; color: #ffffff; box-shadow: 0 20px 25px -5px rgba(239, 68, 68, 0.3), 0 10px 10px -5px rgba(239, 68, 68, 0.1); } .react-toast[data-variant="warning"] { background-color: #f59e0b; color: #ffffff; box-shadow: 0 20px 25px -5px rgba(245, 158, 11, 0.3), 0 10px 10px -5px rgba(245, 158, 11, 0.1); } .react-toast[data-variant="info"] { background-color: #3b82f6; color: #ffffff; box-shadow: 0 20px 25px -5px rgba(59, 130, 246, 0.3), 0 10px 10px -5px rgba(59, 130, 246, 0.1); } .react-toast[data-variant="loading"] { background-color: #6b7280; color: #ffffff; box-shadow: 0 20px 25px -5px rgba(107, 114, 128, 0.3), 0 10px 10px -5px rgba(107, 114, 128, 0.1); } .react-toast[data-variant="default"] { background-color: #ffffff; color: #1f2937; border: 1px solid #e5e7eb; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); } /* Dark mode variants with stronger contrast */ .react-toast[data-theme="dark"][data-variant="success"] { background-color: #047857; /* Darker but still visible */ color: #ffffff; border: 1px solid #059669; box-shadow: 0 20px 25px -5px rgba(4, 120, 87, 0.4), 0 10px 10px -5px rgba(4, 120, 87, 0.2); } .react-toast[data-theme="dark"][data-variant="error"] { background-color: #b91c1c; /* Darker but still visible */ color: #ffffff; border: 1px solid #dc2626; box-shadow: 0 20px 25px -5px rgba(185, 28, 28, 0.4), 0 10px 10px -5px rgba(185, 28, 28, 0.2); } .react-toast[data-theme="dark"][data-variant="warning"] { background-color: #b45309; /* Darker but still visible */ color: #ffffff; border: 1px solid #d97706; box-shadow: 0 20px 25px -5px rgba(180, 83, 9, 0.4), 0 10px 10px -5px rgba(180, 83, 9, 0.2); } .react-toast[data-theme="dark"][data-variant="info"] { background-color: #1d4ed8; /* Darker but still visible */ color: #ffffff; border: 1px solid #2563eb; box-shadow: 0 20px 25px -5px rgba(29, 78, 216, 0.4), 0 10px 10px -5px rgba(29, 78, 216, 0.2); } .react-toast[data-theme="dark"][data-variant="loading"] { background-color: #4b5563; /* Darker but still visible */ color: #ffffff; border: 1px solid #6b7280; box-shadow: 0 20px 25px -5px rgba(75, 85, 99, 0.4), 0 10px 10px -5px rgba(75, 85, 99, 0.2); } .react-toast[data-theme="dark"][data-variant="default"] { background-color: #1f2937; color: #f9fafb; border: 1px solid #374151; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.1); } /* Toast content */ .toast-content { display: flex; flex-direction: column; } /* Title */ .react-toast h4 { margin: 0; font-size: 1rem; font-weight: 600; line-height: 1.5; } /* Description */ .react-toast div:not(.toast-content) { /* margin-top: 0.25rem; */ font-size: 0.875rem; line-height: 1.5; } /* Icon container */ .toast-icon-container { display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-right: 0.75rem; } .toast-icon-animated { animation: toast-icon-animation 1s ease-in-out; } @keyframes toast-icon-animation { 0% { transform: scale(0); opacity: 0; } 50% { transform: scale(1.2); } 100% { transform: scale(1); opacity: 1; } } /* Progress bar */ .react-toast-progress { position: absolute; bottom: 0; left: 0; right: 0; height: 3px; } .react-toast[data-progress-position="top"] .react-toast-progress { top: 0; bottom: auto; } .react-toast[data-progress-position="left"] .react-toast-progress { top: 0; bottom: 0; right: auto; width: 3px; height: 100%; } .react-toast[data-progress-position="right"] .react-toast-progress { top: 0; bottom: 0; left: auto; width: 3px; height: 100%; } .react-toast-progress-fill { height: 100%; width: 100%; } /* Enhanced progress bar styles */ .react-toast-progress.fancy { background: linear-gradient(to right, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.2)); backdrop-filter: blur(4px); } .react-toast-progress.gradient-wave .react-toast-progress-fill { background: linear-gradient(90deg, #3b82f6, #8b5cf6, #ec4899, #3b82f6); background-size: 300% 100%; animation: gradient-wave 2s linear infinite; } @keyframes gradient-wave { 0% { background-position: 0% 50%; } 100% { background-position: 100% 50%; } } .react-toast-progress.pulse .react-toast-progress-fill { animation: progress-pulse 2s infinite; } @keyframes progress-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .react-toast-progress.three-d .react-toast-progress-fill { box-shadow: 0 0 8px rgba(0, 0, 0, 0.3); } .react-toast-progress.glow .react-toast-progress-fill { box-shadow: 0 0 10px rgba(255, 255, 255, 0.7); } .react-toast-progress.rainbow .react-toast-progress-fill { background: linear-gradient(90deg, red, orange, yellow, green, blue, indigo, violet); background-size: 700% 100%; animation: rainbow 4s linear infinite; } @keyframes rainbow { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } .react-toast-progress.dashed .react-toast-progress-fill { background-image: linear-gradient(to right, currentColor 50%, transparent 50%); background-size: 20px 100%; } /* Close button */ .react-toast-close { position: absolute; top: 0.75rem; right: 0.75rem; display: flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; border: none; background: transparent; color: currentColor; opacity: 0.5; cursor: pointer; transition: opacity 0.2s; } .react-toast-close:hover { opacity: 1; } /* Ripple effect */ .toast-ripple { position: relative; overflow: hidden; } .toast-ripple-element { position: absolute; border-radius: 50%; background-color: rgba(255, 255, 255, 0.3); width: 100px; height: 100px; margin-top: -50px; margin-left: -50px; animation: ripple 0.7s linear; transform: scale(0); opacity: 0.5; pointer-events: none; } @keyframes ripple { to { transform: scale(4); opacity: 0; } } /* Floating animation */ .react-toast-floating { animation: float 3s ease-in-out infinite; } @keyframes float { 0% { transform: translateY(0); } 50% { transform: translateY(-5px); } 100% { transform: translateY(0); } } /* Accessibility */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; } /* Mobile optimizations */ @media (max-width: 640px) { .react-toast-container { width: calc(100% - 2rem); max-width: 100%; } .react-toast-item { width: 100%; } .react-toast { font-size: 0.9rem; } .toast-content { padding: 0.75rem; } /* Improved touch targets */ .react-toast-close { width: 2rem; height: 2rem; } }