fix(component): modal overlap issue (#7691)

This commit is contained in:
EYHN 2024-08-01 08:03:21 +00:00
parent 33fc00f8c7
commit bb767a6cdc
No known key found for this signature in database
GPG Key ID: 46C9E26A75AB276C

View File

@ -10,7 +10,7 @@ import * as VisuallyHidden from '@radix-ui/react-visually-hidden';
import { assignInlineVars } from '@vanilla-extract/dynamic'; import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx'; import clsx from 'clsx';
import type { CSSProperties } from 'react'; import type { CSSProperties } from 'react';
import { forwardRef, useCallback } from 'react'; import { forwardRef, useCallback, useEffect, useState } from 'react';
import type { IconButtonProps } from '../button'; import type { IconButtonProps } from '../button';
import { IconButton } from '../button'; import { IconButton } from '../button';
@ -90,20 +90,22 @@ class ModalTransitionContainer extends HTMLElement {
} }
} }
let container: ModalTransitionContainer | null = null; let defined = false;
function prepareContainer() { function createContainer() {
if (!container) { if (!defined) {
customElements.define( customElements.define(
'modal-transition-container', 'modal-transition-container',
ModalTransitionContainer ModalTransitionContainer
); );
container = new ModalTransitionContainer(); defined = true;
document.body.append(container);
} }
const container = new ModalTransitionContainer();
document.body.append(container);
return container; return container;
} }
export const Modal = forwardRef<HTMLDivElement, ModalProps>((props, ref) => { export const ModalInner = forwardRef<HTMLDivElement, ModalProps>(
(props, ref) => {
const { const {
modal, modal,
portalOptions, portalOptions,
@ -133,6 +135,40 @@ export const Modal = forwardRef<HTMLDivElement, ModalProps>((props, ref) => {
...otherProps ...otherProps
} = props; } = props;
const [container, setContainer] = useState<ModalTransitionContainer | null>(
null
);
useEffect(() => {
const container = createContainer();
setContainer(container);
return () => {
setTimeout(() => {
container.remove();
}, 1000) as unknown as number;
};
}, []);
const handlePointerDownOutSide = useCallback(
(e: PointerDownOutsideEvent) => {
onPointerDownOutside?.(e);
persistent && e.preventDefault();
},
[onPointerDownOutside, persistent]
);
const handleEscapeKeyDown = useCallback(
(e: KeyboardEvent) => {
onEscapeKeyDown?.(e);
persistent && e.preventDefault();
},
[onEscapeKeyDown, persistent]
);
if (!container) {
return;
}
return ( return (
<Dialog.Root <Dialog.Root
modal={modal} modal={modal}
@ -140,7 +176,7 @@ export const Modal = forwardRef<HTMLDivElement, ModalProps>((props, ref) => {
onOpenChange={onOpenChange} onOpenChange={onOpenChange}
{...otherProps} {...otherProps}
> >
<Dialog.Portal container={prepareContainer()} {...portalOptions}> <Dialog.Portal container={container} {...portalOptions}>
<Dialog.Overlay <Dialog.Overlay
className={clsx(styles.modalOverlay, overlayClassName)} className={clsx(styles.modalOverlay, overlayClassName)}
style={{ style={{
@ -150,20 +186,8 @@ export const Modal = forwardRef<HTMLDivElement, ModalProps>((props, ref) => {
/> />
<div data-modal={modal} className={clsx(styles.modalContentWrapper)}> <div data-modal={modal} className={clsx(styles.modalContentWrapper)}>
<Dialog.Content <Dialog.Content
onPointerDownOutside={useCallback( onPointerDownOutside={handlePointerDownOutSide}
(e: PointerDownOutsideEvent) => { onEscapeKeyDown={handleEscapeKeyDown}
onPointerDownOutside?.(e);
persistent && e.preventDefault();
},
[onPointerDownOutside, persistent]
)}
onEscapeKeyDown={useCallback(
(e: KeyboardEvent) => {
onEscapeKeyDown?.(e);
persistent && e.preventDefault();
},
[onEscapeKeyDown, persistent]
)}
className={clsx(styles.modalContent, contentClassName)} className={clsx(styles.modalContent, contentClassName)}
style={{ style={{
...assignInlineVars({ ...assignInlineVars({
@ -213,6 +237,16 @@ export const Modal = forwardRef<HTMLDivElement, ModalProps>((props, ref) => {
</Dialog.Portal> </Dialog.Portal>
</Dialog.Root> </Dialog.Root>
); );
}
);
ModalInner.displayName = 'ModalInner';
export const Modal = forwardRef<HTMLDivElement, ModalProps>((props, ref) => {
if (!props.open) {
return;
}
return <ModalInner {...props} ref={ref} />;
}); });
Modal.displayName = 'Modal'; Modal.displayName = 'Modal';