Skip to content

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

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

feat(layouts): add resizable side panels with localStorage persistence#1040
Rudra2637 wants to merge 17 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;

Comment thread layouts/partials/scripts.html Outdated
@@ -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 thread assets/js/resizable-panels.js Outdated
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.

Comment thread assets/js/resizable-panels.js Outdated
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 thread assets/js/resizable-panels.js Outdated
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.

Comment thread assets/js/resizable-panels.js Outdated
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
Contributor

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>
overflow: hidden;
padding: 0px;

&__section-title {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Rudra2637 , Thanks for the effort on this PR. I think these changes can be reverted, as this issue can likely be resolved by simply adding margin-top: 0.5rem inside &_section-title container;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the feedback! I’ll revert the current changes and update the PR by adding margin-top: 0.5rem inside the &_section-title container instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I initially interpreted the issue as requiring a broader UI adjustment and didn’t notice that the panel was already scrollable

Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
@Rudra2637 Rudra2637 requested a review from Sbragul26 May 15, 2026 17:40
Copy link
Copy Markdown
Member

@Sbragul26 Sbragul26 left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@Bhumikagarggg
Copy link
Copy Markdown
Contributor

@Rudra2637 Thank you for your contribution! Let's discuss this during the website call tomorrow at 5:30 PM IST | 7 AM CST Add it as an agenda item to the meeting minutes, if you would 🙂

@leecalcote
Copy link
Copy Markdown
Member

@banana-three-join, how are we doing here?

@alexquincy
Copy link
Copy Markdown
Contributor

REPEAT:

Acceptance Tests
We're using the same framework (Hugo) and same theme across our site properties with much intentionality: reuse, consistent UX, lower cost of sustaining, and so on. When either Meshery Docs or Layer5 Docs receives an enhancement or bug fix in the layout/framework/shortcode/partial, etc... both should benefit. So, open an issue to enhance Meshery Docs when this feature is delivered.

Copy link
Copy Markdown
Contributor

@banana-three-join banana-three-join left a comment

Choose a reason for hiding this comment

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

Disregard the last comment and bring back the changes you previously implemented. You were right about the issue, it requires to adjust the width of both side panels so it fits the user's preference so the content can be read. The previous suggestion has nothing to do with what needs to be implemented, as only margin on the y axis gets added, which by definition, doesn't affect the width of the container.

Go back to the commit with your proposed changes, and once that's done, I'll be reviewing your PR again!

@Rudra2637
Copy link
Copy Markdown
Contributor Author

Thanks for the clarification. I’ll revert back to the previous implementation with the side panel width adjustments and update the PR accordingly. Once that’s done, will let you know.

Rudra2637 added 10 commits May 21, 2026 17:09
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
Signed-off-by: Rudra2637 <singhrudra2637@gmail.com>
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.

Instead of single handedly adding each resource, add all of the needed resources in an array and loop through the slice to request the .RelPermalink

Comment thread assets/js/resizable-panels.js Outdated
main: { min: 42 },
};

class ResizablePanels {
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.

The usage of classes is an overkill. The classes are discarded just as quickly as they got created, adding a lot of boilerplate in the process which makes the code harded to read.

Comment thread assets/js/resizable-panels.js Outdated
const saved = JSON.parse(localStorage.getItem(STORAGE_KEY));
if (
saved &&
(saved.sidebar <= 12 || saved.toc <= 12 || saved.main <= 12)
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.

Don't utilize magic numbers because if this code checks the current storedWidth and compares it with the limit of each item to normalize it to the intended min size then this check is wrong because above you have the following Limits:

sidebar: { min: 12, max: 32 },
toc: { min: 10, max: 28 },
main: { min: 42 },

So now all the items are checking it's width against 12 and not their intended bottom limit. Also, the upper limit isn't being checked.

@Rudra2637
Copy link
Copy Markdown
Contributor Author

Ok, I will look into the suggested changes and re request review once i am done adjusting the pr as per the suggestions

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

/gemini review

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 resizable documentation panels, allowing users to adjust the widths of the left navigation sidebar and the right table of contents (TOC). It includes a JavaScript module to handle dragging, keyboard accessibility, and persistence via localStorage, alongside SCSS styles for layout and visual indicators. The review feedback focuses on improving performance and robustness: it suggests removing hardcoded pixel limits in the CSS that conflict with JavaScript percentage calculations, throttling pointer move updates using requestAnimationFrame to prevent layout thrashing, dynamically binding pointer events only during active resizing, and removing a hardcoded HTML ID to prevent duplicates when multiple panels are initialized.

Comment on lines +29 to +38
.row.flex-xl-nowrap.resizable-panels-ready > .td-sidebar {
flex: 0 0 var(--docs-sidebar-width);
width: var(--docs-sidebar-width);
max-width: 420px;
min-width: 240px;
position: relative;
overflow-x: hidden;
padding-right: 12px;
order: 1;
}
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 hardcoded pixel limits (min-width: 240px and max-width: 420px) in the CSS conflict with the percentage-based limits (min: 12, max: 32) defined in the JavaScript. When these pixel boundaries are hit, the browser will clamp the sidebar width, but the JS will continue to update the percentage width and the drag handle position, causing them to become visually desynchronized. Removing these pixel limits from the CSS allows the JS percentage limits to govern the boundaries consistently.

  .row.flex-xl-nowrap.resizable-panels-ready > .td-sidebar {
    flex: 0 0 var(--docs-sidebar-width);
    width: var(--docs-sidebar-width);
    position: relative;
    overflow-x: hidden;
    padding-right: 12px;
    order: 1;
  }

Comment on lines +63 to +71
.row.flex-xl-nowrap.resizable-panels-ready > .td-sidebar-toc {
width: var(--docs-toc-width);
max-width: 320px;
min-width: 220px;
position: relative;
overflow-x: hidden;
padding-left: 12px;
order: 3;
}
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 hardcoded pixel limits (min-width: 220px and max-width: 320px) in the CSS conflict with the percentage-based limits (min: 10, max: 28) defined in the JavaScript. When these pixel boundaries are hit, the browser will clamp the TOC width, but the JS will continue to update the percentage width and the drag handle position, causing them to become visually desynchronized. Removing these pixel limits from the CSS allows the JS percentage limits to govern the boundaries consistently.

  .row.flex-xl-nowrap.resizable-panels-ready > .td-sidebar-toc {
    width: var(--docs-toc-width);
    position: relative;
    overflow-x: hidden;
    padding-left: 12px;
    order: 3;
  }

Comment on lines +29 to +34
let activeHandle = null;
let sidebarHandle = null;
let tocHandle = null;
let startX = 0;
let startWidths = null;
let widths = getStoredWidths();
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

To support smooth, high-performance resizing without layout thrashing, we should throttle the DOM updates using requestAnimationFrame. Let's declare a variable to hold the animation frame ID so we can cancel any pending frames when a new pointer move event occurs or when resizing stops.

Suggested change
let activeHandle = null;
let sidebarHandle = null;
let tocHandle = null;
let startX = 0;
let startWidths = null;
let widths = getStoredWidths();
let activeHandle = null;
let sidebarHandle = null;
let tocHandle = null;
let startX = 0;
let startWidths = null;
let widths = getStoredWidths();
let animationFrameId = null;

Comment on lines +46 to +62
function bindEvents() {
document.addEventListener('pointermove', onPointerMove);
document.addEventListener('pointerup', stopResize);
document.addEventListener('pointercancel', stopResize);

const onBreakpointChange = () => {
if (mediaQuery.matches) {
applyWidths(widths);
}
};

if (mediaQuery.addEventListener) {
mediaQuery.addEventListener('change', onBreakpointChange);
} else {
mediaQuery.addListener(onBreakpointChange);
}
}
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

Binding pointermove, pointerup, and pointercancel listeners globally on the document at all times is inefficient and can cause performance degradation, as these handlers will execute on every mouse/pointer movement even when the user is not resizing. Instead, we should dynamically bind these listeners only when resizing starts (pointerdown) and unbind them when resizing stops.

    function bindEvents() {
      const onBreakpointChange = () => {
        if (mediaQuery.matches) {
          applyWidths(widths);
        }
      };

      if (mediaQuery.addEventListener) {
        mediaQuery.addEventListener('change', onBreakpointChange);
      } else {
        mediaQuery.addListener(onBreakpointChange);
      }
    }

Comment on lines +94 to +105
function createResetButton() {
const resetButton = document.createElement('button');
resetButton.type = 'button';
resetButton.id = 'reset-panel-widths';
resetButton.className = 'resizable-panel-reset';
resetButton.innerHTML =
'<i class="bi bi-arrow-clockwise" aria-hidden="true"></i><span>Reset layout</span>';
resetButton.title = 'Reset panel widths to default';
resetButton.addEventListener('click', reset);

sidebar.appendChild(resetButton);
}
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

Setting a hardcoded ID reset-panel-widths on the reset button will result in duplicate IDs in the DOM if multiple resizable rows are initialized on the same page. Since the styling in _resizable-panels.scss only targets the class .resizable-panel-reset, we can safely remove the id attribute to maintain valid HTML standards.

    function createResetButton() {
      const resetButton = document.createElement('button');
      resetButton.type = 'button';
      resetButton.className = 'resizable-panel-reset';
      resetButton.innerHTML =
        '<i class="bi bi-arrow-clockwise" aria-hidden="true"></i><span>Reset layout</span>';
      resetButton.title = 'Reset panel widths to default';
      resetButton.addEventListener('click', reset);

      sidebar.appendChild(resetButton);
    }

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.

If the indicator for a "resizable-panel" is it having a ".row.flex-xl-nowrap" then the id comment is correct. But this means that there's multiple items that have different sidebars which are being managed individually. Is the difference in design that big for there to be different size managers for the side panels?

Comment on lines +107 to +119
function startResize(event, handle) {
if (!mediaQuery.matches) {
return;
}

event.preventDefault();
activeHandle = handle;
startX = event.clientX;
startWidths = { ...widths };
handle.classList.add('resizable-panel-handle--active');
handle.setPointerCapture(event.pointerId);
document.body.classList.add('resizable-panels-dragging');
}
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

Dynamically attach the global pointer move and up/cancel event listeners here when the user actually starts dragging the handle.

    function startResize(event, handle) {
      if (!mediaQuery.matches) {
        return;
      }

      event.preventDefault();
      activeHandle = handle;
      startX = event.clientX;
      startWidths = { ...widths };
      handle.classList.add('resizable-panel-handle--active');
      handle.setPointerCapture(event.pointerId);
      document.body.classList.add('resizable-panels-dragging');

      document.addEventListener('pointermove', onPointerMove);
      document.addEventListener('pointerup', stopResize);
      document.addEventListener('pointercancel', stopResize);
    }

Comment on lines +121 to +145
function onPointerMove(event) {
if (!activeHandle || !startWidths) {
return;
}

const rowWidth = row.getBoundingClientRect().width;
if (!rowWidth) {
return;
}

const target = activeHandle.dataset.resizeTarget;
const delta = ((event.clientX - startX) / rowWidth) * 100;
const nextWidths = { ...startWidths };

if (target === 'sidebar') {
nextWidths.sidebar = startWidths.sidebar + delta;
}

if (target === 'toc') {
nextWidths.toc = startWidths.toc - delta;
}

widths = normalizeWidths(nextWidths);
applyWidths(widths);
}
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

Throttle the pointer move updates using requestAnimationFrame to ensure smooth 60fps+ resizing and prevent layout thrashing.

    function onPointerMove(event) {
      if (!activeHandle || !startWidths) {
        return;
      }

      if (animationFrameId) {
        cancelAnimationFrame(animationFrameId);
      }

      const clientX = event.clientX;

      animationFrameId = requestAnimationFrame(() => {
        const rowWidth = row.getBoundingClientRect().width;
        if (!rowWidth) {
          return;
        }

        const target = activeHandle.dataset.resizeTarget;
        const delta = ((clientX - startX) / rowWidth) * 100;
        const nextWidths = { ...startWidths };

        if (target === 'sidebar') {
          nextWidths.sidebar = startWidths.sidebar + delta;
        }

        if (target === 'toc') {
          nextWidths.toc = startWidths.toc - delta;
        }

        widths = normalizeWidths(nextWidths);
        applyWidths(widths);
      });
    }

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.

Thoughts on this?

Comment on lines +147 to +157
function stopResize() {
if (!activeHandle) {
return;
}

activeHandle.classList.remove('resizable-panel-handle--active');
activeHandle = null;
startWidths = null;
document.body.classList.remove('resizable-panels-dragging');
saveWidths();
}
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

Clean up the dynamic pointer event listeners and cancel any pending animation frames when resizing stops.

    function stopResize() {
      if (!activeHandle) {
        return;
      }

      if (animationFrameId) {
        cancelAnimationFrame(animationFrameId);
        animationFrameId = null;
      }

      activeHandle.classList.remove('resizable-panel-handle--active');
      activeHandle = null;
      startWidths = null;
      document.body.classList.remove('resizable-panels-dragging');
      saveWidths();

      document.removeEventListener('pointermove', onPointerMove);
      document.removeEventListener('pointerup', stopResize);
      document.removeEventListener('pointercancel', stopResize);
    }

@banana-three-join
Copy link
Copy Markdown
Contributor

@Rudra2637 Please review the recommendations and resolved them. The most recent recommendations (Both mine's a Gemini's) don't point out any major bugs so after the feedback has been addressed, and it has been stated how it has been addressed, a video proof should be more than enough to merge the pr!

@Rudra2637
Copy link
Copy Markdown
Contributor Author

Ok i will look into your suggestions as well as gemini and create video

@Rudra2637
Copy link
Copy Markdown
Contributor Author

The latest recommendations have been addressed. The resource-loading code now uses an array and loop instead of adding each asset individually, the resizable-panels logic has already been refactored to avoid unnecessary class usage, and the width normalization now uses the defined per-item limits instead of a shared magic number.

Screen.Recording.2026-05-29.194900.mp4

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.

I looked further and the addition of scripts.html isn't needed for the following reason:

All of the JS assets being imported "aside from resizable-panels.js" are currently being imported elsewhere in the code, so it's inclusion isn't needed, not only because they're already imported, but also because they are being imported globally even when they aren't needed.

scripts.html shouldn't be added, as Docsy (The theme currently being imported) already has a scripts.html so adding another one would override the one being currently in use. Instead, the "resizable-panels.js" script should be imported where both "td-sidebar" are being used.

Comment on lines +94 to +105
function createResetButton() {
const resetButton = document.createElement('button');
resetButton.type = 'button';
resetButton.id = 'reset-panel-widths';
resetButton.className = 'resizable-panel-reset';
resetButton.innerHTML =
'<i class="bi bi-arrow-clockwise" aria-hidden="true"></i><span>Reset layout</span>';
resetButton.title = 'Reset panel widths to default';
resetButton.addEventListener('click', reset);

sidebar.appendChild(resetButton);
}
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.

If the indicator for a "resizable-panel" is it having a ".row.flex-xl-nowrap" then the id comment is correct. But this means that there's multiple items that have different sidebars which are being managed individually. Is the difference in design that big for there to be different size managers for the side panels?

Comment on lines +121 to +145
function onPointerMove(event) {
if (!activeHandle || !startWidths) {
return;
}

const rowWidth = row.getBoundingClientRect().width;
if (!rowWidth) {
return;
}

const target = activeHandle.dataset.resizeTarget;
const delta = ((event.clientX - startX) / rowWidth) * 100;
const nextWidths = { ...startWidths };

if (target === 'sidebar') {
nextWidths.sidebar = startWidths.sidebar + delta;
}

if (target === 'toc') {
nextWidths.toc = startWidths.toc - delta;
}

widths = normalizeWidths(nextWidths);
applyWidths(widths);
}
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.

Thoughts on this?

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.

The feedback regarding the dynamic use of the event listening for the dragging of the panels hasn't been implemented. As of right now, there's always an event listening of the pointer movement despite there being a window in which a listening for those particulars event isn't needed.

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

7 participants