Add resizable thumbnail sidebar to EnvelopeViewer

Introduced a resizable splitter for the PDF thumbnail sidebar, allowing users to dynamically adjust its width. Added `_thumbnailWidth` property with min/max constraints and implemented mouse event handlers (`OnSplitterMouseDown`, `OnSplitterMouseMove`, `OnSplitterMouseUp`) to manage resizing.

Integrated JavaScript interop to attach/detach resize event listeners and save user preferences to `localStorage`. Updated `pdf-viewer.js` to handle resizing state and cleanup. Styled the splitter in `envelope-viewer.css` with hover/active states and ensured smooth interaction.

Persisted thumbnail width across sessions and added error handling for `localStorage`. Enhanced user experience with intuitive resizing and improved UI flexibility.
This commit is contained in:
2026-06-06 00:38:27 +02:00
parent fb02a1a359
commit 9fa8ef29d8
3 changed files with 163 additions and 12 deletions

View File

@@ -104,6 +104,46 @@
background: linear-gradient(135deg, #6b1cb0 0%, #1e3a72 100%);
}
.pdf-splitter {
width: 4px;
background: transparent;
cursor: col-resize;
flex-shrink: 0;
position: relative;
transition: background 0.2s ease;
z-index: 10;
user-select: none;
}
.pdf-splitter::before {
content: '';
position: absolute;
left: -4px;
right: -4px;
top: 0;
bottom: 0;
/* Enlarged hitbox for easier grabbing */
}
.pdf-splitter:hover,
.pdf-splitter.resizing {
background: linear-gradient(90deg,
rgba(126, 34, 206, 0.4) 0%,
rgba(42, 82, 152, 0.4) 100%);
}
.pdf-splitter:active {
background: linear-gradient(90deg,
rgba(126, 34, 206, 0.6) 0%,
rgba(42, 82, 152, 0.6) 100%);
}
/* Prevent text selection during resize */
body.resizing {
user-select: none;
cursor: col-resize !important;
}
.pdf-thumbnail {
cursor: pointer;
border-radius: 8px;

View File

@@ -289,6 +289,48 @@ window.pdfViewer = {
this.wheelEventAttached = false;
this.dotNetReference = null;
}
this.detachResizeListeners();
},
// Resizable splitter functionality
isResizing: false,
resizeMouseMoveHandler: null,
resizeMouseUpHandler: null,
attachResizeListeners(dotNetRef) {
this.dotNetReference = dotNetRef;
this.resizeMouseMoveHandler = (e) => {
if (this.isResizing && this.dotNetReference) {
this.dotNetReference.invokeMethodAsync('OnSplitterMouseMove', e.clientX);
}
};
this.resizeMouseUpHandler = () => {
if (this.isResizing && this.dotNetReference) {
this.isResizing = false;
this.dotNetReference.invokeMethodAsync('OnSplitterMouseUp');
}
};
document.addEventListener('mousemove', this.resizeMouseMoveHandler);
document.addEventListener('mouseup', this.resizeMouseUpHandler);
},
detachResizeListeners() {
if (this.resizeMouseMoveHandler) {
document.removeEventListener('mousemove', this.resizeMouseMoveHandler);
this.resizeMouseMoveHandler = null;
}
if (this.resizeMouseUpHandler) {
document.removeEventListener('mouseup', this.resizeMouseUpHandler);
this.resizeMouseUpHandler = null;
}
this.isResizing = false;
},
startResize() {
this.isResizing = true;
}
};