diff --git a/src/popover/animations/ios.enter.ts b/src/popover/animations/ios.enter.ts index 8d68957..c0c108e 100644 --- a/src/popover/animations/ios.enter.ts +++ b/src/popover/animations/ios.enter.ts @@ -102,6 +102,7 @@ export const iosEnterAnimation = (baseEl: HTMLElement, opts: any = {}): Animatio results.referenceCoordinates, referenceSizeEl?.getBoundingClientRect(), isReplace, + opts.preserveHorizontalAlignment === true, ); // A replacing surface grows inward from the button's edge, not its center. const preferredLeft = diff --git a/src/popover/utils.spec.ts b/src/popover/utils.spec.ts index a18137c..a69aa79 100644 --- a/src/popover/utils.spec.ts +++ b/src/popover/utils.spec.ts @@ -4,10 +4,31 @@ import { calculateWindowAdjustment, getIndexOfItem, getNextItem, getPopoverPosit describe('popover utilities', () => { it.each(['left', 'right', 'start', 'end'] as const)('preserves the vertical anchor alignment for side=%s', (side) => { - const position = calculateWindowAdjustment(side, 120, 100, 5, 440, 636, 200, 52, 8, 'right', 'center'); + const position = calculateWindowAdjustment( + side, + 120, + 100, + 5, + 440, + 636, + 200, + 52, + 8, + 'right', + 'center', + undefined, + undefined, + false, + true, + ); expect(position.top).toBe(120); - expect(calculateWindowAdjustment(side, -4, 100, 5, 440, 636, 200, 52, 8, 'right', 'center').top).toBe(5); - expect(calculateWindowAdjustment(side, 620, 100, 5, 440, 636, 200, 52, 8, 'right', 'center').top).toBe(579); + expect(calculateWindowAdjustment(side, 120, 100, 5, 440, 636, 200, 52, 8, 'right', 'center').top).toBe(128); + expect( + calculateWindowAdjustment(side, -4, 100, 5, 440, 636, 200, 52, 8, 'right', 'center', undefined, undefined, false, true).top, + ).toBe(5); + expect( + calculateWindowAdjustment(side, 620, 100, 5, 440, 636, 200, 52, 8, 'right', 'center', undefined, undefined, false, true).top, + ).toBe(579); }); it('navigates only relative to ion-item elements', () => { diff --git a/src/popover/utils.ts b/src/popover/utils.ts index 5700079..e2cb4fc 100644 --- a/src/popover/utils.ts +++ b/src/popover/utils.ts @@ -612,11 +612,13 @@ export const calculateWindowAdjustment = ( triggerCoordinates?: ReferenceCoordinates, eventElementRect?: DOMRect, isReplace: boolean = false, + preserveHorizontalAlignment: boolean = false, ): PopoverStyles => { const triggerTop = triggerCoordinates ? triggerCoordinates.top + triggerCoordinates.height : bodyHeight / 2 - contentHeight / 2; const triggerHeight = triggerCoordinates ? triggerCoordinates.height : 0; let left = coordLeft; - const horizontal = side === 'left' || side === 'right' || side === 'start' || side === 'end'; + // Projected rail controls opt in; ordinary popovers retain their existing margin. + const horizontal = preserveHorizontalAlignment && (side === 'left' || side === 'right' || side === 'start' || side === 'end'); let top = !isReplace ? coordTop + (horizontal ? 0 : POPOVER_IOS_BODY_MARGIN) : coordTop - triggerHeight; if (horizontal && !isReplace) top = Math.max(bodyPadding, Math.min(top, bodyHeight - bodyPadding - contentHeight)); let bottom;