Skip to content

Commit a32d3bc

Browse files
fix(#3450): use manual positioning since polyfill isnt working
1 parent 357d10a commit a32d3bc

2 files changed

Lines changed: 70 additions & 26 deletions

File tree

libs/web-components/src/components/popover/Popover.svelte

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@
6767
// Private
6868
let _rootEl: HTMLElement;
6969
let _popoverEl: HTMLElement;
70+
const _needsPositionPolyfill = typeof document !== "undefined" && !("anchorName" in document.documentElement.style);
71+
let _positionRafId: number | null = null;
7072
7173
// Reactive
7274
let _targetEl: HTMLElement;
@@ -119,23 +121,62 @@
119121
showDeprecationWarnings();
120122
addGlobalCloseListener();
121123
window.addEventListener("resize", updateAutoPosition);
122-
mountAnchorPositioningPolyfill();
123124
});
124125
125126
onDestroy(() => {
127+
stopManualPositioning();
126128
window.removeEventListener("resize", updateAutoPosition);
127129
// true was passed when the listener was added, so it's necesary to be passed here as well
128130
window.removeEventListener("popstate", handleUrlChange, true);
129131
});
130132
131133
// Functions
132134
133-
function mountAnchorPositioningPolyfill() {
134-
if (window.ANCHOR_POSITIONING_POLYFILL) {
135-
const oldRoots = window.ANCHOR_POSITIONING_POLYFILL?.roots || [];
136-
window.ANCHOR_POSITIONING_POLYFILL({
137-
roots: [...oldRoots, _popoverEl.shadowRoot],
138-
});
135+
function updatePopoverPosition() {
136+
if (!_isOpen || !_targetEl || !_popoverEl) return;
137+
138+
const targetRect = _targetEl.getBoundingClientRect();
139+
const xOffset = hoffset ? parseFloat(hoffset) : 0;
140+
const yOffset = voffset ? parseFloat(voffset) : 3;
141+
142+
// Recalculate auto position based on current viewport space
143+
if (position === "auto") {
144+
const popoverRect = _popoverEl.getBoundingClientRect();
145+
const spaceAbove = targetRect.top;
146+
const spaceBelow = window.innerHeight - targetRect.bottom;
147+
148+
_autoPosition =
149+
spaceBelow < popoverRect.height && spaceAbove > spaceBelow
150+
? "above"
151+
: "below";
152+
}
153+
154+
const isAbove = position === "above" || (position === "auto" && _autoPosition === "above");
155+
156+
if (isAbove) {
157+
_popoverEl.style.top = `${targetRect.top - yOffset}px`;
158+
_popoverEl.style.left = `${targetRect.left + xOffset}px`;
159+
_popoverEl.style.transform = "translateY(-100%)";
160+
} else {
161+
_popoverEl.style.top = `${targetRect.bottom + yOffset}px`;
162+
_popoverEl.style.left = `${targetRect.left + xOffset}px`;
163+
_popoverEl.style.transform = "";
164+
}
165+
}
166+
167+
function startManualPositioning() {
168+
if (!_needsPositionPolyfill) return;
169+
const loop = () => {
170+
updatePopoverPosition();
171+
_positionRafId = requestAnimationFrame(loop);
172+
};
173+
_positionRafId = requestAnimationFrame(loop);
174+
}
175+
176+
function stopManualPositioning() {
177+
if (_positionRafId !== null) {
178+
cancelAnimationFrame(_positionRafId);
179+
_positionRafId = null;
139180
}
140181
}
141182
@@ -215,7 +256,9 @@
215256
if (_isOpen) {
216257
dispatch(_rootEl, "_open");
217258
requestAnimationFrame(updateAutoPosition); // same vs await tick(), make sure popover element is fully rendered before we measure its dimension
259+
startManualPositioning();
218260
} else {
261+
stopManualPositioning();
219262
_targetEl.focus();
220263
dispatch(_rootEl, "_close");
221264
}
@@ -359,24 +402,29 @@
359402
filter: var(--goa-popover-shadow, none);
360403
border: var(--goa-popover-border, none);
361404
margin: 0;
362-
363-
position-anchor: --goa-popover-target;
364-
inset-block-start: anchor(bottom);
365-
inset-inline-start: anchor(left);
366-
--popover-translate-x: var(--offset-left, 0);
367-
--popover-translate-y: var(--offset-top, 3px);
368-
translate: var(--popover-translate-x) var(--popover-translate-y);
405+
inset: auto;
369406
}
370407
371-
.popover-content.position-above {
372-
inset-block-start: anchor(top);
373-
--popover-translate-y: calc(-100% - var(--offset-bottom, 3px));
374-
position-try-fallbacks: none;
375-
}
408+
@supports (anchor-name: --a) {
409+
.popover-content {
410+
position-anchor: --goa-popover-target;
411+
inset-block-start: anchor(bottom);
412+
inset-inline-start: anchor(left);
413+
--popover-translate-x: var(--offset-left, 0);
414+
--popover-translate-y: var(--offset-top, 3px);
415+
translate: var(--popover-translate-x) var(--popover-translate-y);
416+
}
417+
418+
.popover-content.position-above {
419+
inset-block-start: anchor(top);
420+
--popover-translate-y: calc(-100% - var(--offset-bottom, 3px));
421+
position-try-fallbacks: none;
422+
}
376423
377-
.popover-content.position-below {
378-
inset-block-start: anchor(bottom);
379-
--popover-translate-y: var(--offset-top, 3px);
424+
.popover-content.position-below {
425+
inset-block-start: anchor(bottom);
426+
--popover-translate-y: var(--offset-top, 3px);
427+
}
380428
}
381429
382430
:global(::slotted(ul)) {

libs/web-components/vite.config.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,6 @@ export default defineConfig(({ mode }) => {
9292
},
9393
rollupOptions: {
9494
output: {
95-
intro: `if (!("anchorName" in document.documentElement.style)) {
96-
import("https://unpkg.com/@oddbird/css-anchor-positioning");
97-
}
98-
`,
9995
assetFileNames: (info) => {
10096
if (info.name === "style.css") {
10197
return "index.css";

0 commit comments

Comments
 (0)