Skip to content

Commit

Permalink
fix(popover): update positioning logic to render within body (#1109)
Browse files Browse the repository at this point in the history
## PR Checklist

Please check if your PR fulfills the following requirements:

- [X] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
- [ ] If applicable, have a visual design approval

## PR Type

What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->

- [X] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] Other... Please describe:

## What is the current behavior?

![datepicker popover position
example](https://github.com/vmware-clarity/ng-clarity/assets/34519388/0d078063-c542-472c-a892-d5864eb61756)

Issue Number: CDE-1508

## What is the new behavior?

![datepicker positioning logic after
example](https://github.com/vmware-clarity/ng-clarity/assets/34519388/61eecd6f-d708-468f-b6c9-8ab5c40c5db9)

## Does this PR introduce a breaking change?

- [ ] Yes
- [X] No

<!-- If this PR contains a breaking change, please describe the impact
and migration path for existing applications below. -->

## Other information
  • Loading branch information
williamernest authored Feb 2, 2024
1 parent 24fe115 commit 3a04da1
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,28 @@ export default function (): void {
expect(handleVerticalAxisTwoViolationsSpy).not.toHaveBeenCalled();
expect(handleHorizontalAxisTwoViolationsSpy.calls.count()).toEqual(1);
});

it('content is rendered within the the body (y >= 0) when AXIS is HORIZONTAL and there is a BOTTOM ViewportViolation', function (this: TestContext) {
const bottomLeftViolation: ClrPopoverPosition = {
axis: ClrAxis.VERTICAL,
side: ClrSide.AFTER,
anchor: ClrAlignment.END,
content: ClrAlignment.START,
};

// Set the popover content to be as big as the window
popoverContent.style.width = '25px';
popoverContent.style.height = window.innerHeight + 'px';
// Set the anchor element to render at the bottom of the body/window
this.eventService.anchorButtonRef.nativeElement.style.bottom = '100%';
this.eventService.anchorButtonRef.nativeElement.style.position = 'absolute';
this.positionService.position = bottomLeftViolation;
document.body.appendChild(popoverContent);
const result = this.positionService.alignContent(popoverContent);

// Verify the yOffset is not a negative value (on the view this would translate to a negative top value).
expect(result.yOffset).toBeGreaterThanOrEqual(0);
});
});

describe('handles content realignment', function (this: TestContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ export class ClrPopoverPositionService {
*
* Note, more than 3 viewport violations and there isn't anything we can do to help. Also when there are two
* violations, we can't help if the violations are TOP+BOTTOM || LEFT+RIGHT => There is no transformation we
* can make to the postion that will help.
* can make to the position that will help.
*
* Some examples:
* There is only one error and Primary axis is VERTICAL
* - this.handleVerticalAxisOneViolation has a switch that will use the error sum to apply the correct
* transform to the postion based on the reduction of visibilityViolations.
* transform to the position based on the reduction of visibilityViolations.
*
* There are two errors and Primary axis is HORIZONTAL
* - handleHorizontalAxisTwoViolations has a switch that uses the error sum to apply both transforms needed to
Expand Down Expand Up @@ -103,6 +103,15 @@ export class ClrPopoverPositionService {
this.contentOffsets.yOffset += Math.abs(this.currentContentCoords.top);
}

/**
* This detects the condition where the popover is flipped because it would violate the bottom of the viewport, but flipping it results in the
* popover rendering above the top of the body (y coordinate outside the body). In that event, it should be rendered within the body
* as much as possible, so this logic sets the top of popover to render touching the top of the body.
*/
if (this.contentOffsets.yOffset + this.currentAnchorCoords.y < 0) {
this.contentOffsets.yOffset = 0 - this.currentContentCoords.top;
}

return this.contentOffsets;
}

Expand Down

0 comments on commit 3a04da1

Please sign in to comment.