Make info panels collapsible with remembered state
Each main section with a data-panel key can now be folded by clicking its heading (rotating chevron, keyboard-accessible via role/tabindex/aria-expanded and Enter/Space). Collapsed keys are persisted in localStorage and restored on load, so the layout stays how you left it across reloads. State is device-global like the theme (a single non-namespaced key, not per-user data), and only collapsed panels are stored — so any panel added later defaults to open.
This commit is contained in:
+42
@@ -1769,6 +1769,48 @@
|
||||
if (ev) openEditDialog(ev);
|
||||
});
|
||||
|
||||
// ---------- collapsible panels ----------
|
||||
// Each main section carrying a data-panel key can be folded by clicking its
|
||||
// heading; collapsed keys are remembered across reloads. State is device-global
|
||||
// (like the theme), so a single non-namespaced key is fine — it's not per-user
|
||||
// data. Only collapsed panels are stored, so newly added panels default open.
|
||||
const PANELS_KEY = "puppy-tracker:panels:v1";
|
||||
function loadPanelState() {
|
||||
try {
|
||||
const s = JSON.parse(localStorage.getItem(PANELS_KEY));
|
||||
return s && typeof s === "object" ? s : {};
|
||||
} catch { return {}; }
|
||||
}
|
||||
function savePanelState(state) {
|
||||
try { localStorage.setItem(PANELS_KEY, JSON.stringify(state)); } catch { /* ignore */ }
|
||||
}
|
||||
function initPanels() {
|
||||
const state = loadPanelState();
|
||||
document.querySelectorAll("main section[data-panel]").forEach(section => {
|
||||
const key = section.dataset.panel;
|
||||
const h2 = section.querySelector(":scope > h2");
|
||||
if (!h2) return;
|
||||
section.classList.add("collapsible");
|
||||
const collapsed = !!state[key];
|
||||
section.classList.toggle("collapsed", collapsed);
|
||||
h2.setAttribute("role", "button");
|
||||
h2.setAttribute("tabindex", "0");
|
||||
h2.setAttribute("aria-expanded", String(!collapsed));
|
||||
const toggle = () => {
|
||||
const nowCollapsed = section.classList.toggle("collapsed");
|
||||
h2.setAttribute("aria-expanded", String(!nowCollapsed));
|
||||
const s = loadPanelState();
|
||||
if (nowCollapsed) s[key] = true; else delete s[key];
|
||||
savePanelState(s);
|
||||
};
|
||||
h2.addEventListener("click", toggle);
|
||||
h2.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); toggle(); }
|
||||
});
|
||||
});
|
||||
}
|
||||
initPanels();
|
||||
|
||||
// ---------- wiring ----------
|
||||
document.querySelectorAll("button.action").forEach(btn => {
|
||||
btn.addEventListener("click", () => {
|
||||
|
||||
Reference in New Issue
Block a user