UNPKG

@divetocode/toast

Version:

A lightweight toast notification system for React/Next.js

97 lines (92 loc) 3.16 kB
// src/Toast.tsx var listener = null; var showToast = (message, options) => { listener?.(message, options); }; var _internalSetToastListener = (fn) => { listener = fn; }; // src/ToastRoot.tsx import { useEffect, useState } from "react"; import { createPortal } from "react-dom"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var toastId = 0; var ToastRoot = () => { const [toasts, setToasts] = useState([]); const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); _internalSetToastListener((message, options) => { const id = toastId++; const type = options?.type || "success"; setToasts((prev) => [...prev, { id, message, type }]); setTimeout(() => { setToasts((prev) => prev.filter((t) => t.id !== id)); }, 5e3); }); }, []); if (!mounted) return null; return createPortal( /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("style", { children: ` @keyframes slide-in { 0% { opacity: 0; transform: translateX(100%); } 100% { opacity: 1; transform: translateX(0); } } .toast-container { position: fixed; top: 1.5rem; /* top-6 */ right: 1.5rem; /* right-6 */ z-index: 50; display: flex; flex-direction: column; align-items: flex-end; gap: 0.5rem; /* space-y-2 */ pointer-events: none; } .toast-base { position: relative; width: 100%; max-width: 20rem; /* max-w-xs */ padding: 0.5rem 1rem; /* px-4 py-2 */ margin-top: 0.5rem; /* mt-2 */ border-radius: 0.375rem; /* rounded-md */ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* shadow-lg */ font-size: 0.875rem; /* text-sm */ font-weight: 500; /* font-medium */ transition: all 0.5s; /* transition-all duration-500 */ transform: translateX(0); /* transform */ animation: slide-in 0.3s ease-out; /* animate-slide-in */ } .toast-success { background-color: #d1fae5; /* bg-green-100 */ color: #065f46; /* text-green-900 */ border: 1px solid #a7f3d0; /* border-green-300 */ } .toast-error { background-color: #fee2e2; /* bg-red-100 */ color: #991b1b; /* text-red-900 */ border: 1px solid #fca5a5; /* border-red-300 */ } ` }), /* @__PURE__ */ jsx("div", { className: "toast-container", children: toasts.map((t) => { const typeClass = t.type === "error" ? "toast-error" : "toast-success"; return /* @__PURE__ */ jsx("div", { className: `toast-base ${typeClass}`, children: t.message }, t.id); }) }) ] }), document.body ); }; var ToastRoot_default = ToastRoot; export { ToastRoot_default as ToastRoot, showToast }; //# sourceMappingURL=index.mjs.map