Skip to content

feat(layouts): add resizable side panels with localStorage persistence#1040

Open
Rudra2637 wants to merge 3 commits into
layer5io:masterfrom
Rudra2637:feat/resizable-side-panels
Open

feat(layouts): add resizable side panels with localStorage persistence#1040
Rudra2637 wants to merge 3 commits into
layer5io:masterfrom
Rudra2637:feat/resizable-side-panels

Conversation

@Rudra2637
Copy link
Copy Markdown
Contributor

Description

This PR implements the resizable side panels feature for Layer5 Docs, allowing users to customize the width of the left sidebar and right table of contents (TOC) panel.

Related Issue

Fixes #1039

Changes Made

  • JavaScript (assets/js/resizable-panels.js): Drag-to-resize functionality with localStorage persistence and reset button
  • Styling (assets/scss/_resizable-panels.scss): Visual feedback for resize handles, responsive hiding on mobile/print
  • Integration: Updated stylesheet imports and created scripts partial for proper loading

Features Implemented

✅ Users can drag to adjust panel widths (left sidebar and right TOC)
✅ Preferences are saved in localStorage and persist across page visits
✅ Reset button available to restore default panel widths
✅ Responsive design: resize functionality only on desktop (XL screens)
✅ Constrained min/max widths to prevent layout breaking

Testing

  • Tested resize functionality (drag handles work smoothly)
  • Verified localStorage persistence (widths retained across page reloads)
  • Tested reset button (restores defaults)
  • Verified mobile/tablet responsiveness (handles hidden on smaller screens)
  • Verified print styles (handles hidden)

Notes for Reviewers

Per the acceptance criteria, a matching issue should be created for Meshery Docs to receive the same enhancement.

Signed Commits

  • Yes, I signed my commits.

Contributing Conventions: PR includes descriptive title with [layouts] component, changes tested, and commits are signed.

Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a resizable panels feature, allowing users to adjust the widths of the sidebar and table of contents with persistence via localStorage. The implementation includes a new JavaScript class, SCSS styling for handles, and a reset layout button. Several issues were identified in the review, including a syntax error in the SCSS transition property and an incorrect script loading method in the HTML template. Additionally, feedback was provided to improve code quality by removing unused variables, optimizing event listener performance, and replacing magic numbers with named constants for better maintainability.

Comment thread assets/scss/_resizable-panels.scss Outdated
.td-sidebar,
.td-sidebar-toc,
main[role="main"] {
transition: flex: 0.3s ease;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There is a syntax error in the transition property (extra colon after flex).

Suggested change
transition: flex: 0.3s ease;
transition: flex 0.3s ease;

@@ -0,0 +1,16 @@
<!-- Page scripts -->
<script defer src="{{ "js/resizable-panels.js" | relURL }}"></script>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The script js/resizable-panels.js is located in the assets/ directory, but it's being loaded using relURL, which typically points to the static/ directory. This will likely result in a 404 error. It should be loaded using Hugo's resources.Get to properly process it from the assets/ folder, consistent with the other scripts in this file.

Suggested change
<script defer src="{{ "js/resizable-panels.js" | relURL }}"></script>
{{ $resizablePanels := resources.Get "js/resizable-panels.js" -}}
{{ if $resizablePanels }}
<script defer src="{{ $resizablePanels.RelPermalink }}"></script>
{{ end -}}

Comment on lines +19 to +32
const COL_CLASSES = {
'col-1': 8.33,
'col-2': 16.66,
'col-3': 25,
'col-4': 33.33,
'col-5': 41.66,
'col-6': 50,
'col-7': 58.33,
'col-8': 66.66,
'col-9': 75,
'col-10': 83.33,
'col-11': 91.66,
'col-12': 100
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The COL_CLASSES object is defined but never used anywhere in the script. It should be removed to keep the code clean.

this.isResizing = false;
this.currentResizeTarget = null;
this.startX = 0;
this.startWidth = 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The property this.startWidth is initialized here but never used. The script uses this.startWidths (plural) for its logic instead. This line can be safely removed.

Comment on lines +98 to +102
addEventListeners() {
document.addEventListener('mousedown', (e) => this.onMouseDown(e));
document.addEventListener('mousemove', (e) => this.onMouseMove(e));
document.addEventListener('mouseup', (e) => this.onMouseUp(e));
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The mousemove and mouseup event listeners are attached to the document globally and remain active even when the user is not interacting with the resize handles. For better performance, consider attaching these listeners only within onMouseDown and removing them in onMouseUp.

const newMainPercent = mainPercent - (adjustment * 100);

// Constrain widths: min 1 col, max 5 cols for sidebar; min 4 cols for main
if (newSidebarPercent >= 8.33 && newSidebarPercent <= 41.66 && newMainPercent >= 33.33) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These magic numbers (8.33, 41.66, 33.33) represent specific Bootstrap column percentages (1/12, 5/12, 4/12). It would be more maintainable to define these as named constants at the top of the file to clarify their meaning and make them easier to adjust if the layout constraints change.

Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

🚀 Preview deployment: https://layer5io.github.io/docs/pr-preview/pr-1040/

Note: Preview may take a moment (GitHub Pages deployment in progress). Please wait and refresh. Track deployment here

Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adjustable Side Panels

1 participant