From c74d4cfe2e0268fe097f29e4fd0ee7a485c6d470 Mon Sep 17 00:00:00 2001 From: ahfoysal Date: Mon, 6 Jul 2026 01:23:25 +0600 Subject: [PATCH] Fix flag picker overlap with share actions --- components/FlagPicker.tsx | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/components/FlagPicker.tsx b/components/FlagPicker.tsx index 3808007..45bb09c 100644 --- a/components/FlagPicker.tsx +++ b/components/FlagPicker.tsx @@ -1,6 +1,6 @@ "use client"; -import { useCallback, useEffect, useId, useMemo, useReducer, useRef } from "react"; +import { useCallback, useEffect, useId, useMemo, useReducer, useRef, useState, useLayoutEffect } from "react"; import { Pencil, Plus, Search, X } from "lucide-react"; import { searchCountries } from "@/lib/countries"; import { comboboxReducer, initialComboboxState } from "@/lib/comboboxNav"; @@ -37,6 +37,7 @@ export default function FlagPicker({ value, onChange }: Props) { const triggerRef = useRef(null); const searchRef = useRef(null); const listRef = useRef(null); + const [openAbove, setOpenAbove] = useState(false); const baseId = useId(); const listId = `${baseId}-list`; const optionId = (i: number) => `${baseId}-opt-${i}`; @@ -60,6 +61,21 @@ export default function FlagPicker({ value, onChange }: Props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [active, open]); + useLayoutEffect(() => { + if (!open) return; + + const trigger = triggerRef.current; + if (!trigger) return; + + const rect = trigger.getBoundingClientRect(); + const viewportHeight = window.innerHeight; + const spaceBelow = viewportHeight - rect.bottom - 12; + const spaceAbove = rect.top - 12; + const need = 300; // approximate popover height (search + max list + borders) + + setOpenAbove(spaceBelow < need && spaceAbove >= need); + }, [open, query]); + const choose = (code: string) => { onChange(code); dispatch({ type: "close" }); @@ -141,7 +157,12 @@ export default function FlagPicker({ value, onChange }: Props) { role="presentation" className="animate-pop pointer-events-auto absolute z-30 w-[280px] max-w-[80vw] overflow-hidden rounded-[14px] border border-line bg-panel/95 shadow-[0_18px_46px_-12px_rgba(0,0,0,.7)] backdrop-blur-[10px]" // anchor below the flag slot - style={{ left: SLOT.left, top: `calc(${SLOT.top} + ${SLOT.height} + 2.5%)` }} + style={{ + left: SLOT.left, + top: openAbove ? SLOT.top : `calc(${SLOT.top} + ${SLOT.height} + 2.5%)`, + transform: openAbove ? "translateY(-100%)" : undefined, + transformOrigin: openAbove ? "left bottom" : "left top", + }} >