From a2e3dd4c59d428ad280ba98605c6da88b8fe7954 Mon Sep 17 00:00:00 2001 From: yashnagar67 Date: Mon, 18 May 2026 00:32:15 +0530 Subject: [PATCH] feat(ux): add resizable side panels with local storage preference Implemented a draggable resizer for the sidebar that saves user width preferences to localStorage. Disabled on mobile breakpoints to preserve native responsive layouts. Fixes #1039. Signed-off-by: yashnagar67 --- assets/js/sidebar-resizer.js | 62 ++++++++++++++++++++++++++++++++ assets/scss/_styles_project.scss | 55 +++++++++++++++++++++++++++- layouts/docs/baseof.html | 11 +++++- 3 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 assets/js/sidebar-resizer.js diff --git a/assets/js/sidebar-resizer.js b/assets/js/sidebar-resizer.js new file mode 100644 index 00000000000..bf032e9266d --- /dev/null +++ b/assets/js/sidebar-resizer.js @@ -0,0 +1,62 @@ + + document.addEventListener("DOMContentLoaded", function () { + const resizer = document.getElementById("left-resizer"); + const sidebar = document.getElementById("left-sidebar"); + + if (!resizer || !sidebar) return; + if (window.innerWidth < 768) return; + + + let isResizing = false; + + + const savedWidth = localStorage.getItem("leftSidebarWidth"); + if (savedWidth) { + sidebar.style.width = savedWidth; + sidebar.style.flex = "none"; + sidebar.style.maxWidth = "35vw"; + } + + + resizer.addEventListener("mousedown", function (e) { + isResizing = true; + document.body.style.cursor = "col-resize"; + document.body.style.userSelect = "none"; + }); + + + document.addEventListener("mousemove", function (e) { + if (!isResizing) return; + + + const newWidth = e.clientX + "px"; + sidebar.style.width = newWidth; + sidebar.style.flex = "none"; // Override bootstrap grid flex + }); + + + document.addEventListener("mouseup", function () { + if (isResizing) { + isResizing = false; + document.body.style.cursor = ""; + document.body.style.userSelect = ""; + + // Save the final width + localStorage.setItem("leftSidebarWidth", sidebar.style.width); + } + }); + + + resizer.addEventListener("dblclick", function () { + sidebar.classList.add("is-resetting"); // Add transition class + + sidebar.style.width = ""; + sidebar.style.flex = ""; + localStorage.removeItem("leftSidebarWidth"); + + + setTimeout(() => sidebar.classList.remove("is-resetting"), 300); + }); + + }); + \ No newline at end of file diff --git a/assets/scss/_styles_project.scss b/assets/scss/_styles_project.scss index d25ce2a36f2..51e7018d57a 100644 --- a/assets/scss/_styles_project.scss +++ b/assets/scss/_styles_project.scss @@ -262,7 +262,7 @@ a:not([href]):not([class]):hover { // Left sidebar .td-sidebar-nav { - overflow: hidden; + max-height: none; padding: 0px; &__section-title { @@ -816,3 +816,56 @@ html { h1, h2, h3, h4, h5, h6 { scroll-margin-top: 1rem; } +/* Sidebar Resizer Handle */ +/* Sidebar Resizer Handle */ +@include media-breakpoint-up(md) +{ + .sidebar-resizer { + width: 10px; + cursor: col-resize; + position: absolute; + top: 0; + right: 8px; /* Push it outside the scrollbar */ + bottom: 0; + z-index: 100; + background-color: transparent; + + /* Grip icon using a pseudo-element */ + &::after { + content: "⋮"; + position: sticky; + top: 40vh; + display: block; + text-align: center; + color: var(--secondary); + font-size: 18px; + opacity: 0.9; + } + + &:hover::after, &:active::after { + opacity: 1; + } +} +#left-sidebar { + min-width: 20vw; + max-width: 35vw; + } + #left-sidebar.is-resetting { + transition: width 0.3s ease, max-width 0.3s ease; +} + + +} +@include media-breakpoint-down(sm) { + #left-sidebar { + /* Force mobile width and override any JS inline styles */ + width: 100% !important; + max-width: 100% !important; + flex: 100% !important; + } +} + + + + + diff --git a/layouts/docs/baseof.html b/layouts/docs/baseof.html index 3503963fb79..a70c38fe99d 100644 --- a/layouts/docs/baseof.html +++ b/layouts/docs/baseof.html @@ -10,8 +10,10 @@
-
{{ partial "scripts.html" . }} {{ partial "image-modal.html" . }} + + {{ with resources.Get "js/sidebar-resizer.js" }} + + {{ end }} + + + \ No newline at end of file