fix(context-menu): Move the reposition logic from the context menu to the dialog component. (#5060)

This commit is contained in:
Joe Boccanfuso authored and GitHub committed 2025-05-23 22:12:08 -04:00
1 parent fa9bbe3afc
commit cb814e6a60
3 files changed
+509 -496

No files matched your search

@@ -1,4 +1,4 @@
import React from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../components/Dialog/Dialog';
import { cn } from '../lib/utils';
@@ -34,6 +34,37 @@ const ManagedDialog: React.FC<ManagedDialogProps> = ({
unstyled,
containerClassName,
}) => {
// When a default position is provided, the assumption is that the position
// is respected unless the position chosen results in the dialog being
// clipped off-screen (i.e. part of the dialog is rendered outside the browser
// window). When the dialog is clipped it will be repositioned about
// the default position such that it is no longer clipped. To avoid a flash
// during the reposition, we initially hide the dialog.
const [contentVisibility, setContentVisibility] = useState(
defaultPosition ? 'invisible' : 'visible'
);
// The callback to reposition an explicitly positioned dialog. Note that
// if the dialog is larger than the window (in either dimension), the
// dialog will still be clipped in some manner.
const contentRef = useCallback(
contentNode => {
if (!contentNode) {
return;
}
const boundingClientRect = contentNode.getBoundingClientRect();
if (boundingClientRect.bottom > window.innerHeight) {
defaultPosition.y = defaultPosition.y - boundingClientRect.height;
}
if (boundingClientRect.right > window.innerWidth) {
defaultPosition.x = defaultPosition.x - boundingClientRect.width;
}
setContentVisibility('visible');
},
[defaultPosition]
);
return (
<Dialog
open={isOpen}
@@ -49,7 +80,8 @@ const ManagedDialog: React.FC<ManagedDialogProps> = ({
showOverlay={showOverlay}
>
<DialogContent
className={cn(unstyled ? 'p-0' : '', containerClassName)}
ref={contentRef}
className={cn(unstyled ? 'p-0' : '', containerClassName, contentVisibility)}
unstyled={unstyled}
style={{
...(defaultPosition
@@ -60,6 +92,7 @@ const ManagedDialog: React.FC<ManagedDialogProps> = ({
transform: 'translate(0, 0)',
margin: 0,
animation: 'none',
transition: 'none',
}
: {}),
}}