mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-12 12:37:04 +00:00
fix(ui): harden queue controls and floating menus
This commit is contained in:
@@ -3,6 +3,12 @@ export interface FloatingPosition {
|
||||
y: number;
|
||||
}
|
||||
|
||||
export type FloatingSubmenuSide = 'left' | 'right';
|
||||
|
||||
export interface FloatingSubmenuPosition extends FloatingPosition {
|
||||
side: FloatingSubmenuSide;
|
||||
}
|
||||
|
||||
/** Keep a fixed-position surface inside the viewport with a small safe gutter. */
|
||||
export const clampFloatingPosition = (
|
||||
x: number,
|
||||
@@ -21,3 +27,37 @@ export const clampFloatingPosition = (
|
||||
y: Math.min(Math.max(gutter, y), maxY),
|
||||
};
|
||||
};
|
||||
|
||||
/** Place a submenu beside its trigger, flipping sides before clamping to the viewport. */
|
||||
export const positionFloatingSubmenu = (
|
||||
trigger: Pick<DOMRect, 'left' | 'right' | 'top'>,
|
||||
width: number,
|
||||
height: number,
|
||||
viewportWidth: number,
|
||||
viewportHeight: number,
|
||||
gutter = 8,
|
||||
gap = 4,
|
||||
preferredSide: FloatingSubmenuSide = 'right'
|
||||
): FloatingSubmenuPosition => {
|
||||
const rightX = trigger.right + gap;
|
||||
const leftX = trigger.left - width - gap;
|
||||
const rightFits = rightX + width <= viewportWidth - gutter;
|
||||
const leftFits = leftX >= gutter;
|
||||
const preferredFits = preferredSide === 'right' ? rightFits : leftFits;
|
||||
const alternateFits = preferredSide === 'right' ? leftFits : rightFits;
|
||||
const side = preferredFits || !alternateFits
|
||||
? preferredSide
|
||||
: preferredSide === 'right' ? 'left' : 'right';
|
||||
const preferredX = side === 'right' ? rightX : leftX;
|
||||
const position = clampFloatingPosition(
|
||||
preferredX,
|
||||
trigger.top,
|
||||
width,
|
||||
height,
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
gutter
|
||||
);
|
||||
|
||||
return { ...position, side };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user