feat(js): tabs.js — tab activation + expand-to-active-modal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
be3a00a8f5
commit
eb0c1a52db
1 changed files with 62 additions and 0 deletions
62
l4d2web/l4d2web/static/js/tabs.js
Normal file
62
l4d2web/l4d2web/static/js/tabs.js
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
// l4d2web/l4d2web/static/js/tabs.js
|
||||||
|
// Tabbed strips: any element with [data-tab-strip] activates the first
|
||||||
|
// [role="tab"] in DOM order (or the one carrying [aria-selected="true"]
|
||||||
|
// if present) on load, and switches panes on click. The strip's
|
||||||
|
// [data-active-tab] attribute mirrors the active tab name and is read
|
||||||
|
// by the expand-to-modal handler.
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
function activateTab(strip, name) {
|
||||||
|
strip.querySelectorAll('[role="tab"]').forEach((t) => {
|
||||||
|
const on = t.dataset.tab === name;
|
||||||
|
t.setAttribute("aria-selected", on ? "true" : "false");
|
||||||
|
t.tabIndex = on ? 0 : -1;
|
||||||
|
});
|
||||||
|
strip.querySelectorAll('[role="tabpanel"]').forEach((p) => {
|
||||||
|
p.hidden = p.dataset.tab !== name;
|
||||||
|
});
|
||||||
|
strip.dataset.activeTab = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function activeTabName(strip) {
|
||||||
|
const selected = strip.querySelector('[role="tab"][aria-selected="true"]');
|
||||||
|
if (selected) return selected.dataset.tab;
|
||||||
|
const first = strip.querySelector('[role="tab"]');
|
||||||
|
return first ? first.dataset.tab : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initStrips(root) {
|
||||||
|
(root || document).querySelectorAll("[data-tab-strip]").forEach((strip) => {
|
||||||
|
// Initialise active tab on load.
|
||||||
|
const name = activeTabName(strip);
|
||||||
|
if (name) activateTab(strip, name);
|
||||||
|
|
||||||
|
// Bind tab clicks.
|
||||||
|
strip.addEventListener("click", (ev) => {
|
||||||
|
const tab = ev.target.closest('[role="tab"]');
|
||||||
|
if (tab && strip.contains(tab)) {
|
||||||
|
activateTab(strip, tab.dataset.tab);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bind expand button: opens <dialog id="<tabname>-modal">.
|
||||||
|
const expand = strip.querySelector(".strip-expand");
|
||||||
|
if (expand) {
|
||||||
|
expand.addEventListener("click", () => {
|
||||||
|
const name = strip.dataset.activeTab;
|
||||||
|
if (!name) return;
|
||||||
|
const dlg = document.getElementById(`${name}-modal`);
|
||||||
|
if (dlg && typeof dlg.showModal === "function" && !dlg.open) {
|
||||||
|
dlg.showModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === "loading") {
|
||||||
|
document.addEventListener("DOMContentLoaded", () => initStrips());
|
||||||
|
} else {
|
||||||
|
initStrips();
|
||||||
|
}
|
||||||
|
})();
|
||||||
Loading…
Reference in a new issue