Router app
Pages, links and a route parameter, with the router in hash mode.
The router runs in hash mode, so the app works from any static host
and inside the frame below. Each page is a component, and the layout
renders the current one in an Outlet.
Preview
Code
Save it as an .html file and open it in a browser. It loads
Signy and Iris CSS from the CDN, so there is nothing to install or build.
Show the full page
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark">
<title>Router app - Signy example</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/iriscss@1/dist/iris.min.css">
<script src="https://cdn.jsdelivr.net/npm/signy@1/dist/signy.global.min.js"></script>
</head>
<body>
<div id="app"></div>
<script>
const { Component, application, html, router, Link, Outlet, For, Show, useParams, useRouter } = Signy;
const PEOPLE = [
{ id: "ada", name: "Ada Lovelace", known: "the first published computer program" },
{ id: "grace", name: "Grace Hopper", known: "the first compiler" },
{ id: "alan", name: "Alan Turing", known: "the Turing machine" },
];
class Home extends Component {
render() {
return html`
<section class="hero">
<h1>Computing pioneers</h1>
<p>A small app with a router in hash mode, so it works on any static host.</p>
<${Link} to="/people" class="primary" role="button">Meet them</${Link}>
</section>
`;
}
}
class People extends Component {
render() {
return html`
<h1>People</h1>
<div class="grid">
${For({
each: PEOPLE,
keyBy: "id",
children: (person) => html`
<article class="card">
<h2>${person.name}</h2>
<${Link} to=${`/people/${person.id}`}>Read more</${Link}>
</article>
`,
})}
</div>
`;
}
}
class Person extends Component {
render() {
const params = useParams(this);
const nav = useRouter(this);
const person = () => PEOPLE.find((p) => p.id === params.value.id);
return html`
${Show({
when: person,
fallback: html`<p>No one with that name.</p>`,
children: (found) => html`
<h1>${found.name}</h1>
<p>Known for ${found.known}.</p>
`,
})}
<button class="secondary outlined" onClick=${() => nav.back()}>Back</button>
`;
}
}
class NotFound extends Component {
render() {
return html`
<h1>Page not found</h1>
<${Link} to="/">Go home</${Link}>
`;
}
}
class Layout extends Component {
render() {
return html`
<header class="navbar">
<nav class="container" aria-label="Main">
<ul>
<li><${Link} to="/"><strong>Pioneers</strong></${Link}></li>
</ul>
<ul>
<li><${Link} to="/people">People</${Link}></li>
<li><${Link} to="/missing">Broken link</${Link}></li>
</ul>
</nav>
</header>
<main class="container">
<${Outlet} />
</main>
`;
}
}
const appRouter = router({
mode: "hash",
routes: [
{ path: "/", component: Home },
{ path: "/people", component: People },
{ path: "/people/:id", component: Person },
{ path: "*", component: NotFound },
],
});
application(Layout).use(appRouter).mount("#app");
</script>
</body>
</html>
What it uses
- Routes, Link and useRouter(), useParams() and a
*route for the not found page