Convert sidebar modules to accordion on mobile

On screens < 992px, sidebar-left and sidebar-right card modules
are transformed into Bootstrap accordion items via JS. Card headers
become collapsible toggles, card bodies collapse. On desktop resize
the accordion reverts to normal cards.

CSS scoped to mobile breakpoint styles the accordion buttons and
removes card borders for a clean stacked look.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 15:53:47 -05:00
parent 1abdd9a253
commit b637b78a4d
2 changed files with 126 additions and 0 deletions

View File

@@ -15844,6 +15844,39 @@ body:not(.has-sidebar-right) .site-grid .container-component {
grid-area: side-r;
}
/* Sidebar accordion on mobile */
@media (max-width: 991.98px) {
.container-sidebar-left.accordion .card,
.container-sidebar-right.accordion .card {
border: none;
border-bottom: 1px solid var(--border-color, #dee2e6);
border-radius: 0;
}
.container-sidebar-left.accordion .card-header,
.container-sidebar-right.accordion .card-header {
padding: 0;
background: none;
border: none;
}
.container-sidebar-left.accordion .accordion-button,
.container-sidebar-right.accordion .accordion-button {
padding: .75rem 1rem;
font-weight: 600;
font-size: .95rem;
background: var(--bs-body-bg, #fff);
color: var(--body-font-color, #444);
}
.container-sidebar-left.accordion .accordion-button:not(.collapsed),
.container-sidebar-right.accordion .accordion-button:not(.collapsed) {
background: var(--bs-body-bg, #fff);
color: var(--link-color, #3565e5);
box-shadow: none;
}
}
.container-main-top {
grid-area: main-t;
}

View File

@@ -488,6 +488,98 @@
return doc.body.getAttribute('data-theme-fab-enabled') === '1';
}
/**
* Convert sidebar card modules into accordion on mobile.
* On screens <= 991px each card collapses; on desktop they revert.
*/
function initSidebarAccordion() {
var BREAKPOINT = 992;
var sidebars = doc.querySelectorAll(".container-sidebar-left, .container-sidebar-right");
if (!sidebars.length) return;
var accordionised = false;
function apply() {
var isMobile = win.innerWidth < BREAKPOINT;
if (isMobile && !accordionised) {
sidebars.forEach(function (sidebar, si) {
var accId = "sidebarAcc-" + si;
sidebar.setAttribute("id", accId);
sidebar.classList.add("accordion");
var cards = sidebar.querySelectorAll(":scope > .card");
cards.forEach(function (card, ci) {
var collapseId = accId + "-c" + ci;
card.classList.add("accordion-item");
var header = card.querySelector(".card-header");
var body = card.querySelector(".card-body");
if (!header || !body) return;
// Turn header into accordion button
header.classList.add("accordion-header");
var btn = doc.createElement("button");
btn.className = "accordion-button collapsed";
btn.type = "button";
btn.setAttribute("data-bs-toggle", "collapse");
btn.setAttribute("data-bs-target", "#" + collapseId);
btn.setAttribute("aria-expanded", "false");
btn.setAttribute("aria-controls", collapseId);
btn.textContent = header.textContent;
header.textContent = "";
header.appendChild(btn);
header.setAttribute("data-moko-original-text", btn.textContent);
// Wrap body in collapse
var wrapper = doc.createElement("div");
wrapper.id = collapseId;
wrapper.className = "accordion-collapse collapse";
wrapper.setAttribute("data-bs-parent", "#" + accId);
card.insertBefore(wrapper, body);
wrapper.appendChild(body);
body.classList.add("accordion-body");
});
});
accordionised = true;
} else if (!isMobile && accordionised) {
// Revert to plain cards
sidebars.forEach(function (sidebar) {
sidebar.classList.remove("accordion");
sidebar.removeAttribute("id");
var cards = sidebar.querySelectorAll(":scope > .card");
cards.forEach(function (card) {
card.classList.remove("accordion-item");
var header = card.querySelector(".card-header");
var btn = header ? header.querySelector(".accordion-button") : null;
if (header && btn) {
var text = header.getAttribute("data-moko-original-text") || btn.textContent;
header.removeAttribute("data-moko-original-text");
header.classList.remove("accordion-header");
header.textContent = text;
}
var wrapper = card.querySelector(".accordion-collapse");
if (wrapper) {
var body = wrapper.querySelector(".card-body");
if (body) {
body.classList.remove("accordion-body");
card.appendChild(body);
}
wrapper.parentNode.removeChild(wrapper);
}
});
});
accordionised = false;
}
}
apply();
win.addEventListener("resize", apply);
}
/**
* Run all template JS initializations
*/
@@ -512,6 +604,7 @@
// Init features
initDrawers();
initBackTop();
initSidebarAccordion();
}
if (doc.readyState === "loading") {