Concorde functional component — Router. sonic-router watches document.location (pathname + hash) and renders the matching view. Doc ID: core/components/functional/router/router. Keywords: Concorde, supersoniks, core/components/functional/router/router, router, Router, functional component, sonic-router, web component, document.location, .routes, .items, fallback, , pathname + hash, #home, #…/router.md/router, #…/router#home, href. URL: https://concorde.supersoniks.org/crawl/core/components/functional/router/router.html.
Router
sonic-router watches document.location (pathname + hash) and renders the matching view.
From a Lit parent, pass a .routes map (property binding — same rule as .items on list): keys are path patterns, values are render functions. Use fallback when nothing matches.
Legacy HTML <template data-route="…"> remains for hosts without Lit — HTML integration.
Static routes (no parameters)
Route keys are matched against pathname + hash. A simple hash route #home matches when the location contains that segment.
On the doc site, the page URL is already a hash (../../../../…/router.html#router). Demos append a second hash for in-page routes (#…/router#home), use href + autoActive="strict" on sonic-button for the active state, and history.replaceState on click so markdown is not reloaded (setDocsDemoSubHash in src/docs/docs-location.ts).
@state()
private routes = {
"#home": () => html`<div>Home</div>`,
"#about": () => html`<div>About</div>`,
fallback: () => html`<div>Not found</div>`,
};
html`
<sonic-button href="#home">Home</sonic-button>
<sonic-router .routes=${this.routes}></sonic-router>
`;
| Key | When it runs |
|---|---|
"#home", "#about", … |
RegExp or url-pattern test succeeds on current location |
fallback |
No other route matched (not an attribute — a key on the same object) |
Routes with parameters
Two styles (see router.demo.ts and docs-router-params-demo):
Url-pattern (:name)
Key uses :param segments. The render function receives an object { param: string }.
"#couleur/:id": ({ id }) => html`<p>Colour id: ${id}</p>`,
RegExp (capturing groups)
Key is a RegExp string with (\d+) / (\w+) groups. The render function receives an array of captured strings (in order).
"#products/(\\d+)/(\\w+)": ([productId, slug]) =>
html`<p>Product ${productId}, slug ${slug}</p>`,
With parameters you usually render data directly in Lit (${id}). The old <template data-route> + dataProviderExpression pattern scoped a dataProvider for data-bind / fetch children — prefer @subscribe or explicit props when using .routes.
.routes binding
Always use .routes=${…} in Lit templates: route handlers are functions and must be set as properties, not HTML attributes.
Optional attributes
| Attribute | Role |
|---|---|
basePath |
Prefix for pattern matching (default allows optional leading segments) |
fallBackRoute |
If set and no template/route matches, navigates to this URL (redirect). Distinct from routes.fallback which only renders content |
sonic-redirect
Separate component: redirect when data appears on a publisher (login steps, wizards). Not part of the .routes map.
<sonic-redirect to="./router.html#router#data-is-set" dataProvider="stupid-data-set-id" onData="theData"></sonic-redirect>
<div class="flex gap-2 mb-4" formDataProvider="stupid-data-set-id">
<sonic-button radio name="theData" value="Some Data" size="xs">
Enter data
</sonic-button>
<sonic-button radio name="theData" value="" href="javascript:history.back();" size="xs">
Delete the data and do a history.back()
</sonic-button>
</div>
Example: combine with .routes and submit for login / logout / profile steps.
Package demo
sonic-router-demo (router.demo.ts) — home, user profile (#user/:id/:slug), products RegExp, fallback 404.