diff --git a/panel/models/column.ts b/panel/models/column.ts index a050e67c69..477859697f 100644 --- a/panel/models/column.ts +++ b/panel/models/column.ts @@ -12,6 +12,7 @@ export class ScrollButtonClick extends ModelEvent { export class ColumnView extends BkColumnView { declare model: Column + _updating: boolean = false scroll_down_button_el: HTMLElement @@ -30,6 +31,9 @@ export class ColumnView extends BkColumnView { } scroll_to_position(): void { + if (this._updating) { + return + } requestAnimationFrame(() => { this.el.scrollTo({top: this.model.scroll_position, behavior: "instant"}) }) @@ -56,7 +60,9 @@ export class ColumnView extends BkColumnView { } record_scroll_position(): void { + this._updating = true this.model.scroll_position = Math.round(this.el.scrollTop) + this._updating = false } toggle_scroll_button(): void { diff --git a/panel/models/feed.ts b/panel/models/feed.ts index c2231724f3..0e5feb3a63 100644 --- a/panel/models/feed.ts +++ b/panel/models/feed.ts @@ -2,12 +2,13 @@ import {Column, ColumnView} from "./column" import type * as p from "@bokehjs/core/properties" import {build_views} from "@bokehjs/core/build_views" import type {UIElementView} from "@bokehjs/models/ui/ui_element" +import {ColumnView as BkColumnView} from "@bokehjs/models/layouts/column" export class FeedView extends ColumnView { declare model: Feed - _intersection_observer: IntersectionObserver _last_visible: UIElementView | null + _lock: any = null _sync: boolean override initialize(): void { @@ -54,10 +55,19 @@ export class FeedView extends ColumnView { } override async update_children(): Promise { + const last = this._last_visible + const scroll_top = this.el.scrollTop + const before_offset = last?.el.offsetTop || 0 this._sync = false await super.update_children() this._sync = true - this._last_visible?.el.scrollIntoView(true) + requestAnimationFrame(() => { + const after_offset = last?.el.offsetTop || 0 + const offset = (after_offset-before_offset) + if (offset > 0) { + this.el.scrollTo({top: scroll_top + offset, behavior: "instant"}) + } + }) } override async build_child_views(): Promise {