Implement Toast component for notifications

This commit is contained in:
Natxo
2026-03-31 12:19:37 +02:00
committed by GitHub
parent b5263d2ab3
commit a4283ac66b

63
src/components/Toast.js Normal file
View 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;
};