fix(playlists): flip the add-to-playlist popover up when it would overflow
The popover was always positioned below its trigger, so on cards near the bottom of the viewport it ran off-screen. Measure the panel's real height and open it upward (clamped to the viewport) when there isn't room below; also clamp the horizontal position.
This commit is contained in:
parent
40a44cdde2
commit
fb5a2f1ed2
1 changed files with 18 additions and 5 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
|
@ -29,14 +29,27 @@ export default function AddToPlaylist({
|
||||||
enabled: open,
|
enabled: open,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Re-place once the panel is actually rendered (so we know its real height) and whenever
|
||||||
|
// its content — hence height — changes, so the flip-above decision uses the true size.
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (open) place();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [open, membership.data]);
|
||||||
|
|
||||||
function place() {
|
function place() {
|
||||||
const r = triggerRef.current?.getBoundingClientRect();
|
const r = triggerRef.current?.getBoundingClientRect();
|
||||||
if (!r) return;
|
if (!r) return;
|
||||||
const width = 240;
|
const width = 240;
|
||||||
setCoords({
|
const margin = 8;
|
||||||
top: Math.round(r.bottom + 6),
|
// Use the panel's real height once it's mounted; estimate on the first open.
|
||||||
left: Math.round(Math.min(r.left, window.innerWidth - width - 8)),
|
const h = panelRef.current?.offsetHeight ?? 300;
|
||||||
});
|
let top = r.bottom + 6;
|
||||||
|
if (top + h > window.innerHeight - margin) {
|
||||||
|
// Not enough room below — open upward, clamped to the viewport.
|
||||||
|
top = Math.max(margin, r.top - h - 6);
|
||||||
|
}
|
||||||
|
const left = Math.min(Math.max(margin, r.left), window.innerWidth - width - margin);
|
||||||
|
setCoords({ top: Math.round(top), left: Math.round(left) });
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleOpen(e: React.MouseEvent) {
|
function toggleOpen(e: React.MouseEvent) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue