Demo · progreso simulado
Encendiendo motores…0%
Tu web ya está lista.
Mientras cargaba, Marciano te hacía compañía. Al terminar guiña un ojo, se apaga en una nube de humo y deja paso al contenido.
Ligero
Un único archivo JS, sin dependencias. Se pausa solo cuando no está en pantalla.
Con entrada y salida
enter()lo enciende desde chispas yexit()lo apaga en humo. Ambas devuelven promesas.Con progreso real
En tu web no hace falta simular: escucha
window.loado tus propias peticiones.
Llévatelo a tu web
Esta demo simula el progreso durante unos 3 segundos para que puedas verlo. En producción basta con encenderlo al empezar y apagarlo cuando la página termina de cargar.
React / Next.js
MarcianoLoader"use client";
// components/marciano-loader.tsx
import { useEffect, useState } from "react";
import { Marciano, useMarciano } from "@hostarys/marciano";
/** Se enciende al montar y se apaga cuando la página termina de cargar. */
export function MarcianoLoader() {
const [ref, marciano] = useMarciano();
const [done, setDone] = useState(false);
useEffect(() => {
let cancelled = false;
const entered = marciano.enter(); // se enciende
const finish = async () => {
await entered;
marciano.play("wink"); // ¡listo!
await new Promise(r => setTimeout(r, 900));
await marciano.exit(); // se apaga en humo
if (!cancelled) setDone(true);
};
if (document.readyState === "complete") finish();
else addEventListener("load", finish, { once: true });
return () => { cancelled = true; removeEventListener("load", finish); };
}, [marciano]);
return (
<div className={done ? "marciano-loader done" : "marciano-loader"} role="status" aria-label="Cargando">
<Marciano ref={ref} color="hostarys" glow hiddenStart sleepAfter={0} size={170} />
</div>
);
}// app/layout.tsx
import { MarcianoLoader } from "@/components/marciano-loader";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="es">
<body>
<MarcianoLoader />
{children}
</body>
</html>
);
}
/* globals.css */
.marciano-loader { position: fixed; inset: 0; z-index: 100;
display: grid; place-items: center; background: #efebe2;
transition: opacity .6s, visibility 0s .6s; }
.marciano-loader.done { opacity: 0; visibility: hidden; }HTML sin frameworks
<!-- justo después de <body> -->
<div id="loader">
<marciano-flame color="hostarys" glow
hidden-start sleep-after="0"></marciano-flame>
</div>
<style>
#loader { position: fixed; inset: 0; z-index: 100;
display: grid; place-items: center; background: #efebe2;
transition: opacity .6s, visibility 0s .6s; }
#loader.done { opacity: 0; visibility: hidden; }
</style><script src="marciano-flame.js"></script>
<script>
const loader = document.getElementById("loader");
const m = loader.querySelector("marciano-flame");
m.enter(); // se enciende
addEventListener("load", async () => {
m.play("wink"); // ¡listo!
await new Promise(r => setTimeout(r, 900));
await m.exit(); // se apaga en humo
loader.classList.add("done");
});
</script>