Replace breadcrumbs with back links; keep the zone header on tab switches

The zone page's breadcrumb (Zones › view) linked the view to a filtered
zone list while the view link below it opened the view. It is now a
single "← Zones" link back to the list with its filters, and a changeset
has "← History". View links carry where they came from, so the views page
offers "← example.org (external)" or "← Zones" (only the UI's own #/
addresses are accepted).

Switching a zone's tabs no longer blanks the page: the header and tabs
show at once and the previous tab stays, faded, until the next has
loaded. The router shows "Loading…" only for pages that take a while.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
abrown38andClaude Opus 5.5 committed 2026-10-09 15:07:55 +00:00
1 parent db9ebb14dd
commit 4b79abf296
8 files changed
+86 -40

No files matched your search

+19 -12
View File
@@ -252,15 +252,16 @@ export function debounce(fn, ms = 250) {
// back to it restores them. The router and list pages fill it in.
export const lastList = {};
// crumbs is a breadcrumb trail above a detail page's heading: the pages
// it belongs to, as [label, href] pairs (the heading names the page).
export function crumbs(...items) {
const out = [];
items.forEach(([label, href], i) => {
if (i > 0) out.push(h("span", { class: "sep", "aria-hidden": "true" }, "›"));
out.push(h("a", { href }, label));
});
return h("nav", { class: "crumbs", "aria-label": "Breadcrumb" }, out);
// backLink is the "← Zones" link above a page's heading, back to the
// page it was opened from.
export function backLink(label, href) {
return h("nav", { class: "back-link", "aria-label": "Back" }, h("a", { href }, "← ", label));
}
// safeBack returns a "back" address taken from the URL if it is one of
// the UI's own (#/...), else null: it ends up in an href.
export function safeBack(v) {
return v && /^#\/[A-Za-z0-9\/?=&%._~+-]*$/.test(v) ? v : null;
}
// The colours a view can be shown in (besides the default, the link
@@ -268,10 +269,16 @@ export function crumbs(...items) {
export const viewColors = ["green", "teal", "purple", "pink", "orange", "yellow", "red", "grey"];
// viewLink links to a view's page, in the view's colour. v is a view
// from /views; name is shown when the view is unknown.
export function viewLink(v, name) {
// from /views; name is shown when the view is unknown. back is the
// address the views page offers to go back to (the current page).
export function viewLink(v, name, back) {
if (!v) return name ? h("span", null, name) : h("span", { class: "muted" }, "–");
return h("a", { href: "#/views?view=" + v.id, class: v.color ? "vc-" + v.color : null, title: "View " + v.name }, v.name);
return h("a", { href: viewHref(v.id, back), class: v.color ? "vc-" + v.color : null, title: "View " + v.name }, v.name);
}
// viewHref is the address of a view on the views page.
export function viewHref(id, back) {
return "#/views?view=" + id + (back ? "&back=" + encodeURIComponent(back) : "");
}
// colorPicker picks a view colour; its value is "" for the default.