Skip to content

Commit 5ffbbd9

Browse files
authored
fix(ui5-popup): position arrows correctly (#2917)
When the Popover is aligned horizontally against the opener, but it is wider than the opener, the arrows will be centered to the middle of the opener element. Fixes: #2758 Fixes: #2401
1 parent cc4ab19 commit 5ffbbd9

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

packages/main/src/Popover.js

+40-8
Original file line numberDiff line numberDiff line change
@@ -529,9 +529,7 @@ class Popover extends Popup {
529529

530530
let maxContentHeight = Math.round(maxHeight);
531531

532-
const hasHeader = this.header.length || this.headerText;
533-
534-
if (hasHeader) {
532+
if (this._displayHeader) {
535533
const headerDomRef = this.shadowRoot.querySelector(".ui5-popup-header-root")
536534
|| this.shadowRoot.querySelector(".ui5-popup-header-text");
537535

@@ -542,9 +540,7 @@ class Popover extends Popup {
542540

543541
this._maxContentHeight = maxContentHeight;
544542

545-
const arrowXCentered = this.horizontalAlign === PopoverHorizontalAlign.Center || this.horizontalAlign === PopoverHorizontalAlign.Stretch;
546-
const arrowTranslateX = isVertical && arrowXCentered ? targetRect.left + targetRect.width / 2 - left - popoverSize.width / 2 : 0;
547-
const arrowTranslateY = !isVertical ? targetRect.top + targetRect.height / 2 - top - popoverSize.height / 2 : 0;
543+
let arrowPos = this.getArrowPosition(targetRect, popoverSize, left, isVertical);
548544

549545
if (this._left === undefined || Math.abs(this._left - left) > 1.5) {
550546
this._left = Math.round(left);
@@ -555,14 +551,50 @@ class Popover extends Popup {
555551
}
556552

557553
return {
558-
arrowX: Math.round(arrowTranslateX),
559-
arrowY: Math.round(arrowTranslateY),
554+
arrowX: arrowPos.x,
555+
arrowY: arrowPos.y,
560556
top: this._top,
561557
left: this._left,
562558
placementType,
563559
};
564560
}
565561

562+
/**
563+
* Calculates the position for the arrow.
564+
* @private
565+
* @param targetRect BoundingClientRect of the target element
566+
* @param popoverSize Width and height of the popover
567+
* @param left Left offset of the popover
568+
* @param isVertical if the popover is positioned vertically to the target element
569+
* @returns {{x: number, y: number}} Arrow's coordinates
570+
*/
571+
getArrowPosition(targetRect, popoverSize, left, isVertical) {
572+
let arrowXCentered = this.horizontalAlign === PopoverHorizontalAlign.Center || this.horizontalAlign === PopoverHorizontalAlign.Stretch;
573+
574+
if (this.horizontalAlign === PopoverHorizontalAlign.Right && left <= targetRect.left) {
575+
arrowXCentered = true;
576+
}
577+
578+
if (this.horizontalAlign === PopoverHorizontalAlign.Left && left + popoverSize.width >= targetRect.left + targetRect.width) {
579+
arrowXCentered = true;
580+
}
581+
582+
let arrowTranslateX = 0;
583+
if (isVertical && arrowXCentered) {
584+
arrowTranslateX = targetRect.left + targetRect.width / 2 - left - popoverSize.width / 2;
585+
}
586+
587+
let arrowTranslateY = 0;
588+
if (!isVertical) {
589+
arrowTranslateY = targetRect.top + targetRect.height / 2 - top - popoverSize.height / 2;
590+
}
591+
592+
return {
593+
x: Math.round(arrowTranslateX),
594+
y: Math.round(arrowTranslateY),
595+
};
596+
}
597+
566598
/**
567599
* Fallbacks to new placement, prioritizing <code>Left</code> and <code>Right</code> placements.
568600
* @private

packages/main/test/pages/Popover.html

+13
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,15 @@
368368
</div>
369369
</ui5-popover>
370370

371+
<div style="text-align: right;">
372+
<p>Right-aligned Popover, wider than button, arrow should be centered on the button</p>
373+
<ui5-button id="btnOpenXRightWide">Open</ui5-button>
374+
</div>
375+
376+
<ui5-popover id="popXRightWide" placement-type="Bottom" horizontal-align="Right">
377+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni architecto tenetur quia nam reprehenderit quas eveniet possimus similique quisquam culpa distinctio ex doloremque molestiae maxime sed harum, in exercitationem! Incidunt?
378+
</ui5-popover>
379+
371380
<br>
372381
<br>
373382

@@ -502,6 +511,10 @@
502511
popWithDiv.openBy(event.target);
503512
});
504513

514+
btnOpenXRightWide.addEventListener("click", function () {
515+
popXRightWide.openBy(btnOpenXRightWide);
516+
});
517+
505518
</script>
506519
</body>
507520

0 commit comments

Comments
 (0)