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