Prevent PersistedElements overflowing scrolled areas

As the DOM element is not in reality contained inside "the parent",
it may overflow the area if the parent gets partially hidden by
scrolling etc.

To make the effect visually less annoying, emulate this by clipping to
the element wrapper. This is not a full general-purpose fix, but
improves the current situation.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
This commit is contained in:
Pauli Virtanen 2020-04-21 01:19:39 +03:00
parent 3962c98c9b
commit d690d4bed2
2 changed files with 60 additions and 2 deletions

View file

@ -96,6 +96,10 @@ $AppsDrawerBodyHeight: 273px;
height: $AppsDrawerBodyHeight; height: $AppsDrawerBodyHeight;
} }
.mx_AppTile_persistedWrapper > div {
height: 100%;
}
.mx_AppTile_mini .mx_AppTile_persistedWrapper { .mx_AppTile_mini .mx_AppTile_persistedWrapper {
height: 114px; height: 114px;
} }

View file

@ -156,16 +156,70 @@ export default class PersistedElement extends React.Component {
child.style.display = visible ? 'block' : 'none'; child.style.display = visible ? 'block' : 'none';
} }
/*
* Clip element bounding rectangle to that of the parent elements.
* This is not a full visibility check, but prevents the persisted
* element from overflowing parent containers when inside a scrolled
* area.
*/
_getClippedBoundingClientRect(element) {
let parentElement = element.parentElement;
let rect = element.getBoundingClientRect();
rect = new DOMRect(rect.left, rect.top, rect.width, rect.height);
while (parentElement) {
const parentRect = parentElement.getBoundingClientRect();
if (parentRect.left > rect.left) {
rect.width = rect.width - (parentRect.left - rect.left);
rect.x = parentRect.x;
}
if (parentRect.top > rect.top) {
rect.height = rect.height - (parentRect.top - rect.top);
rect.y = parentRect.y;
}
if (parentRect.right < rect.right) {
rect.width = rect.width - (rect.right - parentRect.right);
}
if (parentRect.bottom < rect.bottom) {
rect.height = rect.height - (rect.bottom - parentRect.bottom);
}
parentElement = parentElement.parentElement;
}
if (rect.width < 0) rect.width = 0;
if (rect.height < 0) rect.height = 0;
return rect;
}
updateChildPosition(child, parent) { updateChildPosition(child, parent) {
if (!child || !parent) return; if (!child || !parent) return;
const parentRect = parent.getBoundingClientRect(); const parentRect = parent.getBoundingClientRect();
const clipRect = this._getClippedBoundingClientRect(parent);
Object.assign(child.parentElement.style, {
position: 'absolute',
top: clipRect.top + 'px',
left: clipRect.left + 'px',
width: clipRect.width + 'px',
height: clipRect.height + 'px',
overflow: "hidden",
});
Object.assign(child.style, { Object.assign(child.style, {
position: 'absolute', position: 'absolute',
top: parentRect.top + 'px', top: (parentRect.top - clipRect.top) + 'px',
left: parentRect.left + 'px', left: (parentRect.left - clipRect.left) + 'px',
width: parentRect.width + 'px', width: parentRect.width + 'px',
height: parentRect.height + 'px', height: parentRect.height + 'px',
overflow: "hidden",
}); });
} }