mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
fix(app): keep tooltips inside the fullscreen element (#1968)
This commit is contained in:
1 parent
51e2eee15a
commit
f56ccf5ef5
2 files changed
+30
-4
No files matched your search
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import Accessibility from '@app/features/accessibility/state/Accessibility';
|
import Accessibility from '@app/features/accessibility/state/Accessibility';
|
||||||
import {Logger} from '@app/features/platform/utils/AppLogger';
|
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 {appZoomCssPx, appZoomLayoutPx} from '@app/features/ui/utils/AppZoomUtils';
|
||||||
import {
|
import {
|
||||||
getReducedMotionProps,
|
getReducedMotionProps,
|
||||||
@@ -101,9 +101,17 @@ export function useSliderTooltip({
|
|||||||
left: '-9999px',
|
left: '-9999px',
|
||||||
top: '-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, {
|
const {x, y, middlewareData} = await computePosition(target, tooltip, {
|
||||||
placement: 'top',
|
placement: 'top',
|
||||||
|
strategy: 'fixed',
|
||||||
middleware,
|
middleware,
|
||||||
});
|
});
|
||||||
Object.assign(tooltip.style, {
|
Object.assign(tooltip.style, {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
subscribeWindowHoverControlsChange,
|
subscribeWindowHoverControlsChange,
|
||||||
} from '@app/features/ui/utils/WindowFocusInteractionGuard';
|
} from '@app/features/ui/utils/WindowFocusInteractionGuard';
|
||||||
import {elementSupportsRef} from '@app/lib/react';
|
import {elementSupportsRef} from '@app/lib/react';
|
||||||
|
import type {ExtendedDocument} from '@app/types/browser.d';
|
||||||
import {FloatingPortal} from '@floating-ui/react';
|
import {FloatingPortal} from '@floating-ui/react';
|
||||||
import {arrow, autoUpdate, computePosition, flip, offset, shift} from '@floating-ui/react-dom';
|
import {arrow, autoUpdate, computePosition, flip, offset, shift} from '@floating-ui/react-dom';
|
||||||
import {clsx} from 'clsx';
|
import {clsx} from 'clsx';
|
||||||
@@ -47,6 +48,20 @@ const TOOLTIP_AUTO_UPDATE_OPTIONS = {
|
|||||||
layoutShift: true,
|
layoutShift: true,
|
||||||
} as const;
|
} 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 tooltipPortalRoots = new WeakMap<Document, HTMLElement>();
|
||||||
|
|
||||||
const getTooltipPortalRoot = (ownerDocument: Document): HTMLElement => {
|
const getTooltipPortalRoot = (ownerDocument: Document): HTMLElement => {
|
||||||
@@ -389,14 +404,17 @@ export const Tooltip = observer(
|
|||||||
left: '-9999px',
|
left: '-9999px',
|
||||||
top: '-9999px',
|
top: '-9999px',
|
||||||
} as CSSStyleDeclaration);
|
} as CSSStyleDeclaration);
|
||||||
|
const overflowBoundary = getFullscreenOverflowBoundary(target);
|
||||||
|
const boundaryOptions = overflowBoundary ? {boundary: overflowBoundary} : undefined;
|
||||||
const middleware = [
|
const middleware = [
|
||||||
offset(padding + nudge),
|
offset(padding + nudge),
|
||||||
flip(),
|
flip(boundaryOptions),
|
||||||
shift({padding: 8}),
|
shift({padding: 8, ...boundaryOptions}),
|
||||||
...(arrowRef.current ? [arrow({element: arrowRef.current})] : []),
|
...(arrowRef.current ? [arrow({element: arrowRef.current})] : []),
|
||||||
];
|
];
|
||||||
const {x, y, placement, middlewareData} = await computePosition(target, tooltip, {
|
const {x, y, placement, middlewareData} = await computePosition(target, tooltip, {
|
||||||
placement: position,
|
placement: position,
|
||||||
|
strategy: 'fixed',
|
||||||
middleware,
|
middleware,
|
||||||
});
|
});
|
||||||
if (
|
if (
|
||||||
|
|||||||
Reference in new issue
Block a user