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