From 5fca466e94a3e5a6f60f8e70a7c9ec85d8f879a7 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Sun, 19 Oct 2025 14:28:44 -0400 Subject: [PATCH] Adjust sidebar width to accommodate dropup content --- css/tailwind.source.css | 40 +++++++++++---- css/tokens.css | 7 ++- js/index.js | 105 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 10 deletions(-) diff --git a/css/tailwind.source.css b/css/tailwind.source.css index db709db5..f2eefb74 100644 --- a/css/tailwind.source.css +++ b/css/tailwind.source.css @@ -2811,9 +2811,18 @@ } #app[data-sidebar-state="expanded"] { - margin-left: var(--sidebar-width-expanded); - width: calc(100vw - var(--sidebar-width-expanded)); - max-width: calc(100vw - var(--sidebar-width-expanded)); + margin-left: max( + var(--sidebar-width-expanded-base), + var(--sidebar-dropup-content-width) + ); + width: min( + calc(100vw - var(--sidebar-width-expanded-base)), + calc(100vw - var(--sidebar-dropup-content-width)) + ); + max-width: min( + calc(100vw - var(--sidebar-width-expanded-base)), + calc(100vw - var(--sidebar-dropup-content-width)) + ); } body.sidebar-collapsed #sidebar .sidebar-nav-link, @@ -2925,14 +2934,27 @@ } #app[data-sidebar-state="expanded"] { - margin-left: calc( - var(--sidebar-width-expanded) + var(--sidebar-content-gap) + margin-left: max( + calc(var(--sidebar-width-expanded-base) + var(--sidebar-content-gap)), + calc(var(--sidebar-dropup-content-width) + var(--sidebar-content-gap)) ); - width: calc( - 100vw - var(--sidebar-width-expanded) - var(--sidebar-content-gap) + width: min( + calc( + 100vw - var(--sidebar-width-expanded-base) - var(--sidebar-content-gap) + ), + calc( + 100vw - var(--sidebar-dropup-content-width) - + var(--sidebar-content-gap) + ) ); - max-width: calc( - 100vw - var(--sidebar-width-expanded) - var(--sidebar-content-gap) + max-width: min( + calc( + 100vw - var(--sidebar-width-expanded-base) - var(--sidebar-content-gap) + ), + calc( + 100vw - var(--sidebar-dropup-content-width) - + var(--sidebar-content-gap) + ) ); } diff --git a/css/tokens.css b/css/tokens.css index eeb54d3f..45bd3cb4 100644 --- a/css/tokens.css +++ b/css/tokens.css @@ -146,7 +146,12 @@ --z-modal-top-content: 160; --overlay-backdrop-color: var(--color-overlay-backdrop); --overlay-backdrop-blur: 12px; - --sidebar-width-expanded: 16rem; + --sidebar-width-expanded-base: 16rem; + --sidebar-dropup-content-width: 0px; + --sidebar-width-expanded: max( + var(--sidebar-width-expanded-base), + var(--sidebar-dropup-content-width) + ); --sidebar-width-collapsed: 4rem; --sidebar-width: var(--sidebar-width-expanded); --sidebar-control-size: 2.75rem; diff --git a/js/index.js b/js/index.js index 58f6f6a2..b253923c 100644 --- a/js/index.js +++ b/js/index.js @@ -375,6 +375,108 @@ async function bootstrapInterface() { const footerDropdownLabel = document.getElementById("footerDropdownText"); const footerDropdownIcon = document.getElementById("footerDropdownIcon"); + const debounce = (fn, delay) => { + let timeoutId = null; + return (...args) => { + if (timeoutId !== null) { + window.clearTimeout(timeoutId); + } + timeoutId = window.setTimeout(() => { + timeoutId = null; + fn(...args); + }, delay); + }; + }; + + const resolveCssLengthToPixels = (value, container) => { + if (!(container instanceof HTMLElement) || typeof value !== "string") { + return 0; + } + + const measurementNode = container.ownerDocument.createElement("div"); + measurementNode.style.position = "absolute"; + measurementNode.style.visibility = "hidden"; + measurementNode.style.pointerEvents = "none"; + measurementNode.style.height = "0"; + measurementNode.style.width = value; + measurementNode.style.overflow = "hidden"; + + container.appendChild(measurementNode); + const pixels = measurementNode.getBoundingClientRect().width; + container.removeChild(measurementNode); + + return Number.isFinite(pixels) ? pixels : 0; + }; + + const updateSidebarDropupContentWidth = () => { + const panelInner = document.querySelector(".sidebar-dropup-panel__inner"); + const panel = panelInner?.closest(".sidebar-dropup-panel"); + + if (!(panelInner instanceof HTMLElement) || !(panel instanceof HTMLElement)) { + document.documentElement.style.setProperty( + "--sidebar-dropup-content-width", + "0px", + ); + return; + } + + const originalStyles = { + position: panelInner.style.position, + width: panelInner.style.width, + maxWidth: panelInner.style.maxWidth, + visibility: panelInner.style.visibility, + pointerEvents: panelInner.style.pointerEvents, + left: panelInner.style.left, + right: panelInner.style.right, + top: panelInner.style.top, + bottom: panelInner.style.bottom, + }; + + panelInner.style.position = "absolute"; + panelInner.style.width = "max-content"; + panelInner.style.maxWidth = "none"; + panelInner.style.visibility = "hidden"; + panelInner.style.pointerEvents = "none"; + panelInner.style.left = "-9999px"; + panelInner.style.right = "auto"; + panelInner.style.top = "auto"; + panelInner.style.bottom = "auto"; + + const measuredInnerWidth = Math.ceil(panelInner.scrollWidth); + + panelInner.style.position = originalStyles.position; + panelInner.style.width = originalStyles.width; + panelInner.style.maxWidth = originalStyles.maxWidth; + panelInner.style.visibility = originalStyles.visibility; + panelInner.style.pointerEvents = originalStyles.pointerEvents; + panelInner.style.left = originalStyles.left; + panelInner.style.right = originalStyles.right; + panelInner.style.top = originalStyles.top; + panelInner.style.bottom = originalStyles.bottom; + + const panelStyles = window.getComputedStyle(panel); + const paddingInlineStart = Number.parseFloat(panelStyles.paddingInlineStart) || 0; + const paddingInlineEnd = Number.parseFloat(panelStyles.paddingInlineEnd) || 0; + + const scrollReserveValue = window + .getComputedStyle(panel) + .getPropertyValue("--space-sidebar-dropup-scroll-reserve"); + const scrollReserve = resolveCssLengthToPixels(scrollReserveValue, panel); + + const totalWidth = Math.max( + 0, + measuredInnerWidth + paddingInlineStart + paddingInlineEnd + scrollReserve, + ); + + document.documentElement.style.setProperty( + "--sidebar-dropup-content-width", + `${Math.ceil(totalWidth)}px`, + ); + }; + + const debouncedSidebarDropupResize = debounce(updateSidebarDropupContentWidth, 150); + window.addEventListener("resize", debouncedSidebarDropupResize); + if (footerDropdownButton && footerLinksContainer) { const sidebarFooter = footerDropdownButton.closest(".sidebar-footer"); @@ -407,6 +509,7 @@ async function bootstrapInterface() { sidebarFooter.dataset.footerState = nextState; } isFooterDropupExpanded = expanded; + updateSidebarDropupContentWidth(); }; footerDropdownButton.addEventListener("click", (event) => { @@ -429,6 +532,8 @@ async function bootstrapInterface() { if (typeof syncFooterDropupFn === "function") { syncFooterDropupFn(initialExpanded); } + } else { + updateSidebarDropupContentWidth(); } try {