Implement Toast component for notifications
This commit is contained in:
63
src/components/Toast.js
Normal file
63
src/components/Toast.js
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { $html, $mount } from "sigpro";
|
||||||
|
import { Button } from "./Button.js";
|
||||||
|
|
||||||
|
/** TOAST (Imperative Function) */
|
||||||
|
export const Toast = (message, type = "alert-success", duration = 3500) => {
|
||||||
|
let container = document.getElementById("sigpro-toast-container");
|
||||||
|
|
||||||
|
// Crear el contenedor global si no existe
|
||||||
|
if (!container) {
|
||||||
|
container = $html("div", {
|
||||||
|
id: "sigpro-toast-container",
|
||||||
|
class: "fixed top-0 right-0 z-[9999] p-4 flex flex-col gap-2 pointer-events-none",
|
||||||
|
});
|
||||||
|
document.body.appendChild(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
const toastHost = $html("div", { style: "display: contents" });
|
||||||
|
container.appendChild(toastHost);
|
||||||
|
|
||||||
|
let timeoutId;
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
const el = toastHost.firstElementChild;
|
||||||
|
if (el && !el.classList.contains("opacity-0")) {
|
||||||
|
el.classList.add("translate-x-full", "opacity-0");
|
||||||
|
setTimeout(() => {
|
||||||
|
instance.destroy();
|
||||||
|
toastHost.remove();
|
||||||
|
// Limpiar el contenedor si ya no hay más toasts
|
||||||
|
if (!container.hasChildNodes()) container.remove();
|
||||||
|
}, 300);
|
||||||
|
} else {
|
||||||
|
instance.destroy();
|
||||||
|
toastHost.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ToastComponent = () => {
|
||||||
|
const el = $html(
|
||||||
|
"div",
|
||||||
|
{
|
||||||
|
class: `alert alert-soft ${type} shadow-lg transition-all duration-300 translate-x-10 opacity-0 pointer-events-auto`,
|
||||||
|
},
|
||||||
|
[
|
||||||
|
$html("span", {}, [typeof message === "function" ? message() : message]),
|
||||||
|
Button({ class: "btn-xs btn-circle btn-ghost", onclick: close }, "✕")
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Animación de entrada
|
||||||
|
requestAnimationFrame(() => el.classList.remove("translate-x-10", "opacity-0"));
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
const instance = $mount(ToastComponent, toastHost);
|
||||||
|
|
||||||
|
if (duration > 0) {
|
||||||
|
timeoutId = setTimeout(close, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
return close;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user