Skip to content

Commit 0bb61f4

Browse files
committed
Trying to improve accuracy
1 parent edc202d commit 0bb61f4

3 files changed

Lines changed: 37 additions & 18 deletions

File tree

core/src/components/popover/animations/ios.enter.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,10 @@ export const iosEnterAnimation = (baseEl: HTMLElement, opts?: any): Animation =>
133133
* safe-area inset to ensure the popover doesn't overlap with system UI
134134
* (status bars, home indicators, navigation bars on Android API 36+, etc.)
135135
*/
136-
const safeAreaTop = ' + var(--ion-safe-area-top, 0)';
137-
const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0)';
138-
const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
139-
const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
136+
const safeAreaTop = ' + var(--ion-safe-area-top, 0px)';
137+
const safeAreaBottom = ' + var(--ion-safe-area-bottom, 0px)';
138+
const safeAreaLeft = ' + var(--ion-safe-area-left, 0px)';
139+
const safeAreaRight = ' - var(--ion-safe-area-right, 0px)';
140140

141141
let topValue = `${top}px`;
142142
let bottomValue = bottom !== undefined ? `${bottom}px` : undefined;
@@ -159,20 +159,27 @@ export const iosEnterAnimation = (baseEl: HTMLElement, opts?: any): Animation =>
159159
contentEl.style.setProperty('bottom', `calc(${bottomValue})`);
160160
/**
161161
* When both top and bottom are explicitly constrained (isFullyConstrained),
162-
* we need to override the height: var(--height) style to allow the
163-
* top/bottom constraint to determine the height.
162+
* we need to explicitly calculate the height to ensure the popover
163+
* fits within the safe area boundaries.
164164
*
165-
* We only do this when fully constrained because setting height: unset
166-
* when only bottom is set (without explicit top) would result in an
167-
* incorrectly sized popover.
165+
* Using CSS calc with 100vh minus top and bottom values ensures the
166+
* popover height respects both safe areas. We also override max-height
167+
* to prevent it from interfering with the calculated height.
168168
*/
169169
if (isFullyConstrained) {
170-
contentEl.style.setProperty('height', 'unset');
170+
/**
171+
* Wrap topValue and bottomValue in parentheses to ensure correct
172+
* order of operations in the CSS calc. Without parentheses, the
173+
* safe-area additions would have wrong signs.
174+
*/
175+
const heightCalc = `calc(100vh - (${topValue}) - (${bottomValue}) - var(--offset-y, 0px))`;
176+
contentEl.style.setProperty('height', heightCalc);
177+
contentEl.style.setProperty('max-height', heightCalc);
171178
}
172179
}
173180

174-
contentEl.style.setProperty('top', `calc(${topValue} + var(--offset-y, 0))`);
175-
contentEl.style.setProperty('left', `calc(${leftValue} + var(--offset-x, 0))`);
181+
contentEl.style.setProperty('top', `calc(${topValue} + var(--offset-y, 0px))`);
182+
contentEl.style.setProperty('left', `calc(${leftValue} + var(--offset-x, 0px))`);
176183
contentEl.style.setProperty('transform-origin', `${originY} ${originX}`);
177184

178185
if (arrowEl !== null) {

core/src/components/popover/animations/md.enter.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,22 @@ export const mdEnterAnimation = (baseEl: HTMLElement, opts?: any): Animation =>
137137
contentEl.style.setProperty('bottom', `calc(${bottomValue})`);
138138
/**
139139
* When both top and bottom are explicitly constrained (isFullyConstrained),
140-
* we need to override the height: var(--height) style to allow the
141-
* top/bottom constraint to determine the height.
140+
* we need to explicitly calculate the height to ensure the popover
141+
* fits within the safe area boundaries.
142142
*
143-
* We only do this when fully constrained because setting height: unset
144-
* when only bottom is set (without explicit top) would result in an
145-
* incorrectly sized popover.
143+
* Using CSS calc with 100vh minus top and bottom values ensures the
144+
* popover height respects both safe areas. We also override max-height
145+
* to prevent it from interfering with the calculated height.
146146
*/
147147
if (isFullyConstrained) {
148-
contentEl.style.setProperty('height', 'unset');
148+
/**
149+
* Wrap topValue and bottomValue in parentheses to ensure correct
150+
* order of operations in the CSS calc. Without parentheses, the
151+
* safe-area additions would have wrong signs.
152+
*/
153+
const heightCalc = `calc(100vh - (${topValue}) - (${bottomValue}) - var(--offset-y, 0px))`;
154+
contentEl.style.setProperty('height', heightCalc);
155+
contentEl.style.setProperty('max-height', heightCalc);
149156
}
150157
}
151158
})

core/src/components/popover/utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,8 +965,13 @@ export const calculateWindowAdjustment = (
965965
/**
966966
* Set a bottom constraint to push the popover up out of the safe-area zone.
967967
* The animation will add the safe-area CSS variable to this value.
968+
*
969+
* We also set isFullyConstrained so that height: unset is applied,
970+
* allowing the bottom constraint to actually take effect (otherwise
971+
* the explicit height would override the bottom constraint).
968972
*/
969973
bottom = bodyPadding;
974+
isFullyConstrained = true;
970975
}
971976
if (top < safeAreaMargin) {
972977
checkSafeAreaTop = true;

0 commit comments

Comments
 (0)