Add a collapse/expand-all toggle to the pedigree

A header button folds the whole tree down to just the dog or opens every
branch at once, alongside the per-dog toggles. Grouped with the zoom
controls, which the header now wraps on narrow screens.
This commit is contained in:
Alexander Heldt
2026-07-26 10:50:12 +00:00
parent 12a5bd0548
commit a2c9aa9716
4 changed files with 31 additions and 5 deletions
+14
View File
@@ -2486,6 +2486,19 @@
pedZoomIn.addEventListener("click", () => pedZoomBy(0.2)); pedZoomIn.addEventListener("click", () => pedZoomBy(0.2));
pedZoomOut.addEventListener("click", () => pedZoomBy(-0.2)); pedZoomOut.addEventListener("click", () => pedZoomBy(-0.2));
pedZoomReset.addEventListener("click", () => { pedZoom = 1; applyPedZoom(); }); pedZoomReset.addEventListener("click", () => { pedZoom = 1; applyPedZoom(); });
// ---- collapse / expand all ----
const pedFoldAll = document.getElementById("ped-foldall");
function pedSetAll(collapsed) {
pedTree.querySelectorAll("li").forEach((li) => {
if (!li.querySelector(":scope > ul")) return; // no ancestors to fold
li.classList.toggle("collapsed", collapsed);
const t = li.querySelector(":scope > .ped-card > .ped-toggle");
if (t) t.textContent = collapsed ? "+" : "";
});
pedFoldAll.textContent = collapsed ? "Expand all" : "Collapse all";
}
pedFoldAll.addEventListener("click", () => pedSetAll(pedFoldAll.textContent[0] === "C"));
// Trackpad/desktop: ctrl or ⌘ + wheel zooms instead of scrolling the page. // Trackpad/desktop: ctrl or ⌘ + wheel zooms instead of scrolling the page.
pedTree.addEventListener("wheel", (e) => { pedTree.addEventListener("wheel", (e) => {
if (!e.ctrlKey && !e.metaKey) return; if (!e.ctrlKey && !e.metaKey) return;
@@ -2729,6 +2742,7 @@
ul.className = "ped-tree-h"; ul.className = "ped-tree-h";
ul.append(root); ul.append(root);
pedTree.append(ul); pedTree.append(ul);
if (pedFoldAll) pedFoldAll.textContent = "Collapse all"; // fresh tree starts partly open
} }
// Highlight (or unhighlight) every card that is the same dog as `key`. // Highlight (or unhighlight) every card that is the same dog as `key`.
+1
View File
@@ -1,4 +1,5 @@
[ [
{ "date": "2026-07-26", "text": "Added a Collapse all / Expand all toggle to the pedigree, to fold the whole tree down to your dog or open every branch at once" },
{ "date": "2026-07-26", "text": "The pedigree is now zoomable — use the +/ buttons, ⌘/Ctrl-scroll, or pinch on a phone — to fit a wide tree on screen or zoom in for detail; your zoom level is remembered" }, { "date": "2026-07-26", "text": "The pedigree is now zoomable — use the +/ buttons, ⌘/Ctrl-scroll, or pinch on a phone — to fit a wide tree on screen or zoom in for detail; your zoom level is remembered" },
{ "date": "2026-07-26", "text": "In the pedigree, a dog that fills more than one spot (pedigree collapse, common in a breed's older lines) now carries a ×N badge — tap it to highlight every place that dog appears in the tree" }, { "date": "2026-07-26", "text": "In the pedigree, a dog that fills more than one spot (pedigree collapse, common in a breed's older lines) now carries a ×N badge — tap it to highlight every place that dog appears in the tree" },
{ "date": "2026-07-26", "text": "The pedigree now reads top-down like a family tree — your dog on top with its sire and dam branching below — showing three generations at a glance, with each dog expandable to trace the line further back" }, { "date": "2026-07-26", "text": "The pedigree now reads top-down like a family tree — your dog on top with its sire and dam branching below — showing three generations at a glance, with each dog expandable to trace the line further back" },
+3
View File
@@ -280,11 +280,14 @@
<header class="pedigree-header"> <header class="pedigree-header">
<button type="button" id="pedigree-back" class="ghost icon-btn" aria-label="Back to tracker" title="Back"></button> <button type="button" id="pedigree-back" class="ghost icon-btn" aria-label="Back to tracker" title="Back"></button>
<h1>🌳 Pedigree</h1> <h1>🌳 Pedigree</h1>
<div class="ped-controls">
<button type="button" id="ped-foldall" class="ghost">Collapse all</button>
<div class="ped-zoom" role="group" aria-label="Zoom"> <div class="ped-zoom" role="group" aria-label="Zoom">
<button type="button" id="ped-zoom-out" class="ghost icon-btn" aria-label="Zoom out" title="Zoom out"></button> <button type="button" id="ped-zoom-out" class="ghost icon-btn" aria-label="Zoom out" title="Zoom out"></button>
<button type="button" id="ped-zoom-reset" class="ghost" aria-label="Reset zoom" title="Reset zoom">100%</button> <button type="button" id="ped-zoom-reset" class="ghost" aria-label="Reset zoom" title="Reset zoom">100%</button>
<button type="button" id="ped-zoom-in" class="ghost icon-btn" aria-label="Zoom in" title="Zoom in">+</button> <button type="button" id="ped-zoom-in" class="ghost icon-btn" aria-label="Zoom in" title="Zoom in">+</button>
</div> </div>
</div>
</header> </header>
<main class="pedigree-main"> <main class="pedigree-main">
<p class="muted-note pedigree-hint"> <p class="muted-note pedigree-hint">
+9 -1
View File
@@ -1065,9 +1065,17 @@ section.collapsed > :not(h2) { display: none; }
gap: 10px; gap: 10px;
padding: 12px 4px 8px; padding: 12px 4px 8px;
} }
.pedigree-header { flex-wrap: wrap; }
.pedigree-header h1 { font-size: 1.4rem; } .pedigree-header h1 { font-size: 1.4rem; }
.ped-zoom { .ped-controls {
margin-left: auto; margin-left: auto;
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
}
#ped-foldall { padding: 5px 10px; font-size: 0.8rem; white-space: nowrap; }
.ped-zoom {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 4px;