feat(dees-pdf-viewer): improve scrolling behavior and styles for better user experience

This commit is contained in:
2025-09-20 22:03:47 +00:00
parent a95d5a96a0
commit 352fe79791
2 changed files with 58 additions and 13 deletions

View File

@@ -528,10 +528,16 @@ export class DeesPdfViewer extends DeesElement {
const isBelow = thumbnailRect.bottom > sidebarRect.bottom;
if (isAbove || isBelow) {
// Scroll the thumbnail into view, centering it if possible
thumbnail.scrollIntoView({
behavior: 'smooth',
block: 'center'
// Calculate the scroll position to center the thumbnail
const thumbnailOffset = thumbnail.offsetTop;
const thumbnailHeight = thumbnail.offsetHeight;
const sidebarHeight = sidebarContent.clientHeight;
const targetScrollTop = thumbnailOffset - (sidebarHeight / 2) + (thumbnailHeight / 2);
// Scroll the sidebar to center the thumbnail
sidebarContent.scrollTo({
top: Math.max(0, targetScrollTop),
behavior: 'smooth'
});
}
}
@@ -541,10 +547,23 @@ export class DeesPdfViewer extends DeesElement {
await this.updateComplete;
const pageWrapper = this.shadowRoot?.querySelector(`.page-wrapper[data-page="${pageNum}"]`) as HTMLElement;
if (pageWrapper && this.viewerMain) {
pageWrapper.scrollIntoView({
behavior: smooth ? 'smooth' : 'auto',
block: 'start'
});
// Calculate the offset of the page wrapper relative to the viewer
const pageRect = pageWrapper.getBoundingClientRect();
const viewerRect = this.viewerMain.getBoundingClientRect();
const currentScrollTop = this.viewerMain.scrollTop;
// Calculate the target scroll position
const targetScrollTop = currentScrollTop + (pageRect.top - viewerRect.top) - this.viewerMain.clientTop;
// Scroll to the calculated position
if (smooth) {
this.viewerMain.scrollTo({
top: targetScrollTop,
behavior: 'smooth'
});
} else {
this.viewerMain.scrollTop = targetScrollTop;
}
// Update current page
this.currentPage = pageNum;
@@ -661,11 +680,6 @@ export class DeesPdfViewer extends DeesElement {
}
}
private async goToPage(pageNum: number) {
if (pageNum >= 1 && pageNum <= this.totalPages) {
await this.scrollToPage(pageNum);
}
}
private handleThumbnailClick(e: Event) {
const target = e.currentTarget as HTMLElement;
@@ -809,6 +823,28 @@ export class DeesPdfViewer extends DeesElement {
});
this.resizeObserver.observe(this.viewerMain);
this.measureViewportDimensions();
// Prevent scroll propagation to parent when scrolling inside viewer
this.viewerMain.addEventListener('wheel', (e) => {
const element = e.currentTarget as HTMLElement;
const scrollTop = element.scrollTop;
const scrollHeight = element.scrollHeight;
const clientHeight = element.clientHeight;
const deltaY = e.deltaY;
// Check if we're at the boundaries
const isAtTop = scrollTop === 0;
const isAtBottom = Math.abs(scrollTop + clientHeight - scrollHeight) < 1;
// Prevent propagation if we're scrolling within bounds
if ((deltaY < 0 && !isAtTop) || (deltaY > 0 && !isAtBottom)) {
e.stopPropagation();
} else if ((deltaY < 0 && isAtTop) || (deltaY > 0 && isAtBottom)) {
// Prevent default and propagation when at boundaries
e.preventDefault();
e.stopPropagation();
}
}, { passive: false });
}
}

View File

@@ -9,6 +9,7 @@ export const viewerStyles = [
height: 600px;
position: relative;
font-family: 'Geist Sans', sans-serif;
contain: layout style;
}
.pdf-viewer {
@@ -17,6 +18,8 @@ export const viewerStyles = [
display: flex;
flex-direction: column;
background: ${cssManager.bdTheme('hsl(0 0% 97%)', 'hsl(215 20% 10%)')};
position: relative;
overflow: hidden;
}
.toolbar {
@@ -109,6 +112,7 @@ export const viewerStyles = [
display: flex;
overflow: hidden;
position: relative;
min-height: 0;
}
.sidebar {
@@ -160,6 +164,8 @@ export const viewerStyles = [
display: flex;
flex-direction: column;
gap: 12px;
overscroll-behavior: contain;
min-height: 0;
}
.thumbnail {
@@ -210,6 +216,9 @@ export const viewerStyles = [
overflow-x: hidden;
padding: 20px;
scroll-behavior: smooth;
overscroll-behavior: contain;
min-height: 0;
position: relative;
}
.loading-container {