Skip to content

Commit e35cc1a

Browse files
authored
fix(ui5-popover): calculate offset for all sides of the page (#2916)
1 parent 07cd7c5 commit e35cc1a

File tree

4 files changed

+74
-29
lines changed

4 files changed

+74
-29
lines changed

packages/base/src/util/clamp.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* Returns a value clamped between an upper bound 'max' and lower bound 'min'.
3+
* @param {number} val value
4+
* @param {number} min lower bound
5+
* @param {number} max upper bound
6+
* @returns {number}
7+
*/
8+
const clamp = (val, min, max) => {
9+
return Math.min(Math.max(val, min), max);
10+
};
11+
12+
export default clamp;

packages/main/src/Dialog.js

+5-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { isPhone, isDesktop } from "@ui5/webcomponents-base/dist/Device.js";
2+
import clamp from "@ui5/webcomponents-base/dist/util/clamp.js";
23
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
34
import Popup from "./Popup.js";
45
import "@ui5/webcomponents-icons/dist/resize-corner.js";
@@ -223,10 +224,6 @@ class Dialog extends Popup {
223224
this._center();
224225
}
225226

226-
_clamp(val, min, max) {
227-
return Math.min(Math.max(val, min), max);
228-
}
229-
230227
onBeforeRendering() {
231228
this._isRTL = this.effectiveDir === "rtl";
232229
this.onPhone = isPhone();
@@ -386,26 +383,26 @@ class Dialog extends Popup {
386383
let newLeft;
387384

388385
if (this._isRTL) {
389-
newWidth = this._clamp(
386+
newWidth = clamp(
390387
this._initialWidth - (clientX - this._initialX),
391388
this._minWidth,
392389
this._initialLeft + this._initialWidth,
393390
);
394391

395-
newLeft = this._clamp(
392+
newLeft = clamp(
396393
this._initialLeft + (clientX - this._initialX),
397394
0,
398395
this._initialX + this._initialWidth - this._minWidth,
399396
);
400397
} else {
401-
newWidth = this._clamp(
398+
newWidth = clamp(
402399
this._initialWidth + (clientX - this._initialX),
403400
this._minWidth,
404401
window.innerWidth - this._initialLeft,
405402
);
406403
}
407404

408-
const newHeight = this._clamp(
405+
const newHeight = clamp(
409406
this._initialHeight + (clientY - this._initialY),
410407
this._minHeight,
411408
window.innerHeight - this._initialTop,

packages/main/src/Popover.js

+43-21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Integer from "@ui5/webcomponents-base/dist/types/Integer.js";
22
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
33
import { getClosedPopupParent } from "@ui5/webcomponents-base/dist/util/PopupUtils.js";
4+
import clamp from "@ui5/webcomponents-base/dist/util/clamp.js";
45
import Popup from "./Popup.js";
56
import PopoverPlacementType from "./types/PopoverPlacementType.js";
67
import PopoverVerticalAlign from "./types/PopoverVerticalAlign.js";
@@ -396,15 +397,44 @@ class Popover extends Popup {
396397

397398
this._oldPlacement = placement;
398399

400+
const left = clamp(
401+
this._left,
402+
Popover.MIN_OFFSET,
403+
document.documentElement.clientWidth - popoverSize.width - Popover.MIN_OFFSET,
404+
);
405+
406+
const top = clamp(
407+
this._top,
408+
Popover.MIN_OFFSET,
409+
document.documentElement.clientHeight - popoverSize.height - Popover.MIN_OFFSET,
410+
);
411+
412+
let { arrowX, arrowY } = placement;
413+
399414
const popoverOnLeftBorder = this._left === 0;
415+
const popoverOnRightBorder = this._left + popoverSize.width >= document.documentElement.clientWidth;
416+
if (popoverOnLeftBorder) {
417+
arrowX -= Popover.MIN_OFFSET;
418+
} else if (popoverOnRightBorder) {
419+
arrowX += Popover.MIN_OFFSET;
420+
}
421+
this.arrowTranslateX = arrowX;
422+
400423
const popoverOnTopBorder = this._top === 0;
424+
const popoverOnBottomBorder = this._top + popoverSize.height >= document.documentElement.clientHeight;
425+
if (popoverOnTopBorder) {
426+
arrowY -= Popover.MIN_OFFSET;
427+
} else if (popoverOnBottomBorder) {
428+
arrowY += Popover.MIN_OFFSET;
429+
}
430+
this.arrowTranslateY = arrowY;
401431

402432
this.actualPlacementType = placement.placementType;
403-
this.arrowTranslateX = popoverOnLeftBorder ? placement.arrowX - Popover.MIN_OFFSET : placement.arrowX;
404-
this.arrowTranslateY = popoverOnTopBorder ? placement.arrowY - Popover.MIN_OFFSET : placement.arrowY;
405433

406-
this.style.left = `${popoverOnLeftBorder ? Popover.MIN_OFFSET : this._left}px`;
407-
this.style.top = `${popoverOnTopBorder ? Popover.MIN_OFFSET : this._top}px`;
434+
Object.assign(this.style, {
435+
top: `${top}px`,
436+
left: `${left}px`,
437+
});
408438
super.show();
409439

410440
if (stretching && this._width) {
@@ -413,25 +443,17 @@ class Popover extends Popup {
413443
}
414444

415445
getPopoverSize() {
416-
let width,
417-
height;
418-
let rect = this.getBoundingClientRect();
419-
420-
if (this.opened) {
421-
width = rect.width;
422-
height = rect.height;
423-
424-
return { width, height };
446+
if (!this.opened) {
447+
Object.assign(this.style, {
448+
display: "block",
449+
top: "-10000px",
450+
left: "-10000px",
451+
});
425452
}
426453

427-
this.style.display = "block";
428-
this.style.top = "-10000px";
429-
this.style.left = "-10000px";
430-
431-
rect = this.getBoundingClientRect();
432-
433-
width = rect.width;
434-
height = rect.height;
454+
const rect = this.getBoundingClientRect(),
455+
width = rect.width,
456+
height = rect.height;
435457

436458
return { width, height };
437459
}

packages/main/test/pages/Popover.html

+14
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,16 @@
402402
</div>
403403
</ui5-popover>
404404

405+
<div style="display: flex; justify-content: flex-end;">
406+
<ui5-button id="btnRightEdge">Popover on right edge of screen</ui5-button>
407+
</div>
408+
409+
<ui5-popover header-text="Header" id="popoverRightEdge" placement-type="Top">
410+
<ui5-label>Input field: </ui5-label>
411+
<ui5-input></ui5-input>
412+
</ui5-popover>
413+
414+
405415
<script>
406416
btn.addEventListener("click", function (event) {
407417
pop.openBy(btn);
@@ -515,6 +525,10 @@
515525
popXRightWide.openBy(btnOpenXRightWide);
516526
});
517527

528+
btnRightEdge.addEventListener("click", function () {
529+
popoverRightEdge.openBy(btnRightEdge);
530+
});
531+
518532
</script>
519533
</body>
520534

0 commit comments

Comments
 (0)