// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const STORAGE_KEY = 'toolbox-second-nav-width';
const DEFAULT_WIDTH = 250;
const MIN_WIDTH = 200;
const MAX_WIDTH_PERCENT = 50;
/**
* Creates and attaches a resize handle to the second navigation panel
*/
export function initializeResize() {
const secondNav = document.querySelector('.second-nav');
if (!secondNav) {
return;
}
// Create resize handle
const resizeHandle = document.createElement('div');
resizeHandle.className = 'resize-handle';
resizeHandle.setAttribute('aria-label', 'Resize panel');
secondNav.appendChild(resizeHandle);
// Load saved width or use default
let initialWidth = DEFAULT_WIDTH;
try {
const savedWidth = localStorage.getItem(STORAGE_KEY);
if (savedWidth) {
const parsed = parseInt(savedWidth, 10);
if (!isNaN(parsed) && parsed >= MIN_WIDTH) {
initialWidth = parsed;
}
}
} catch (e) {
// localStorage may be unavailable in private browsing mode
console.warn('Failed to load saved panel width:', e);
}
setPanelWidth(secondNav, initialWidth);
// Setup resize functionality
let startX = 0;
let startWidth = 0;
const onMouseMove = (e) => {
const deltaX = e.clientX - startX;
const newWidth = startWidth + deltaX;
const maxWidth = (window.innerWidth * MAX_WIDTH_PERCENT) / 100;
const clampedWidth = Math.max(MIN_WIDTH, Math.min(newWidth, maxWidth));
setPanelWidth(secondNav, clampedWidth);
};
const onMouseUp = () => {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
resizeHandle.classList.remove('active');
document.body.style.cursor = '';
document.body.style.userSelect = '';
// Save width to localStorage
try {
localStorage.setItem(STORAGE_KEY, secondNav.offsetWidth.toString());
} catch (e) {
// localStorage may be unavailable in private browsing mode
console.warn('Failed to save panel width:', e);
}
};
resizeHandle.addEventListener('mousedown', (e) => {
startX = e.clientX;
startWidth = secondNav.offsetWidth;
resizeHandle.classList.add('active');
document.body.style.cursor = 'ew-resize';
document.body.style.userSelect = 'none';
e.preventDefault();
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
// Handle window resize to enforce max width
window.addEventListener('resize', () => {
const currentWidth = secondNav.offsetWidth;
const maxWidth = (window.innerWidth * MAX_WIDTH_PERCENT) / 100;
if (currentWidth > maxWidth) {
setPanelWidth(secondNav, maxWidth);
try {
localStorage.setItem(STORAGE_KEY, maxWidth.toString());
} catch (e) {
// localStorage may be unavailable in private browsing mode
console.warn('Failed to save panel width:', e);
}
}
});
}
/**
* Sets the width of the panel and updates flex property
*/
function setPanelWidth(panel, width) {
panel.style.flex = `0 0 ${width}px`;
}