Skip to content

Commit

Permalink
pw_web: Improve scrolling behavior
Browse files Browse the repository at this point in the history
Changelist
- Enable/disable autoscroll based on scroll direction
- Add transition to jump-to-bottom button and bottom overflow indicator

Bug: b/298097109
Change-Id: I95b11dda409eeee4482937c20bed1b003e5a9239
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/171290
Reviewed-by: Amy Hu <[email protected]>
Presubmit-Verified: CQ Bot Account <[email protected]>
Commit-Queue: Luis Flores <[email protected]>
Reviewed-by: Asad Memon <[email protected]>
  • Loading branch information
Luis Flores authored and CQ Bot Account committed Sep 18, 2023
1 parent 2328c7a commit 0c5eb3d
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 41 deletions.
28 changes: 24 additions & 4 deletions pw_web/log-viewer/src/components/log-list/log-list.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,7 @@ export const styles = css`
}
th[hidden],
td[hidden],
.jump-to-bottom-btn[hidden] {
td[hidden] {
display: none;
}
Expand Down Expand Up @@ -172,9 +171,9 @@ export const styles = css`
--md-filled-button-hover-container-elevation: 4;
bottom: 2.25rem;
font-family: 'Roboto Flex', sans-serif;
left: 50%;
position: absolute;
transform: translate(-50%);
place-self: center;
transform: translateY(15%) scale(0.9);
}
.resize-handle {
Expand Down Expand Up @@ -272,6 +271,27 @@ export const styles = css`
outline: 1px solid var(--sys-log-viewer-color-table-mark);
}
.jump-to-bottom-btn,
.bottom-indicator {
opacity: 0;
transition:
opacity 100ms ease,
transform 100ms ease,
visibility 100ms ease;
visibility: hidden;
}
.jump-to-bottom-btn[data-visible='true'],
.bottom-indicator[data-visible='true'] {
opacity: 1;
transform: translateY(0) scale(1);
transition:
opacity 250ms ease,
transform 250ms ease,
250ms ease;
visibility: visible;
}
::-webkit-scrollbar {
box-shadow: inset 0 0 2rem 2rem var(--md-sys-color-surface-container-low);
-webkit-appearance: auto;
Expand Down
74 changes: 37 additions & 37 deletions pw_web/log-viewer/src/components/log-list/log-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ export class LogList extends LitElement {
@state()
private _scrollPercentageLeft = 0;

/** A number representing visibility of vertical scroll indicator. */
@state()
private _scrollDownOpacity = 0;

/** Indicates whether to enable autosizing of incoming log entries. */
@state()
private _autosizeLocked = false;
Expand All @@ -82,7 +78,6 @@ export class LogList extends LitElement {
@query('table') private _table!: HTMLTableElement;
@query('tbody') private _tableBody!: HTMLTableSectionElement;
@queryAll('tr') private _tableRows!: HTMLTableRowElement[];
@query('.jump-to-bottom-btn') private _jumpBottomBtn!: HTMLButtonElement;

/**
* Data used for column resizing including the column index, the starting
Expand All @@ -102,11 +97,13 @@ export class LogList extends LitElement {
private readonly AUTOSIZE_LIMIT: number = 8;
/** The minimum width (in px) for table columns. */
private readonly MIN_COL_WIDTH: number = 52;
/** The last known vertical scroll position of the table container. */
private lastScrollTop: number = 0;

firstUpdated() {
setInterval(() => this.updateHorizontalOverflowState(), 1000);

window.addEventListener('scroll', this.handleTableScroll);
this._tableContainer.addEventListener('scroll', this.handleTableScroll);
this._tableBody.addEventListener('rangeChanged', this.onRangeChanged);

const newRowObserver = new MutationObserver(this.onTableRowAdded);
Expand Down Expand Up @@ -189,9 +186,6 @@ export class LogList extends LitElement {
setTimeout(() => {
container.scrollTop = container.scrollHeight;
}, 0); // Complete any rendering tasks before scrolling

this._scrollDownOpacity = 0;
this._jumpBottomBtn.hidden = true;
}

/**
Expand Down Expand Up @@ -309,15 +303,31 @@ export class LogList extends LitElement {
*/
private handleTableScroll = () => {
const container = this._tableContainer;
const currentScrollTop = container.scrollTop;
const containerWidth = container.offsetWidth;
const scrollLeft = container.scrollLeft;
const scrollY =
container.scrollHeight - container.scrollTop - container.clientHeight;
container.scrollHeight - currentScrollTop - container.clientHeight;
const maxScrollLeft = container.scrollWidth - containerWidth;
const rowHeight = this._tableRows[0].offsetHeight;

this._scrollPercentageLeft = scrollLeft / maxScrollLeft || 0;
// Determine scroll direction and update the last known scroll position
const isScrollingVertically = currentScrollTop !== this.lastScrollTop;
const isScrollingUp = currentScrollTop < this.lastScrollTop;
this.lastScrollTop = currentScrollTop;

// Only run autoscroll logic if the user is scrolling vertically
if (!isScrollingVertically) {
return;
}

// User is scrolling up, disable autoscroll
if (isScrollingUp) {
this._autoscrollIsEnabled = false;
return;
}

// User is scrolling down, enable autoscroll if they're near the bottom
if (Math.abs(scrollY) <= 1) {
this._autoscrollIsEnabled = true;
return;
Expand All @@ -327,20 +337,7 @@ export class LogList extends LitElement {
this._autoscrollIsEnabled = false;
}

let debounceTimer: NodeJS.Timer | null = null;
if (debounceTimer) {
clearTimeout(debounceTimer);
}

debounceTimer = setTimeout(() => {
if (Math.round(scrollY - rowHeight) >= 1) {
this._jumpBottomBtn.hidden = false;
this._scrollDownOpacity = 1;
} else {
this._jumpBottomBtn.hidden = true;
this._scrollDownOpacity = 0;
}
}, 100);
this._scrollPercentageLeft = scrollLeft / maxScrollLeft || 0;
};

/**
Expand Down Expand Up @@ -454,18 +451,8 @@ export class LogList extends LitElement {
})}
</tbody>
</table>
${this.overflowIndicators()}
${this.overflowIndicators()} ${this.jumpToBottomButton()}
</div>
<md-filled-button
class="jump-to-bottom-btn"
title="Jump to Bottom"
@click="${this.scrollTableToBottom}"
leading-icon
hidden
>
<md-icon slot="icon" aria-hidden="true">arrow_downward</md-icon>
Jump to Bottom
</md-filled-button>
`;
}

Expand Down Expand Up @@ -591,7 +578,7 @@ export class LogList extends LitElement {
private overflowIndicators = () => html`
<div
class="bottom-indicator"
style="opacity: ${this._scrollDownOpacity}"
data-visible="${this._autoscrollIsEnabled ? 'false' : 'true'}"
></div>
<div
Expand All @@ -606,4 +593,17 @@ export class LogList extends LitElement {
?hidden="${!this._isOverflowingToRight}"
></div>
`;

private jumpToBottomButton = () => html`
<md-filled-button
class="jump-to-bottom-btn"
title="Jump to Bottom"
@click="${this.scrollTableToBottom}"
leading-icon
data-visible="${this._autoscrollIsEnabled ? 'false' : 'true'}"
>
<md-icon slot="icon" aria-hidden="true">arrow_downward</md-icon>
Jump to Bottom
</md-filled-button>
`;
}

0 comments on commit 0c5eb3d

Please sign in to comment.