Fix WP description edit scrolling to page bottom on activation

https://community.openproject.org/wp/OP-19226

When clicking the description to enter inline edit mode, the display
container (holding the read-only description text) is immediately hidden
via [hidden]="active", removing its full height from the layout. At the
same time, the edit container becomes visible but is initially empty —
the Angular portal that renders CKEditor resolves asynchronously, after
detectChanges() has already flushed.

This causes a temporary collapse of the page height. If the current
scroll position exceeds the new page maximum, the browser clamps
window.scrollY to the new bottom. By the time CKEditor finishes
rendering and the page height recovers, the scroll position is already
stuck at the bottom.

This behaviour was observed in Firefox only; Chrome does not clamp the
scroll position in the same way when page height shrinks. Safari was not
tested.

Fix by capturing the display container's height before detectChanges()
runs and setting it as min-height on the inner block wrapper div. This
keeps the page height stable throughout the transition so the browser
has no reason to clamp the scroll. The min-height is cleared when the
field is deactivated.

Note: min-height must be applied to the wrapper div (display:block), not
to the host element op-editable-attribute-field, which is display:inline
and ignores min-height.
This commit is contained in:
Christophe Bliard
2026-06-11 18:47:34 +02:00
parent 45c29be300
commit 88a1837c89
@@ -90,6 +90,24 @@ export class EditableAttributeFieldComponent extends UntilDestroyedMixin impleme
public destroyed = false;
public setActive(active = true):void {
if (active && !this.active) {
// When switching to edit mode, the display container collapses immediately
// (display:none) while the edit portal renders asynchronously. This shrinks
// the page height and the browser clamps scroll to the new maximum, causing
// the page to jump to the bottom. Preserve the wrapper height to prevent this.
// Note: min-height must be set on the block wrapper div, not the host element
// (op-editable-attribute-field is display:inline and ignores min-height).
const wrapperEl = this.displayContainer.nativeElement.parentElement;
const height = this.displayContainer.nativeElement.offsetHeight;
if (wrapperEl && height > 0) {
wrapperEl.style.minHeight = `${height}px`;
}
} else if (!active) {
const wrapperEl = this.displayContainer.nativeElement.parentElement;
if (wrapperEl) {
wrapperEl.style.minHeight = '';
}
}
this.active = active;
if (!this.componentDestroyed) {
this.cdRef.detectChanges();
@@ -226,4 +244,3 @@ export class EditableAttributeFieldComponent extends UntilDestroyedMixin impleme
return this.schemaCache.of(this.resource);
}
}