From 48787af11c2365b1e803e639f5077fdb95e26062 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Wed, 19 Aug 2026 01:13:40 +0200 Subject: [PATCH] fix(channels): keep the About popover on-screen at high browser zoom At elevated zoom the CSS viewport shrinks; a long channel About wanted its fixed max-h-112 (448px) height, so when floating-ui flipped it above the trigger its top rendered above the viewport edge, clipped and unreachable (the inner overflow-y-auto can't scroll past its own top). Enable the popover's fitHeight so the `size` middleware caps the panel to the available space. Because the surface splits into an outer positioned element and an inner styled/scroll wrapper, the middleware now also publishes the available height as a --fit-max-h custom property the inner scroller consumes via maxHeight: min(28rem, var(--fit-max-h)), keeping the 28rem design cap on a tall viewport and shrinking to fit on a short one. --- frontend/src/components/AboutCell.tsx | 9 ++++++++- frontend/src/components/AnchoredPopover.tsx | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/AboutCell.tsx b/frontend/src/components/AboutCell.tsx index 9ddb995f..e26bc63d 100644 --- a/frontend/src/components/AboutCell.tsx +++ b/frontend/src/components/AboutCell.tsx @@ -28,6 +28,10 @@ export default function AboutCell({ text, channelId }: { text: string | null; ch offset: 6, // Pop instantly like the old cell did; the close grace lets the cursor reach the card. hoverDelay: { open: 0, close: 160 }, + // Cap the panel to the space between the trigger and the viewport edge (publishes --fit-max-h) so a + // long About never runs its top off-screen — at high browser zoom the short viewport made a fixed + // max-height overflow above the top edge, where the scroll container can't reach. + fitHeight: true, }); const { data: ch } = useQuery({ @@ -51,7 +55,10 @@ export default function AboutCell({ text, channelId }: { text: string | null; ch {/* Full About once the detail loads; until then the list's truncated description. */} {ch ? ( diff --git a/frontend/src/components/AnchoredPopover.tsx b/frontend/src/components/AnchoredPopover.tsx index 7e70d586..de4526a1 100644 --- a/frontend/src/components/AnchoredPopover.tsx +++ b/frontend/src/components/AnchoredPopover.tsx @@ -131,7 +131,14 @@ export function useAnchoredPopover(opts: AnchoredPopoverOptions) { size({ padding: 8, apply({ availableHeight, elements }) { + // Cap the positioned element, AND publish the available space as a custom property so + // the INNER styled/scroll wrapper (PopoverSurface renders `className` on a child, not on + // the floating element) can cap itself too — e.g. `maxHeight: min(28rem, var(--fit-max-h))` + // keeps a caller's design cap while still shrinking to fit at high zoom / short viewports. + // Capping only the outer element would leave the inner overflow-y-auto box at its fixed + // height, spilling its top off-screen (the whole point of fitHeight). elements.floating.style.maxHeight = `${availableHeight}px`; + elements.floating.style.setProperty("--fit-max-h", `${availableHeight}px`); }, }), ]