fix(ui): adjust submenu placement based on available viewport space
- add refs for submenu trigger and panel elements - compute available space above/below using getBoundingClientRect - dynamically set submenu side to avoid overflow outside viewport
This commit is contained in:
@@ -159,6 +159,26 @@ function BlockActionsMenu({
|
||||
const { side } = useDropdownPlacement(open, triggerRef);
|
||||
const [submenuOpen, setSubmenuOpen] = useState(false);
|
||||
const submenuTimerRef = useRef(null);
|
||||
const submenuTriggerRef = useRef(null);
|
||||
const submenuPanelRef = useRef(null);
|
||||
const [submenuSide, setSubmenuSide] = useState('below');
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!submenuOpen) return;
|
||||
const trigger = submenuTriggerRef.current;
|
||||
const panel = submenuPanelRef.current;
|
||||
if (!trigger || !panel || typeof window === 'undefined') return;
|
||||
const triggerRect = trigger.getBoundingClientRect();
|
||||
const panelHeight = panel.getBoundingClientRect().height;
|
||||
const vh = window.innerHeight;
|
||||
const spaceBelow = vh - triggerRect.top - DROPDOWN_VIEWPORT_MARGIN;
|
||||
const spaceAbove = triggerRect.bottom - DROPDOWN_VIEWPORT_MARGIN;
|
||||
if (panelHeight > spaceBelow && spaceAbove > spaceBelow) {
|
||||
setSubmenuSide('above');
|
||||
} else {
|
||||
setSubmenuSide('below');
|
||||
}
|
||||
}, [submenuOpen, transformOptions]);
|
||||
|
||||
function scheduleSubmenuClose() {
|
||||
if (submenuTimerRef.current) clearTimeout(submenuTimerRef.current);
|
||||
@@ -236,6 +256,7 @@ function BlockActionsMenu({
|
||||
<div className="p-1.5 flex flex-col gap-0.5">
|
||||
{transformOptions.length > 0 && (
|
||||
<div
|
||||
ref={submenuTriggerRef}
|
||||
className="relative"
|
||||
onMouseEnter={() => { cancelSubmenuClose(); setSubmenuOpen(true); }}
|
||||
onMouseLeave={scheduleSubmenuClose}
|
||||
@@ -250,7 +271,8 @@ function BlockActionsMenu({
|
||||
</div>
|
||||
{submenuOpen && (
|
||||
<div
|
||||
className="absolute left-full top-0 ml-1 w-56 rounded-xl border border-black/8 dark:border-white/8 bg-white dark:bg-[#0B0B0B] shadow-lg p-1.5 flex flex-col gap-0.5 z-50"
|
||||
ref={submenuPanelRef}
|
||||
className={`absolute left-full ${submenuSide === 'above' ? 'bottom-0' : 'top-0'} ml-1 w-56 rounded-xl border border-black/8 dark:border-white/8 bg-white dark:bg-[#0B0B0B] shadow-lg p-1.5 flex flex-col gap-0.5 z-50`}
|
||||
onMouseEnter={cancelSubmenuClose}
|
||||
onMouseLeave={scheduleSubmenuClose}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user