mirror of
https://github.com/fluxerapp/fluxer.git
synced 2026-09-03 05:10:25 +03:00
fix(app): keep tooltips inside the fullscreen element (#1968)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import Accessibility from '@app/features/accessibility/state/Accessibility';
|
||||
import {Logger} from '@app/features/platform/utils/AppLogger';
|
||||
import {useTooltipPortalRoot} from '@app/features/ui/tooltip/Tooltip';
|
||||
import {getFullscreenOverflowBoundary, useTooltipPortalRoot} from '@app/features/ui/tooltip/Tooltip';
|
||||
import {appZoomCssPx, appZoomLayoutPx} from '@app/features/ui/utils/AppZoomUtils';
|
||||
import {
|
||||
getReducedMotionProps,
|
||||
@@ -101,9 +101,17 @@ export function useSliderTooltip({
|
||||
left: '-9999px',
|
||||
top: '-9999px',
|
||||
});
|
||||
const middleware = [offset(8), flip(), shift({padding: 8}), arrow({element: arrowRef})];
|
||||
const overflowBoundary = getFullscreenOverflowBoundary(target);
|
||||
const boundaryOptions = overflowBoundary ? {boundary: overflowBoundary} : undefined;
|
||||
const middleware = [
|
||||
offset(8),
|
||||
flip(boundaryOptions),
|
||||
shift({padding: 8, ...boundaryOptions}),
|
||||
arrow({element: arrowRef}),
|
||||
];
|
||||
const {x, y, middlewareData} = await computePosition(target, tooltip, {
|
||||
placement: 'top',
|
||||
strategy: 'fixed',
|
||||
middleware,
|
||||
});
|
||||
Object.assign(tooltip.style, {
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
subscribeWindowHoverControlsChange,
|
||||
} from '@app/features/ui/utils/WindowFocusInteractionGuard';
|
||||
import {elementSupportsRef} from '@app/lib/react';
|
||||
import type {ExtendedDocument} from '@app/types/browser.d';
|
||||
import {FloatingPortal} from '@floating-ui/react';
|
||||
import {arrow, autoUpdate, computePosition, flip, offset, shift} from '@floating-ui/react-dom';
|
||||
import {clsx} from 'clsx';
|
||||
@@ -47,6 +48,20 @@ const TOOLTIP_AUTO_UPDATE_OPTIONS = {
|
||||
layoutShift: true,
|
||||
} as const;
|
||||
|
||||
export const getFullscreenOverflowBoundary = (target: HTMLElement): HTMLElement | null => {
|
||||
const ownerDocument = target.ownerDocument as ExtendedDocument;
|
||||
const ownerWindow = ownerDocument.defaultView;
|
||||
if (!ownerWindow) return null;
|
||||
const fullscreenElement =
|
||||
ownerDocument.fullscreenElement ??
|
||||
ownerDocument.webkitFullscreenElement ??
|
||||
ownerDocument.mozFullScreenElement ??
|
||||
ownerDocument.msFullscreenElement ??
|
||||
null;
|
||||
if (!(fullscreenElement instanceof ownerWindow.HTMLElement)) return null;
|
||||
return fullscreenElement.contains(target) ? fullscreenElement : null;
|
||||
};
|
||||
|
||||
const tooltipPortalRoots = new WeakMap<Document, HTMLElement>();
|
||||
|
||||
const getTooltipPortalRoot = (ownerDocument: Document): HTMLElement => {
|
||||
@@ -389,14 +404,17 @@ export const Tooltip = observer(
|
||||
left: '-9999px',
|
||||
top: '-9999px',
|
||||
} as CSSStyleDeclaration);
|
||||
const overflowBoundary = getFullscreenOverflowBoundary(target);
|
||||
const boundaryOptions = overflowBoundary ? {boundary: overflowBoundary} : undefined;
|
||||
const middleware = [
|
||||
offset(padding + nudge),
|
||||
flip(),
|
||||
shift({padding: 8}),
|
||||
flip(boundaryOptions),
|
||||
shift({padding: 8, ...boundaryOptions}),
|
||||
...(arrowRef.current ? [arrow({element: arrowRef.current})] : []),
|
||||
];
|
||||
const {x, y, placement, middlewareData} = await computePosition(target, tooltip, {
|
||||
placement: position,
|
||||
strategy: 'fixed',
|
||||
middleware,
|
||||
});
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user