Navigation
Elegance supports client-side navigation through the global navigate function in the browser and the built-in <Link> component.
Usage
import { Link } from "elegance-js";
export default function Page() {
return <div>
<Link href={"/blog"}>Go to Blog</Link>
<Link href={"/recipes"}>Go to Recipes</Link>
</div>
}The navigate Function
Navigation is also possible programmatically via the navigate function; which is globally accessible in the browser.
You can use it like so:
navigate("/blogs", true, true);The first parameter determines the pathname, the second parameter determines whether or not to push to the history stack and the third parameter determines whether or not to use the view-transitions api (overrides the value defined in the config).
How client-side Navigation Works
async function navigate(url: string, push = true, vt?: boolean): Promise<void> {
const target = new URL(url, location.href);
if (target.pathname === location.pathname) {
if (push && target.href !== location.href) history.pushState(null, "", url);
scroll();
return;
}
if (push) history.pushState(null, "", url);
const doc = new DOMParser().parseFromString(
await (await fetch(url, { headers: { Accept: "text/html" } })).text(),
"text/html",
);
const tag = doc.querySelector<HTMLScriptElement>(`script[data-bundle="true"][data-pathname="${target.pathname}"]`);
if (doc.querySelector('template[data-region]')) await ensureRuntime();
let mod: any;
if (tag) {
mod = await importBundle(tag);
} else {
try {
mod = await import(`${target.pathname === "/" ? "" : target.pathname}/bundle.js`);
} catch {
console.error("navigate: no bundle found for this pathname.");
return;
}
}
runPageCleanup();
const result = (mod.default ?? (() => null))();
if (!Array.isArray(result?.regions)) {
console.error("navigate: target is not an Elegance page.");
return;
}
if (result.handlers?.length && !globalThis.__hydrate) await ensureRuntime();
const apply = () => loadPage(url, result.regions, result.handlers, doc);
const wantsVT = typeof document.startViewTransition === "function" && !prefersReducedMotion() && (vt ?? __VIEW_TRANSITIONS);
if (wantsVT) {
const t = document.startViewTransition(() => apply());
try { await t.finished; } catch {}
} else {
await apply();
}
runPageCallbacks();
globalThis.__navCallbacks.forEach(f => f());
scroll();
}